From 6c6f5258a52188ba821af02e7eb64ea5cd841657 Mon Sep 17 00:00:00 2001 From: dicarobinho <61138287+dicarobinho@users.noreply.github.com> Date: Mon, 29 Jul 2024 13:10:38 +0300 Subject: [PATCH 001/128] =?UTF-8?q?Bugfix=20FXIOS-9454=20=E2=81=83=20Scrol?= =?UTF-8?q?ling=20when=20in=20"find=20in=20page"=20mode=20causes=20the=20a?= =?UTF-8?q?ddress=20bar=20to=20open=20(#21228)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * FXIOS-9454 #20928 ⁃ Scrolling when in "find in page" mode causes the address bar to open * FXIOS-9454 #20928 ⁃ Scrolling when in "find in page" mode causes the address bar to open Don't show the toolbar when appDidBecomeActive if we are in find in page mode --- .../BrowserViewController+FindInPage.swift | 1 + .../Views/BrowserViewController.swift | 17 +++++++-- .../Browser/TabScrollController.swift | 38 +++++++++---------- firefox-ios/Client/TabManagement/Tab.swift | 11 ++++++ firefox-ios/Shared/KeyboardHelper.swift | 18 +++++++++ 5 files changed, 63 insertions(+), 22 deletions(-) diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+FindInPage.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+FindInPage.swift index 7b0aff2dbcd4..36f1b829f433 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+FindInPage.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+FindInPage.swift @@ -13,6 +13,7 @@ extension BrowserViewController { } else { useCustomFindInteraction(isVisible: isVisible, tab: tab) } + tabManager.selectedTab?.isFindInPageMode = isVisible && isBottomSearchBar } @available(iOS 16, *) diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift index 82606206faa6..eeff6e0b685c 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift @@ -529,8 +529,10 @@ class BrowserViewController: UIViewController, self.view.sendSubviewToBack(self.webViewContainerBackdrop) }) - // Re-show toolbar which might have been hidden during scrolling (prior to app moving into the background) - scrollController.showToolbars(animated: false) + if let tab = tabManager.selectedTab, !tab.isFindInPageMode { + // Re-show toolbar which might have been hidden during scrolling (prior to app moving into the background) + scrollController.showToolbars(animated: false) + } browserDidBecomeActive() } @@ -1107,7 +1109,11 @@ class BrowserViewController: UIViewController, adjustBottomContentStackView(remake) } - adjustBottomSearchBarForKeyboard() + if let tab = tabManager.selectedTab, tab.isFindInPageMode { + scrollController.hideToolbars(animated: true, isFindInPageMode: true) + } else { + adjustBottomSearchBarForKeyboard() + } } private func adjustBottomContentStackView(_ remake: ConstraintMaker) { @@ -3638,6 +3644,11 @@ extension BrowserViewController: KeyboardHelperDelegate { finishEditionMode() } + func keyboardHelper(_ keyboardHelper: KeyboardHelper, keyboardDidHideWithState state: KeyboardState) { + tabManager.selectedTab?.setFindInPage(isBottomSearchBar: isBottomSearchBar, + doesFindInPageBarExist: findInPageBar != nil) + } + func keyboardHelper(_ keyboardHelper: KeyboardHelper, keyboardWillChangeWithState state: KeyboardState) { keyboardState = state updateViewConstraints() diff --git a/firefox-ios/Client/Frontend/Browser/TabScrollController.swift b/firefox-ios/Client/Frontend/Browser/TabScrollController.swift index fb05e6cc9fcd..c478989ed481 100644 --- a/firefox-ios/Client/Frontend/Browser/TabScrollController.swift +++ b/firefox-ios/Client/Frontend/Browser/TabScrollController.swift @@ -197,6 +197,21 @@ class TabScrollingController: NSObject, FeatureFlaggable, SearchBarLocationProvi completion: nil) } + func hideToolbars(animated: Bool, isFindInPageMode: Bool = false) { + guard toolbarState != .collapsed || isFindInPageMode else { return } + toolbarState = .collapsed + + let actualDuration = TimeInterval(ToolbarBaseAnimationDuration * hideDurationRation) + self.animateToolbarsWithOffsets( + animated, + duration: actualDuration, + headerOffset: -topScrollHeight, + bottomContainerOffset: bottomContainerScrollHeight, + overKeyboardOffset: overKeyboardScrollHeight, + alpha: 0, + completion: nil) + } + func beginObserving(scrollView: UIScrollView) { guard !observedScrollViews.contains(scrollView) else { logger.log("Duplicate observance of scroll view", level: .warning, category: .webview) @@ -252,21 +267,6 @@ class TabScrollingController: NSObject, FeatureFlaggable, SearchBarLocationProvi // MARK: - Private private extension TabScrollingController { - func hideToolbars(animated: Bool) { - guard toolbarState != .collapsed else { return } - toolbarState = .collapsed - - let actualDuration = TimeInterval(ToolbarBaseAnimationDuration * hideDurationRation) - self.animateToolbarsWithOffsets( - animated, - duration: actualDuration, - headerOffset: -topScrollHeight, - bottomContainerOffset: bottomContainerScrollHeight, - overKeyboardOffset: overKeyboardScrollHeight, - alpha: 0, - completion: nil) - } - func configureRefreshControl(isEnabled: Bool) { scrollView?.refreshControl = isEnabled ? UIRefreshControl() : nil scrollView?.refreshControl?.addTarget(self, action: #selector(reload), for: .valueChanged) @@ -459,15 +459,15 @@ extension TabScrollingController: UIScrollViewDelegate { } func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { - guard !tabIsLoading(), !isBouncingAtBottom(), isAbleToScroll else { return } + guard !tabIsLoading(), !isBouncingAtBottom(), isAbleToScroll, let tab else { return } - tab?.shouldScrollToTop = false + tab.shouldScrollToTop = false if decelerate || (toolbarState == .animating && !decelerate) { - if scrollDirection == .up { + if scrollDirection == .up, !tab.isFindInPageMode { showToolbars(animated: true) } else if scrollDirection == .down { - hideToolbars(animated: true) + hideToolbars(animated: true, isFindInPageMode: tab.isFindInPageMode) } } } diff --git a/firefox-ios/Client/TabManagement/Tab.swift b/firefox-ios/Client/TabManagement/Tab.swift index 8fa8b950b6ce..c5e3dec17d38 100644 --- a/firefox-ios/Client/TabManagement/Tab.swift +++ b/firefox-ios/Client/TabManagement/Tab.swift @@ -127,6 +127,7 @@ class Tab: NSObject, ThemeApplicable { var adsProviderName: String = "" var hasHomeScreenshot = false var shouldScrollToTop = false + var isFindInPageMode = false private var logger: Logger @@ -771,6 +772,16 @@ class Tab: NSObject, ThemeApplicable { bars.reversed().filter({ $0.snackbarClassIdentifier == snackbarClass }).forEach({ removeSnackbar($0) }) } + func setFindInPage(isBottomSearchBar: Bool, doesFindInPageBarExist: Bool) { + if #available(iOS 16, *) { + guard let webView = self.webView, + let findInteraction = webView.findInteraction else { return } + isFindInPageMode = findInteraction.isFindNavigatorVisible && isBottomSearchBar + } else { + isFindInPageMode = doesFindInPageBarExist && isBottomSearchBar + } + } + func setScreenshot(_ screenshot: UIImage?) { self.screenshot = screenshot } diff --git a/firefox-ios/Shared/KeyboardHelper.swift b/firefox-ios/Shared/KeyboardHelper.swift index 6084a6164b42..1fb7c30ebc0b 100644 --- a/firefox-ios/Shared/KeyboardHelper.swift +++ b/firefox-ios/Shared/KeyboardHelper.swift @@ -46,12 +46,14 @@ public protocol KeyboardHelperDelegate: AnyObject { func keyboardHelper(_ keyboardHelper: KeyboardHelper, keyboardWillHideWithState state: KeyboardState) func keyboardHelper(_ keyboardHelper: KeyboardHelper, keyboardWillChangeWithState state: KeyboardState) func keyboardHelper(_ keyboardHelper: KeyboardHelper, keyboardDidChangeWithState state: KeyboardState) + func keyboardHelper(_ keyboardHelper: KeyboardHelper, keyboardDidHideWithState state: KeyboardState) } public extension KeyboardHelperDelegate { func keyboardHelper(_ keyboardHelper: KeyboardHelper, keyboardDidShowWithState state: KeyboardState) {} func keyboardHelper(_ keyboardHelper: KeyboardHelper, keyboardWillChangeWithState state: KeyboardState) {} func keyboardHelper(_ keyboardHelper: KeyboardHelper, keyboardDidChangeWithState state: KeyboardState) {} + func keyboardHelper(_ keyboardHelper: KeyboardHelper, keyboardDidHideWithState state: KeyboardState) {} } /** @@ -91,6 +93,12 @@ open class KeyboardHelper: NSObject { name: UIResponder.keyboardWillHideNotification, object: nil ) + NotificationCenter.default.addObserver( + self, + selector: #selector(keyboardDidHide), + name: UIResponder.keyboardDidHideNotification, + object: nil + ) NotificationCenter.default.addObserver( self, selector: #selector(keyboardDidChange), @@ -153,6 +161,16 @@ open class KeyboardHelper: NSObject { } } + @objc + private func keyboardDidHide(_ notification: Notification) { + if let userInfo = notification.userInfo { + for weakDelegate in delegates { + weakDelegate.delegate?.keyboardHelper(self, + keyboardDidHideWithState: KeyboardState(userInfo)) + } + } + } + @objc private func keyboardWillChange(_ notification: Notification) { if let userInfo = notification.userInfo { From e36283070cae1f35c6e670be6f75e06b1c196989 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 15:19:57 +0200 Subject: [PATCH 002/128] Firefox Localize [v130] String import 2024-07-29 (#21320) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- firefox-ios/Client.xcodeproj/project.pbxproj | 156 ++++++++++++++++++ .../bs.lproj/EditAddress.strings | 51 ++++++ .../EnhancedTrackingProtection.strings | 12 ++ .../bs.lproj/Microsurvey.strings | 6 + .../bs.lproj/PasswordAutofill.strings | 3 + .../bs.lproj/ScanQRCode.strings | 9 + .../Supporting Files/bs.lproj/Toolbar.strings | 3 + .../co.lproj/EditAddress.strings | 141 ++++++++++++++++ .../EnhancedTrackingProtection.strings | 12 ++ .../co.lproj/PasswordAutofill.strings | 3 + .../co.lproj/ScanQRCode.strings | 9 + .../co.lproj/Shopping.strings | 4 +- .../Supporting Files/co.lproj/Toolbar.strings | 3 + .../cs.lproj/EditAddress.strings | 18 ++ .../EnhancedTrackingProtection.strings | 12 ++ .../cs.lproj/PasswordAutofill.strings | 3 + .../cs.lproj/ScanQRCode.strings | 9 + .../Supporting Files/cs.lproj/Toolbar.strings | 3 + .../cy.lproj/EditAddress.strings | 3 + .../cy.lproj/PasswordAutofill.strings | 3 + .../cy.lproj/ScanQRCode.strings | 9 + .../da.lproj/EditAddress.strings | 141 ++++++++++++++++ .../EnhancedTrackingProtection.strings | 12 ++ .../da.lproj/PasswordAutofill.strings | 3 + .../da.lproj/ScanQRCode.strings | 9 + .../Supporting Files/da.lproj/Toolbar.strings | 3 + .../de.lproj/EditAddress.strings | 3 + .../Supporting Files/de.lproj/Toolbar.strings | 3 + .../dsb.lproj/EditAddress.strings | 3 + .../dsb.lproj/Toolbar.strings | 3 + .../el.lproj/EditAddress.strings | 3 + .../Supporting Files/el.lproj/Toolbar.strings | 3 + .../en-CA.lproj/EditAddress.strings | 3 + .../en-CA.lproj/Toolbar.strings | 3 + .../en-GB.lproj/EditAddress.strings | 3 + .../en-GB.lproj/Toolbar.strings | 3 + .../en-US.lproj/EditAddress.strings | 3 + .../en-US.lproj/Toolbar.strings | 3 + .../es-AR.lproj/EditAddress.strings | 3 + .../es-AR.lproj/Toolbar.strings | 3 + .../es-CL.lproj/EditAddress.strings | 3 + .../es-CL.lproj/Toolbar.strings | 3 + .../es-MX.lproj/ActivityStream.strings | 6 + .../es-MX.lproj/Alerts.strings | 3 + .../es-MX.lproj/CustomizeFirefoxHome.strings | 3 + .../es-MX.lproj/EditAddress.strings | 36 ++++ .../EnhancedTrackingProtection.strings | 3 + .../es-MX.lproj/Microsurvey.strings | 15 ++ .../es-MX.lproj/Onboarding.strings | 9 + .../es-MX.lproj/PasswordAutofill.strings | 3 + .../es-MX.lproj/RememberCard.strings | 6 + .../es-MX.lproj/ScanQRCode.strings | 3 + .../es-MX.lproj/SelectCreditCard.strings | 3 + .../es-MX.lproj/Settings.strings | 33 ++++ .../es-MX.lproj/Shopping.strings | 15 ++ .../es-MX.lproj/TabLocation.strings | 15 ++ .../es-MX.lproj/TabsTray.strings | 6 + .../es-MX.lproj/Toolbar.strings | 3 + .../es-MX.lproj/UpdateCard.strings | 6 + .../fi.lproj/EditAddress.strings | 3 + .../fi.lproj/Shopping.strings | 9 + .../Supporting Files/fi.lproj/Toolbar.strings | 3 + .../fr.lproj/EditAddress.strings | 3 + .../Supporting Files/fr.lproj/Toolbar.strings | 3 + .../he.lproj/EditAddress.strings | 3 + .../Supporting Files/he.lproj/Toolbar.strings | 3 + .../hsb.lproj/EditAddress.strings | 3 + .../hsb.lproj/Toolbar.strings | 3 + .../hy-AM.lproj/EditAddress.strings | 3 + .../hy-AM.lproj/Toolbar.strings | 3 + .../ia.lproj/EditAddress.strings | 3 + .../Supporting Files/ia.lproj/Toolbar.strings | 3 + .../is.lproj/EditAddress.strings | 3 + .../Supporting Files/is.lproj/Toolbar.strings | 3 + .../it.lproj/EditAddress.strings | 3 + .../Supporting Files/it.lproj/Toolbar.strings | 3 + .../ja.lproj/EditAddress.strings | 141 ++++++++++++++++ .../EnhancedTrackingProtection.strings | 12 ++ .../ja.lproj/PasswordAutofill.strings | 3 + .../ja.lproj/ScanQRCode.strings | 9 + .../Supporting Files/ja.lproj/Toolbar.strings | 3 + .../kab.lproj/EditAddress.strings | 3 + .../kab.lproj/Shopping.strings | 33 ++++ .../kab.lproj/Toolbar.strings | 3 + .../kk.lproj/EditAddress.strings | 3 + .../Supporting Files/kk.lproj/Toolbar.strings | 3 + .../ko.lproj/EditAddress.strings | 3 + .../Supporting Files/ko.lproj/Toolbar.strings | 3 + .../nb.lproj/EditAddress.strings | 126 ++++++++++++++ .../nl.lproj/EditAddress.strings | 3 + .../Supporting Files/nl.lproj/Toolbar.strings | 3 + .../Supporting Files/nn.lproj/Alerts.strings | 2 +- .../nn.lproj/EditAddress.strings | 3 + .../Supporting Files/nn.lproj/Toolbar.strings | 3 + .../pa-IN.lproj/EditAddress.strings | 3 + .../pa-IN.lproj/Toolbar.strings | 3 + .../pl.lproj/EditAddress.strings | 141 ++++++++++++++++ .../EnhancedTrackingProtection.strings | 12 ++ .../pl.lproj/PasswordAutofill.strings | 3 + .../pl.lproj/ScanQRCode.strings | 9 + .../Supporting Files/pl.lproj/Toolbar.strings | 3 + .../pt-BR.lproj/EditAddress.strings | 3 + .../pt-BR.lproj/Toolbar.strings | 3 + .../pt-PT.lproj/EditAddress.strings | 15 +- .../EnhancedTrackingProtection.strings | 2 +- .../pt-PT.lproj/ScanQRCode.strings | 2 +- .../pt-PT.lproj/Toolbar.strings | 3 + .../rm.lproj/EditAddress.strings | 3 + .../Supporting Files/rm.lproj/Toolbar.strings | 3 + .../ru.lproj/EditAddress.strings | 3 + .../Supporting Files/ru.lproj/Toolbar.strings | 3 + .../sat-Olck.lproj/Credentials.strings | 6 + .../CustomizeFirefoxHome.strings | 3 + .../sat-Olck.lproj/Edit Card.strings | 2 +- .../sat-Olck.lproj/EditAddress.strings | 138 ++++++++++++++++ .../si.lproj/EditAddress.strings | 90 ++++++++++ .../si.lproj/ResearchSurface.strings | 2 +- .../sk.lproj/EditAddress.strings | 3 + .../Supporting Files/sk.lproj/Toolbar.strings | 3 + .../sl.lproj/EditAddress.strings | 6 + .../sl.lproj/ScanQRCode.strings | 9 + .../sl.lproj/Settings.strings | 6 + .../Supporting Files/sl.lproj/Toolbar.strings | 3 + .../sq.lproj/EditAddress.strings | 3 + .../EnhancedTrackingProtection.strings | 3 + .../Supporting Files/sq.lproj/Toolbar.strings | 3 + .../sv.lproj/EditAddress.strings | 7 +- .../EnhancedTrackingProtection.strings | 2 +- .../sv.lproj/ScanQRCode.strings | 2 +- .../Supporting Files/sv.lproj/Toolbar.strings | 3 + .../th.lproj/ActivityStream.strings | 6 + .../th.lproj/AddressToolbar.strings | 12 ++ .../th.lproj/CustomizeFirefoxHome.strings | 3 + .../th.lproj/EditAddress.strings | 141 ++++++++++++++++ .../EnhancedTrackingProtection.strings | 71 ++++++++ .../th.lproj/Microsurvey.strings | 21 +++ .../th.lproj/PasswordAutofill.strings | 3 + .../Supporting Files/th.lproj/QRCode.strings | 3 + .../th.lproj/ScanQRCode.strings | 9 + .../Supporting Files/th.lproj/Toolbar.strings | 3 + .../tr.lproj/EditAddress.strings | 3 + .../Supporting Files/tr.lproj/Toolbar.strings | 3 + .../ug.lproj/EditAddress.strings | 3 + .../Supporting Files/ug.lproj/Toolbar.strings | 3 + .../vi.lproj/EditAddress.strings | 3 + .../Supporting Files/vi.lproj/Toolbar.strings | 3 + .../zh-CN.lproj/EditAddress.strings | 3 + .../zh-CN.lproj/Toolbar.strings | 3 + .../zh-TW.lproj/EditAddress.strings | 3 + .../zh-TW.lproj/Toolbar.strings | 3 + .../Shared/dsb.lproj/Localizable.strings | 8 +- .../Shared/dsb.lproj/LoginManager.strings | 2 +- .../Shared/es-MX.lproj/Localizable.strings | 3 + firefox-ios/Shared/es-MX.lproj/Menu.strings | 3 + .../Shared/nb.lproj/Localizable.strings | 3 + firefox-ios/Shared/nb.lproj/Menu.strings | 6 + .../Shared/si.lproj/Localizable.strings | 6 +- .../Shared/si.lproj/LoginManager.strings | 2 +- .../Shared/th.lproj/Localizable.strings | 9 + firefox-ios/Shared/th.lproj/Menu.strings | 6 + 160 files changed, 2104 insertions(+), 26 deletions(-) create mode 100644 firefox-ios/Shared/Supporting Files/bs.lproj/ScanQRCode.strings create mode 100644 firefox-ios/Shared/Supporting Files/bs.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/co.lproj/EditAddress.strings create mode 100644 firefox-ios/Shared/Supporting Files/co.lproj/ScanQRCode.strings create mode 100644 firefox-ios/Shared/Supporting Files/co.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/cs.lproj/ScanQRCode.strings create mode 100644 firefox-ios/Shared/Supporting Files/cs.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/cy.lproj/ScanQRCode.strings create mode 100644 firefox-ios/Shared/Supporting Files/da.lproj/EditAddress.strings create mode 100644 firefox-ios/Shared/Supporting Files/da.lproj/ScanQRCode.strings create mode 100644 firefox-ios/Shared/Supporting Files/da.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/de.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/dsb.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/el.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/en-CA.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/en-GB.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/en-US.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/es-AR.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/es-CL.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/es-MX.lproj/ActivityStream.strings create mode 100644 firefox-ios/Shared/Supporting Files/es-MX.lproj/EditAddress.strings create mode 100644 firefox-ios/Shared/Supporting Files/es-MX.lproj/EnhancedTrackingProtection.strings create mode 100644 firefox-ios/Shared/Supporting Files/es-MX.lproj/Microsurvey.strings create mode 100644 firefox-ios/Shared/Supporting Files/es-MX.lproj/ScanQRCode.strings create mode 100644 firefox-ios/Shared/Supporting Files/es-MX.lproj/SelectCreditCard.strings create mode 100644 firefox-ios/Shared/Supporting Files/es-MX.lproj/TabLocation.strings create mode 100644 firefox-ios/Shared/Supporting Files/es-MX.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/es-MX.lproj/UpdateCard.strings create mode 100644 firefox-ios/Shared/Supporting Files/fi.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/fr.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/he.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/hsb.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/hy-AM.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/ia.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/is.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/it.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/ja.lproj/EditAddress.strings create mode 100644 firefox-ios/Shared/Supporting Files/ja.lproj/ScanQRCode.strings create mode 100644 firefox-ios/Shared/Supporting Files/ja.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/kab.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/kk.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/ko.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/nb.lproj/EditAddress.strings create mode 100644 firefox-ios/Shared/Supporting Files/nl.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/nn.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/pa-IN.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/pl.lproj/EditAddress.strings create mode 100644 firefox-ios/Shared/Supporting Files/pl.lproj/ScanQRCode.strings create mode 100644 firefox-ios/Shared/Supporting Files/pl.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/pt-BR.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/pt-PT.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/rm.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/ru.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/sat-Olck.lproj/Credentials.strings create mode 100644 firefox-ios/Shared/Supporting Files/sat-Olck.lproj/EditAddress.strings create mode 100644 firefox-ios/Shared/Supporting Files/si.lproj/EditAddress.strings create mode 100644 firefox-ios/Shared/Supporting Files/sk.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/sl.lproj/ScanQRCode.strings create mode 100644 firefox-ios/Shared/Supporting Files/sl.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/sq.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/sv.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/th.lproj/ActivityStream.strings create mode 100644 firefox-ios/Shared/Supporting Files/th.lproj/AddressToolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/th.lproj/EditAddress.strings create mode 100644 firefox-ios/Shared/Supporting Files/th.lproj/EnhancedTrackingProtection.strings create mode 100644 firefox-ios/Shared/Supporting Files/th.lproj/QRCode.strings create mode 100644 firefox-ios/Shared/Supporting Files/th.lproj/ScanQRCode.strings create mode 100644 firefox-ios/Shared/Supporting Files/th.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/tr.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/ug.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/vi.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/zh-CN.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/zh-TW.lproj/Toolbar.strings diff --git a/firefox-ios/Client.xcodeproj/project.pbxproj b/firefox-ios/Client.xcodeproj/project.pbxproj index 5265db2b4737..36207b6eb4f0 100644 --- a/firefox-ios/Client.xcodeproj/project.pbxproj +++ b/firefox-ios/Client.xcodeproj/project.pbxproj @@ -423,6 +423,7 @@ 43DF945A292258C300590FE3 /* SearchHeaderTitle.strings in Resources */ = {isa = PBXBuildFile; fileRef = 43DF9458292258C300590FE3 /* SearchHeaderTitle.strings */; }; 43E69EC3254D081D00B591C2 /* SimpleTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43E69EAF254D064E00B591C2 /* SimpleTab.swift */; }; 43E69ED7254D081F00B591C2 /* SimpleTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43E69EAF254D064E00B591C2 /* SimpleTab.swift */; }; + 43E6BE162C57AF7600C2152C /* Toolbar.strings in Resources */ = {isa = PBXBuildFile; fileRef = 43E6BE142C57AF7600C2152C /* Toolbar.strings */; }; 43F119002A52E42400C44C6C /* CustomizeFirefoxHome.strings in Resources */ = {isa = PBXBuildFile; fileRef = 43F118FE2A52E42400C44C6C /* CustomizeFirefoxHome.strings */; }; 43F7952525795F69005AEE40 /* SearchTelemetry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43F7952425795F69005AEE40 /* SearchTelemetry.swift */; }; 43F92B3829E9F52B000C0F17 /* AutofillAllFramesAtDocumentStart.js in Resources */ = {isa = PBXBuildFile; fileRef = 43F92B3729E9F52B000C0F17 /* AutofillAllFramesAtDocumentStart.js */; }; @@ -2824,6 +2825,15 @@ 42CC4F75B4E9E31A4754A9FE /* az */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = az; path = az.lproj/3DTouchActions.strings; sourceTree = ""; }; 42D84A3EBD583A4797682E74 /* ia */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ia; path = ia.lproj/PrivateBrowsing.strings; sourceTree = ""; }; 430057C029E4293100FE51CA /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = "uk.lproj/Edit Card.strings"; sourceTree = ""; }; + 4300B0D92C57B06E00F609C1 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/ActivityStream.strings"; sourceTree = ""; }; + 4300B0DA2C57B06E00F609C1 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/EditAddress.strings"; sourceTree = ""; }; + 4300B0DB2C57B06E00F609C1 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/EnhancedTrackingProtection.strings"; sourceTree = ""; }; + 4300B0DC2C57B06E00F609C1 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/Microsurvey.strings"; sourceTree = ""; }; + 4300B0DD2C57B06E00F609C1 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/ScanQRCode.strings"; sourceTree = ""; }; + 4300B0DE2C57B06E00F609C1 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/SelectCreditCard.strings"; sourceTree = ""; }; + 4300B0DF2C57B06E00F609C1 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/TabLocation.strings"; sourceTree = ""; }; + 4300B0E02C57B06E00F609C1 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/Toolbar.strings"; sourceTree = ""; }; + 4300B0E12C57B06E00F609C1 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/UpdateCard.strings"; sourceTree = ""; }; 4300B70A2C298D9C0099DEEC /* lo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = lo; path = lo.lproj/ActivityStream.strings; sourceTree = ""; }; 4300B70B2C298D9C0099DEEC /* lo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = lo; path = lo.lproj/EnhancedTrackingProtection.strings; sourceTree = ""; }; 4300B70C2C298D9C0099DEEC /* lo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = lo; path = lo.lproj/LoginsHelper.strings; sourceTree = ""; }; @@ -2926,6 +2936,7 @@ 430405402C298AEC00EB6E76 /* cy */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cy; path = cy.lproj/QRCode.strings; sourceTree = ""; }; 43041686293E0B3100BBFD8A /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/Alerts.strings; sourceTree = ""; }; 43041687293E0B3100BBFD8A /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/TabsTray.strings; sourceTree = ""; }; + 430439F42C57B34D005518C3 /* nn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nn; path = nn.lproj/Toolbar.strings; sourceTree = ""; }; 43045C9729E428A800B5BD9B /* si */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = si; path = si.lproj/Alert.strings; sourceTree = ""; }; 43045C9829E428A800B5BD9B /* si */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = si; path = "si.lproj/Edit Card.strings"; sourceTree = ""; }; 43045C9929E428A800B5BD9B /* si */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = si; path = si.lproj/EditCard.strings; sourceTree = ""; }; @@ -2975,9 +2986,11 @@ 430A4A422A0BCCB0009D4128 /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/Upgrade.strings; sourceTree = ""; }; 430AA4CE29FFD516005AB95C /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Onboarding.strings; sourceTree = ""; }; 430AA4CF29FFD516005AB95C /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/ResearchSurface.strings; sourceTree = ""; }; + 430ADCC62C57B00800B0A55B /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/Toolbar.strings"; sourceTree = ""; }; 430B5C042C20544900652135 /* sl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sl; path = sl.lproj/ActivityStream.strings; sourceTree = ""; }; 430B5C052C20544900652135 /* sl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sl; path = sl.lproj/AddressToolbar.strings; sourceTree = ""; }; 430B5C062C20544900652135 /* sl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sl; path = sl.lproj/EnhancedTrackingProtection.strings; sourceTree = ""; }; + 430B81E02C57B198008C994B /* ia */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ia; path = ia.lproj/Toolbar.strings; sourceTree = ""; }; 430B8F7A2AC1A2B500CDB6CC /* ia */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ia; path = ia.lproj/Share.strings; sourceTree = ""; }; 430B8F7B2AC1A2B500CDB6CC /* ia */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ia; path = ia.lproj/TabLocation.strings; sourceTree = ""; }; 430B9F052A24C0E200DC4B8E /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/DisplayCard.strings; sourceTree = ""; }; @@ -3078,6 +3091,7 @@ 4314C48E2C2051D0009E4D70 /* hsb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hsb; path = hsb.lproj/AddressToolbar.strings; sourceTree = ""; }; 4314C48F2C2051D0009E4D70 /* hsb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hsb; path = hsb.lproj/EnhancedTrackingProtection.strings; sourceTree = ""; }; 4314C4902C2051D0009E4D70 /* hsb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hsb; path = hsb.lproj/QRCode.strings; sourceTree = ""; }; + 4315028A2C57B23B005BB18E /* kk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kk; path = kk.lproj/Toolbar.strings; sourceTree = ""; }; 4315209A29BA68CF00D729C1 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/EngagementNotification.strings; sourceTree = ""; }; 4315209B29BA68CF00D729C1 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/Onboarding.strings; sourceTree = ""; }; 4315209C29BA68CF00D729C1 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/ResearchSurface.strings; sourceTree = ""; }; @@ -3127,6 +3141,7 @@ 43177EC82A49A96800A22B9C /* eo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eo; path = eo.lproj/Upgrade.strings; sourceTree = ""; }; 4317873D2A655B9100A38B47 /* zh-CN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-CN"; path = "zh-CN.lproj/SelectCreditCard.strings"; sourceTree = ""; }; 4317CE012B0B76F500BD4D5B /* hsb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hsb; path = hsb.lproj/FirefoxHomepage.strings; sourceTree = ""; }; + 431813AE2C57B017007C3268 /* en-US */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-US"; path = "en-US.lproj/Toolbar.strings"; sourceTree = ""; }; 43183D2F293E0C44009F788D /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Alerts.strings"; sourceTree = ""; }; 43183D30293E0C44009F788D /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/TabsTray.strings"; sourceTree = ""; }; 431853AA2A0911440099B0E0 /* gl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = gl; path = "gl.lproj/Default Browser.strings"; sourceTree = ""; }; @@ -3194,6 +3209,7 @@ 431D38832A49AADF00A8BE49 /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/UpdateCard.strings; sourceTree = ""; }; 431D44862AEFC97A00B92311 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Shopping.strings; sourceTree = ""; }; 431D65DB292B94F800BB9A90 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/SearchHeaderTitle.strings; sourceTree = ""; }; + 431D82792C57B3F600062D71 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Toolbar.strings; sourceTree = ""; }; 431DACF12A24BF0C00D7CE85 /* en-US */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-US"; path = "en-US.lproj/DisplayCard.strings"; sourceTree = ""; }; 431DE38F2B023BC600BF06E3 /* eo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eo; path = eo.lproj/Shopping.strings; sourceTree = ""; }; 431DF6C52C20532100ADD05A /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/ActivityStream.strings; sourceTree = ""; }; @@ -3238,6 +3254,7 @@ 4320E17E2A16E5A9009A4B5F /* CreditCardExtras.ios.mjs */ = {isa = PBXFileReference; lastKnownFileType = text; path = CreditCardExtras.ios.mjs; sourceTree = ""; }; 43211DCD2C3C045A00E4CA4D /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/EditAddress.strings; sourceTree = ""; }; 43211DCE2C3C045A00E4CA4D /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/ScanQRCode.strings; sourceTree = ""; }; + 43211E6B2C57B11F003F9FAF /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = he.lproj/Toolbar.strings; sourceTree = ""; }; 4321FAB82B8CA9A70046DCA0 /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/KeyboardAccessory.strings; sourceTree = ""; }; 4321FAB92B8CA9A70046DCA0 /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/PasswordAutofill.strings; sourceTree = ""; }; 4322680229225CA3008F8C47 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/SearchHeaderTitle.strings; sourceTree = ""; }; @@ -3324,6 +3341,8 @@ 4328FAD229D1B35100DABB9A /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/SnackBar.strings; sourceTree = ""; }; 4329591628D8852300D8BC68 /* eo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eo; path = eo.lproj/JumpBackIn.strings; sourceTree = ""; }; 4329591728D8852400D8BC68 /* eo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eo; path = eo.lproj/ToolbarLocation.strings; sourceTree = ""; }; + 432985492C57B47B00FE7CA2 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Toolbar.strings; sourceTree = ""; }; + 4329BDC32C57B1BF007F18C7 /* is */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = is; path = is.lproj/Toolbar.strings; sourceTree = ""; }; 432A14A0292B93900059D21F /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/SearchHeaderTitle.strings; sourceTree = ""; }; 432A50F52B14B165003EE621 /* kab */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kab; path = kab.lproj/FirefoxHomepage.strings; sourceTree = ""; }; 432A91F328B39EAE006CE202 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/JumpBackIn.strings"; sourceTree = ""; }; @@ -3391,6 +3410,8 @@ 432FFF5B2C2051FC00ADC8E7 /* ia */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ia; path = ia.lproj/AddressToolbar.strings; sourceTree = ""; }; 432FFF5C2C2051FC00ADC8E7 /* ia */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ia; path = ia.lproj/EnhancedTrackingProtection.strings; sourceTree = ""; }; 432FFF5D2C2051FC00ADC8E7 /* ia */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ia; path = ia.lproj/QRCode.strings; sourceTree = ""; }; + 433020F72C57B40600AF5EE2 /* sat-Olck */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "sat-Olck"; path = "sat-Olck.lproj/Credentials.strings"; sourceTree = ""; }; + 433020F82C57B40700AF5EE2 /* sat-Olck */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "sat-Olck"; path = "sat-Olck.lproj/EditAddress.strings"; sourceTree = ""; }; 4330773429F69CC7006BC636 /* pa-IN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pa-IN"; path = "pa-IN.lproj/Notification.strings"; sourceTree = ""; }; 4330773529F69CC7006BC636 /* pa-IN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pa-IN"; path = "pa-IN.lproj/ZoomPageBar.strings"; sourceTree = ""; }; 4330958B2B83917C00FAD61B /* hsb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hsb; path = hsb.lproj/KeyboardAccessory.strings; sourceTree = ""; }; @@ -3424,6 +3445,7 @@ 433204162B68010A00ECE7AC /* bs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bs; path = bs.lproj/TabToolbar.strings; sourceTree = ""; }; 4332247E2A5C203D00B07818 /* pa-IN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pa-IN"; path = "pa-IN.lproj/CustomizeFirefoxHome.strings"; sourceTree = ""; }; 4332247F2A5C203D00B07818 /* pa-IN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pa-IN"; path = "pa-IN.lproj/SelectCreditCard.strings"; sourceTree = ""; }; + 43328A002C57B38800444F7E /* pa-IN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pa-IN"; path = "pa-IN.lproj/Toolbar.strings"; sourceTree = ""; }; 4332AE0B2B305F6200885C18 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/ContextualHints.strings; sourceTree = ""; }; 4332AE0C2B305F6200885C18 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/CredentialProvider.strings; sourceTree = ""; }; 4332AE0D2B305F6200885C18 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Credentials.strings; sourceTree = ""; }; @@ -3478,6 +3500,9 @@ 4337C9D62A5C211300987DEB /* tt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tt; path = tt.lproj/SelectCreditCard.strings; sourceTree = ""; }; 4337C9D72A5C211300987DEB /* tt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tt; path = tt.lproj/UpdateCard.strings; sourceTree = ""; }; 4337E1142AEFC993007579AC /* zh-CN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-CN"; path = "zh-CN.lproj/Shopping.strings"; sourceTree = ""; }; + 43383DE92C57AF94001BCD0E /* co */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = co; path = co.lproj/EditAddress.strings; sourceTree = ""; }; + 43383DEA2C57AF94001BCD0E /* co */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = co; path = co.lproj/ScanQRCode.strings; sourceTree = ""; }; + 43383DEB2C57AF94001BCD0E /* co */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = co; path = co.lproj/Toolbar.strings; sourceTree = ""; }; 4338633128CF4C5100564CA4 /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/JumpBackIn.strings; sourceTree = ""; }; 4338633228CF4C5100564CA4 /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/ToolbarLocation.strings; sourceTree = ""; }; 4338F50C2C453D8800851075 /* rm */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = rm; path = rm.lproj/EditAddress.strings; sourceTree = ""; }; @@ -3488,6 +3513,7 @@ 4339390B28B39F8F001B8301 /* fil */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fil; path = fil.lproj/BookmarkPanel.strings; sourceTree = ""; }; 433942802AC1A24E009B3F3C /* gl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = gl; path = gl.lproj/Share.strings; sourceTree = ""; }; 433942812AC1A24E009B3F3C /* gl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = gl; path = gl.lproj/TabLocation.strings; sourceTree = ""; }; + 433954F62C57B0A900EC1EAE /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/Toolbar.strings; sourceTree = ""; }; 4339D0B32BA85A7400521234 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/BottomSheet.strings"; sourceTree = ""; }; 4339E2A02A49A9250071F5CF /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/Footer.strings; sourceTree = ""; }; 4339E2A12A49A9250071F5CF /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/RememberCard.strings; sourceTree = ""; }; @@ -3668,6 +3694,7 @@ 434E1FDD299A549B00F79A7B /* fil */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fil; path = fil.lproj/Localizable.strings; sourceTree = ""; }; 434E733625EED32E006D3BDE /* BrowserViewController+URLBarDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BrowserViewController+URLBarDelegate.swift"; sourceTree = ""; }; 434EA84429225CDE0039FBE1 /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/SearchHeaderTitle.strings; sourceTree = ""; }; + 434ED7EC2C57B1D4000C86E4 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Toolbar.strings; sourceTree = ""; }; 434EE0B429225A31005D030A /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/SearchHeaderTitle.strings"; sourceTree = ""; }; 434F05982A0BCD36008B1057 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/FirefoxSync.strings; sourceTree = ""; }; 434F05992A0BCD36008B1057 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Upgrade.strings; sourceTree = ""; }; @@ -3741,6 +3768,7 @@ 43569A322A0BCB0E00BCDA77 /* es-AR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-AR"; path = "es-AR.lproj/Upgrade.strings"; sourceTree = ""; }; 4356A5C82BE8F2C300A39580 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Microsurvey.strings; sourceTree = ""; }; 4356DB4F2AEFC6FF00ADF289 /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/Shopping.strings; sourceTree = ""; }; + 43571C312C57B52200A2DD89 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Toolbar.strings; sourceTree = ""; }; 43571D57293E0A2000EF42C5 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/Alerts.strings; sourceTree = ""; }; 43571D58293E0A2000EF42C5 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/TabsTray.strings; sourceTree = ""; }; 435784DC2A24C0C80046746E /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/DisplayCard.strings"; sourceTree = ""; }; @@ -3785,6 +3813,8 @@ 435A759129E4285900778D0C /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Edit Card.strings"; sourceTree = ""; }; 435AC01A2A52E65800B0156A /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/CustomizeFirefoxHome.strings; sourceTree = ""; }; 435AC01B2A52E65800B0156A /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/SelectCreditCard.strings; sourceTree = ""; }; + 435B35652C57AFA200F1C0BE /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/ScanQRCode.strings; sourceTree = ""; }; + 435B35662C57AFA200F1C0BE /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Toolbar.strings; sourceTree = ""; }; 435B625129D1B3D2005FBA5D /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Alert.strings; sourceTree = ""; }; 435B625229D1B3D2005FBA5D /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/BiometricAuthentication.strings; sourceTree = ""; }; 435B625329D1B3D2005FBA5D /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/EditCard.strings; sourceTree = ""; }; @@ -3957,6 +3987,7 @@ 4366A0B429DAEDF500DA8329 /* rm */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = rm; path = rm.lproj/ResearchSurface.strings; sourceTree = ""; }; 4366A0B529DAEDF500DA8329 /* rm */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = rm; path = rm.lproj/Settings.strings; sourceTree = ""; }; 4366A0B629DAEDF500DA8329 /* rm */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = rm; path = rm.lproj/SnackBar.strings; sourceTree = ""; }; + 436705DA2C57B3D7002C7FE6 /* rm */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = rm; path = rm.lproj/Toolbar.strings; sourceTree = ""; }; 43680DD7293E0A160013269F /* cy */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cy; path = cy.lproj/Alerts.strings; sourceTree = ""; }; 43680DD8293E0A160013269F /* cy */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cy; path = cy.lproj/TabsTray.strings; sourceTree = ""; }; 43682B4D28B39CFF00F2C865 /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/JumpBackIn.strings; sourceTree = ""; }; @@ -3976,6 +4007,7 @@ 4368ED3A28B39C1300A50B64 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/JumpBackIn.strings"; sourceTree = ""; }; 4368ED3B28B39C1300A50B64 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/ToolbarLocation.strings"; sourceTree = ""; }; 4368EE5B292B95C0005A0673 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/SearchHeaderTitle.strings; sourceTree = ""; }; + 436957A82C57AFB100B079FE /* cy */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cy; path = cy.lproj/ScanQRCode.strings; sourceTree = ""; }; 43696A66292B9719002C3EAD /* zh-CN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-CN"; path = "zh-CN.lproj/SearchHeaderTitle.strings"; sourceTree = ""; }; 436985E428B39FFE00198055 /* zh-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-TW"; path = "zh-TW.lproj/JumpBackIn.strings"; sourceTree = ""; }; 436985E528B39FFE00198055 /* zh-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-TW"; path = "zh-TW.lproj/ToolbarLocation.strings"; sourceTree = ""; }; @@ -4162,6 +4194,9 @@ 4378BD402B14B2C5004CB18D /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/FirefoxHomepage.strings; sourceTree = ""; }; 4378C733293E09C200D0C1C7 /* be */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = be; path = be.lproj/Alerts.strings; sourceTree = ""; }; 4378C736293E09C200D0C1C7 /* be */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = be; path = be.lproj/TabsTray.strings; sourceTree = ""; }; + 4378EFA72C57AFBF0031897A /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/EditAddress.strings; sourceTree = ""; }; + 4378EFA82C57AFBF0031897A /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/ScanQRCode.strings; sourceTree = ""; }; + 4378EFA92C57AFBF0031897A /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/Toolbar.strings; sourceTree = ""; }; 4378F1B329BA6AD200D37BDC /* lo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = lo; path = lo.lproj/EngagementNotification.strings; sourceTree = ""; }; 4378F1B429BA6AD200D37BDC /* lo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = lo; path = lo.lproj/Onboarding.strings; sourceTree = ""; }; 4378F1B529BA6AD200D37BDC /* lo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = lo; path = lo.lproj/ResearchSurface.strings; sourceTree = ""; }; @@ -4173,6 +4208,7 @@ 43790BF4292B94C500968A85 /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/SearchHeaderTitle.strings; sourceTree = ""; }; 4379F313293E0A5A0029C76D /* en-US */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-US"; path = "en-US.lproj/Alerts.strings"; sourceTree = ""; }; 4379F314293E0A5A0029C76D /* en-US */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-US"; path = "en-US.lproj/TabsTray.strings"; sourceTree = ""; }; + 437A0B5A2C57B22500FCF751 /* kab */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kab; path = kab.lproj/Toolbar.strings; sourceTree = ""; }; 437A857727E43FE100E42764 /* FxAWebViewTelemetry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FxAWebViewTelemetry.swift; sourceTree = ""; }; 437A88922C2054C100031657 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/EnhancedTrackingProtection.strings; sourceTree = ""; }; 437A88932C2054C100031657 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/QRCode.strings; sourceTree = ""; }; @@ -4244,6 +4280,13 @@ 437E34352C3C03870025BFA9 /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/ResearchSurface.strings; sourceTree = ""; }; 437E6394293E0BF6008C190A /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/Alerts.strings; sourceTree = ""; }; 437E6395293E0BF6008C190A /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/TabsTray.strings; sourceTree = ""; }; + 437E67412C57B4AB00A8791A /* th */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = th; path = th.lproj/ActivityStream.strings; sourceTree = ""; }; + 437E67422C57B4AB00A8791A /* th */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = th; path = th.lproj/AddressToolbar.strings; sourceTree = ""; }; + 437E67432C57B4AB00A8791A /* th */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = th; path = th.lproj/EditAddress.strings; sourceTree = ""; }; + 437E67442C57B4AB00A8791A /* th */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = th; path = th.lproj/EnhancedTrackingProtection.strings; sourceTree = ""; }; + 437E67452C57B4AB00A8791A /* th */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = th; path = th.lproj/QRCode.strings; sourceTree = ""; }; + 437E67462C57B4AB00A8791A /* th */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = th; path = th.lproj/ScanQRCode.strings; sourceTree = ""; }; + 437E67472C57B4AB00A8791A /* th */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = th; path = th.lproj/Toolbar.strings; sourceTree = ""; }; 437EA6282B83915700DE9E71 /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = he.lproj/KeyboardAccessory.strings; sourceTree = ""; }; 437EA6292B83915700DE9E71 /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = he.lproj/PasswordAutofill.strings; sourceTree = ""; }; 437F339929EF08FC003E82BC /* rm */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = rm; path = "rm.lproj/Edit Card.strings"; sourceTree = ""; }; @@ -4318,6 +4361,7 @@ 438605AF2C3C010600C4CD23 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/ScanQRCode.strings; sourceTree = ""; }; 43866D292B8CAA5C00808188 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/KeyboardAccessory.strings; sourceTree = ""; }; 43866D2A2B8CAA5C00808188 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/PasswordAutofill.strings; sourceTree = ""; }; + 4386E32C2C57AFCF00C97DCD /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Toolbar.strings; sourceTree = ""; }; 438712062BCD42B6003E6870 /* eo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eo; path = eo.lproj/BottomSheet.strings; sourceTree = ""; }; 4387326C28B39ED800FB7454 /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/BookmarkPanel.strings; sourceTree = ""; }; 43879B6F2B399B6700015597 /* kab */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kab; path = kab.lproj/CredentialProvider.strings; sourceTree = ""; }; @@ -4357,6 +4401,7 @@ 438998AF2B42D59F00591121 /* hy-AM */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "hy-AM"; path = "hy-AM.lproj/Credentials.strings"; sourceTree = ""; }; 438998B02B42D59F00591121 /* hy-AM */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "hy-AM"; path = "hy-AM.lproj/FirefoxLogins.strings"; sourceTree = ""; }; 438998B12B42D59F00591121 /* hy-AM */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "hy-AM"; path = "hy-AM.lproj/LoginsHelper.strings"; sourceTree = ""; }; + 4389B08A2C57B27500C52A68 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/Toolbar.strings; sourceTree = ""; }; 4389EEC42AC1A40100C748E8 /* rm */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = rm; path = rm.lproj/TabLocation.strings; sourceTree = ""; }; 438A4B202C20535600621E8F /* nn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nn; path = nn.lproj/ActivityStream.strings; sourceTree = ""; }; 438A4B212C20535600621E8F /* nn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nn; path = nn.lproj/AddressToolbar.strings; sourceTree = ""; }; @@ -4368,11 +4413,15 @@ 438AEF732AC1A29C00908F58 /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/TabLocation.strings; sourceTree = ""; }; 438B138E28B39FB900E53858 /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/JumpBackIn.strings; sourceTree = ""; }; 438B138F28B39FB900E53858 /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/ToolbarLocation.strings; sourceTree = ""; }; + 438B16422C57B39C007BD1A3 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/EditAddress.strings; sourceTree = ""; }; + 438B16432C57B39C007BD1A3 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/ScanQRCode.strings; sourceTree = ""; }; + 438B16442C57B39C007BD1A3 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Toolbar.strings; sourceTree = ""; }; 438B41BA2B5E865F00BA2E52 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/CredentialProvider.strings; sourceTree = ""; }; 438B41BB2B5E865F00BA2E52 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/Credentials.strings; sourceTree = ""; }; 438B41BC2B5E865F00BA2E52 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/FirefoxLogins.strings; sourceTree = ""; }; 438B41BD2B5E865F00BA2E52 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/LoginsHelper.strings; sourceTree = ""; }; 438B41BE2B5E865F00BA2E52 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/TabToolbar.strings; sourceTree = ""; }; + 438C39022C57B042005CD2CC /* es-AR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-AR"; path = "es-AR.lproj/Toolbar.strings"; sourceTree = ""; }; 438C427F29D1B1EB0088717D /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/SnackBar.strings; sourceTree = ""; }; 438C789C2BE8F22600265DFC /* en-US */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-US"; path = "en-US.lproj/Microsurvey.strings"; sourceTree = ""; }; 438C8BD62C3C039500F49EC2 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/EditAddress.strings; sourceTree = ""; }; @@ -4391,6 +4440,7 @@ 438DF00B2959B85B005E4C8F /* en-CA */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-CA"; path = "en-CA.lproj/SearchHeaderTitle.strings"; sourceTree = ""; }; 438DF00C2959B85B005E4C8F /* en-CA */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-CA"; path = "en-CA.lproj/TabsTray.strings"; sourceTree = ""; }; 438E69C22BA85A1200DE4241 /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/BottomSheet.strings; sourceTree = ""; }; + 438E812A2C57B30F004E1492 /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/EditAddress.strings; sourceTree = ""; }; 438EA1322C298BCA00EF793D /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/ActivityStream.strings; sourceTree = ""; }; 438EA1332C298BCA00EF793D /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/AddressToolbar.strings; sourceTree = ""; }; 438EA1342C298BCA00EF793D /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/EnhancedTrackingProtection.strings; sourceTree = ""; }; @@ -4411,6 +4461,10 @@ 43907D302C2050FB00DA0338 /* es-CL */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-CL"; path = "es-CL.lproj/EnhancedTrackingProtection.strings"; sourceTree = ""; }; 43907D312C2050FB00DA0338 /* es-CL */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-CL"; path = "es-CL.lproj/QRCode.strings"; sourceTree = ""; }; 43907E4C2B42D4550053503C /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Credentials.strings; sourceTree = ""; }; + 4390F7E12C57B1E700F52D3C /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/EditAddress.strings; sourceTree = ""; }; + 4390F7E22C57B1E700F52D3C /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/ScanQRCode.strings; sourceTree = ""; }; + 4390F7E32C57B1E800F52D3C /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Toolbar.strings; sourceTree = ""; }; + 4391326B2C57B0BB00805AE1 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Toolbar.strings; sourceTree = ""; }; 43914B522B4C115A0028781C /* nn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nn; path = nn.lproj/ContextualHints.strings; sourceTree = ""; }; 43914B532B4C115B0028781C /* nn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nn; path = nn.lproj/Credentials.strings; sourceTree = ""; }; 43914B542B4C115B0028781C /* nn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nn; path = nn.lproj/FirefoxHomepage.strings; sourceTree = ""; }; @@ -4458,6 +4512,7 @@ 439532AD28BE8D9B00B79237 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/ToolbarLocation.strings; sourceTree = ""; }; 4395FBDC2B5E85D200AA7AF3 /* is */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = is; path = is.lproj/TabToolbar.strings; sourceTree = ""; }; 43960B552ADD551700E3DF6B /* rm */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = rm; path = rm.lproj/Share.strings; sourceTree = ""; }; + 43961E7E2C57B15B00762948 /* hsb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hsb; path = hsb.lproj/Toolbar.strings; sourceTree = ""; }; 43962D222A24C16600934337 /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/DisplayCard.strings; sourceTree = ""; }; 4396410329C87A6700F74173 /* zh-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-TW"; path = "zh-TW.lproj/Alert.strings"; sourceTree = ""; }; 4396410429C87A6700F74173 /* zh-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-TW"; path = "zh-TW.lproj/BiometricAuthentication.strings"; sourceTree = ""; }; @@ -4468,6 +4523,7 @@ 439691A02AEFC7C900ED7ADA /* kk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kk; path = kk.lproj/Shopping.strings; sourceTree = ""; }; 4396BBE32A0BCCD200482ABA /* nn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nn; path = nn.lproj/FirefoxSync.strings; sourceTree = ""; }; 4396BBE42A0BCCD200482ABA /* nn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nn; path = nn.lproj/Upgrade.strings; sourceTree = ""; }; + 4396C29A2C57B42700837488 /* si */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = si; path = si.lproj/EditAddress.strings; sourceTree = ""; }; 4396CC192BCD424B000EB7C7 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/BottomSheet.strings; sourceTree = ""; }; 4396E5F72A373433008E15B7 /* es-CL */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-CL"; path = "es-CL.lproj/Footer.strings"; sourceTree = ""; }; 4396E5F82A373433008E15B7 /* es-CL */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-CL"; path = "es-CL.lproj/RememberCard.strings"; sourceTree = ""; }; @@ -4502,6 +4558,7 @@ 4398CDB82AC1A2FF00C9AA9E /* ka */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ka; path = ka.lproj/Share.strings; sourceTree = ""; }; 4398CDB92AC1A2FF00C9AA9E /* ka */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ka; path = ka.lproj/TabLocation.strings; sourceTree = ""; }; 4399EF912B7BEFC600E091BE /* kab */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kab; path = kab.lproj/TabToolbar.strings; sourceTree = ""; }; + 439A03F62C57B051003675A3 /* es-CL */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-CL"; path = "es-CL.lproj/Toolbar.strings"; sourceTree = ""; }; 439A0C6E29FFD5DA0084BD94 /* eu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eu; path = eu.lproj/Notification.strings; sourceTree = ""; }; 439A0C6F29FFD5DB0084BD94 /* eu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eu; path = eu.lproj/ZoomPageBar.strings; sourceTree = ""; }; 439A220E29F69A0C00F120EE /* be */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = be; path = be.lproj/Notification.strings; sourceTree = ""; }; @@ -4521,6 +4578,7 @@ 439A9B0F2C2052310071A727 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/AddressToolbar.strings; sourceTree = ""; }; 439A9B102C2052310071A727 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/EnhancedTrackingProtection.strings; sourceTree = ""; }; 439A9B112C2052310071A727 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/QRCode.strings; sourceTree = ""; }; + 439A9F662C57B3AF00448564 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Toolbar.strings"; sourceTree = ""; }; 439B78172A09721600CAAE37 /* FormAutofillHelperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormAutofillHelperTests.swift; sourceTree = ""; }; 439BC6462AC1A4E000AF4D58 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Share.strings; sourceTree = ""; }; 439BC6472AC1A4E000AF4D58 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/TabLocation.strings; sourceTree = ""; }; @@ -4622,6 +4680,7 @@ 43A49E682B30607700FC86A9 /* hsb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hsb; path = hsb.lproj/Credentials.strings; sourceTree = ""; }; 43A49E692B30607700FC86A9 /* hsb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hsb; path = hsb.lproj/FirefoxLogins.strings; sourceTree = ""; }; 43A49E6A2B30607700FC86A9 /* hsb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hsb; path = hsb.lproj/LoginsHelper.strings; sourceTree = ""; }; + 43A4B26E2C57B43700EF1B91 /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/Toolbar.strings; sourceTree = ""; }; 43A4FE5528B9069200497E4A /* si */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = si; path = si.lproj/JumpBackIn.strings; sourceTree = ""; }; 43A4FE5628B9069200497E4A /* si */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = si; path = si.lproj/ToolbarLocation.strings; sourceTree = ""; }; 43A5515C28B39F1E0077B8F9 /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/JumpBackIn.strings; sourceTree = ""; }; @@ -4651,12 +4710,14 @@ 43A7CA152A2DF99E00BCAA15 /* en-US */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-US"; path = "en-US.lproj/RememberCard.strings"; sourceTree = ""; }; 43A7CA162A2DF99E00BCAA15 /* en-US */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-US"; path = "en-US.lproj/UpdateCard.strings"; sourceTree = ""; }; 43A878162B838FF90039D6B7 /* br */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = br; path = br.lproj/PasswordAutofill.strings; sourceTree = ""; }; + 43A9086F2C57B3C300698450 /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/Toolbar.strings"; sourceTree = ""; }; 43A9B1E62A124A3800FB58C6 /* cy */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cy; path = cy.lproj/FirefoxSync.strings; sourceTree = ""; }; 43A9B1E72A124A3800FB58C6 /* cy */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cy; path = cy.lproj/Upgrade.strings; sourceTree = ""; }; 43A9DD9A29BA6B3A003D55A4 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/EngagementNotification.strings; sourceTree = ""; }; 43A9DD9B29BA6B3B003D55A4 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Onboarding.strings; sourceTree = ""; }; 43A9DD9C29BA6B3B003D55A4 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/ResearchSurface.strings; sourceTree = ""; }; 43AAE57528B39C790048A19E /* ga */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ga; path = ga.lproj/BookmarkPanel.strings; sourceTree = ""; }; + 43AB384A2C57B33900F19287 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Toolbar.strings; sourceTree = ""; }; 43AB6F9C25DC53D20016B015 /* GoogleTopSiteManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GoogleTopSiteManager.swift; sourceTree = ""; }; 43AB6F9E25DC53D20016B015 /* LabelButtonHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LabelButtonHeaderView.swift; sourceTree = ""; }; 43AB6FA125DC53D30016B015 /* TopSiteHistoryManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopSiteHistoryManager.swift; sourceTree = ""; }; @@ -4753,6 +4814,9 @@ 43B2DC8A29BA6BF200810266 /* sl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sl; path = sl.lproj/EngagementNotification.strings; sourceTree = ""; }; 43B2DC8B29BA6BF200810266 /* sl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sl; path = sl.lproj/Onboarding.strings; sourceTree = ""; }; 43B2DC8C29BA6BF200810266 /* sl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sl; path = sl.lproj/ResearchSurface.strings; sourceTree = ""; }; + 43B3869C2C57B446007728B6 /* sl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sl; path = sl.lproj/ScanQRCode.strings; sourceTree = ""; }; + 43B3869D2C57B446007728B6 /* sl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sl; path = sl.lproj/Toolbar.strings; sourceTree = ""; }; + 43B388562C57B1830004C424 /* hy-AM */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "hy-AM"; path = "hy-AM.lproj/Toolbar.strings"; sourceTree = ""; }; 43B3D33329DAEB53006B3FBC /* en-CA */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-CA"; path = "en-CA.lproj/Alert.strings"; sourceTree = ""; }; 43B3D33429DAEB53006B3FBC /* en-CA */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-CA"; path = "en-CA.lproj/BiometricAuthentication.strings"; sourceTree = ""; }; 43B3D33529DAEB53006B3FBC /* en-CA */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-CA"; path = "en-CA.lproj/EditCard.strings"; sourceTree = ""; }; @@ -4817,6 +4881,7 @@ 43B950CD2A2DFC2F0001A8D1 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Footer.strings; sourceTree = ""; }; 43B950CE2A2DFC2F0001A8D1 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/RememberCard.strings; sourceTree = ""; }; 43B950CF2A2DFC2F0001A8D1 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/UpdateCard.strings; sourceTree = ""; }; + 43B956C12C57B4C800F0E77B /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Toolbar.strings; sourceTree = ""; }; 43B966AE2BE8F11D007448EA /* be */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = be; path = be.lproj/Microsurvey.strings; sourceTree = ""; }; 43B9A3EB2A2DFA560078C977 /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/Footer.strings; sourceTree = ""; }; 43B9A3EC2A2DFA560078C977 /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/RememberCard.strings; sourceTree = ""; }; @@ -4898,6 +4963,7 @@ 43BED8DE2BE8F1F100E34361 /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/Microsurvey.strings; sourceTree = ""; }; 43BF382B2B8CA9C400EFDAF3 /* ia */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ia; path = ia.lproj/KeyboardAccessory.strings; sourceTree = ""; }; 43BFD4502C3C04B400B76DE5 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/EditAddress.strings; sourceTree = ""; }; + 43BFE5BA2C57B54100CFB4C5 /* zh-CN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-CN"; path = "zh-CN.lproj/Toolbar.strings"; sourceTree = ""; }; 43C0B1D82BE8F26100E527D7 /* es-CL */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-CL"; path = "es-CL.lproj/Microsurvey.strings"; sourceTree = ""; }; 43C0DAB929D1B25700827785 /* kk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kk; path = kk.lproj/Alert.strings; sourceTree = ""; }; 43C0DABA29D1B25700827785 /* kk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kk; path = kk.lproj/BiometricAuthentication.strings; sourceTree = ""; }; @@ -4913,6 +4979,7 @@ 43C19FC129F69DE0005214A6 /* zh-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-TW"; path = "zh-TW.lproj/Notification.strings"; sourceTree = ""; }; 43C19FC229F69DE0005214A6 /* zh-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-TW"; path = "zh-TW.lproj/ZoomPageBar.strings"; sourceTree = ""; }; 43C22F422BE8F4D80043046A /* rm */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = rm; path = rm.lproj/Microsurvey.strings; sourceTree = ""; }; + 43C2B2312C57B4560010E539 /* sq */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sq; path = sq.lproj/Toolbar.strings; sourceTree = ""; }; 43C335E028B39F6500858209 /* ta */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ta; path = ta.lproj/BookmarkPanel.strings; sourceTree = ""; }; 43C39FE42A24C0EB000FD072 /* sat-Olck */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "sat-Olck"; path = "sat-Olck.lproj/DisplayCard.strings"; sourceTree = ""; }; 43C4236D2AEFC88A00518309 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Shopping.strings"; sourceTree = ""; }; @@ -5010,6 +5077,7 @@ 43CD8C0929F69B6900B3ED1C /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = he.lproj/ZoomPageBar.strings; sourceTree = ""; }; 43CE859E2BCD467D00EFFAA4 /* th */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = th; path = th.lproj/BottomSheet.strings; sourceTree = ""; }; 43CE90FA2BE8F36700FFB2D4 /* is */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = is; path = is.lproj/Microsurvey.strings; sourceTree = ""; }; + 43CE9F3D2C57B5500069B3AF /* zh-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-TW"; path = "zh-TW.lproj/Toolbar.strings"; sourceTree = ""; }; 43CEB4582B680459000F85A9 /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/ContextualHints.strings"; sourceTree = ""; }; 43CEB4592B680459000F85A9 /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/Credentials.strings"; sourceTree = ""; }; 43CEB45A2B680459000F85A9 /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/TabToolbar.strings"; sourceTree = ""; }; @@ -5121,6 +5189,7 @@ 43D6F6F32B554C0100328E70 /* rm */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = rm; path = rm.lproj/FirefoxLogins.strings; sourceTree = ""; }; 43D6F6F42B554C0100328E70 /* rm */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = rm; path = rm.lproj/LoginsHelper.strings; sourceTree = ""; }; 43D6F6F52B554C0100328E70 /* rm */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = rm; path = rm.lproj/TabToolbar.strings; sourceTree = ""; }; + 43D6F80C2C57B4E7004BFBB8 /* ug */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ug; path = ug.lproj/Toolbar.strings; sourceTree = ""; }; 43D72DB226FCE3550069BDE9 /* mr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = mr; path = "mr.lproj/Default Browser.strings"; sourceTree = ""; }; 43D73B492A77CD3300E8C4EB /* be */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = be; path = be.lproj/CustomizeFirefoxHome.strings; sourceTree = ""; }; 43D74AE02BCD4286000D0251 /* en-CA */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-CA"; path = "en-CA.lproj/BottomSheet.strings"; sourceTree = ""; }; @@ -5227,6 +5296,7 @@ 43DF19022C20505300CB9A72 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/AddressToolbar.strings; sourceTree = ""; }; 43DF19032C20505300CB9A72 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/EnhancedTrackingProtection.strings; sourceTree = ""; }; 43DF19042C20505300CB9A72 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/QRCode.strings; sourceTree = ""; }; + 43DF2A222C57AFDD0083E728 /* dsb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = dsb; path = dsb.lproj/Toolbar.strings; sourceTree = ""; }; 43DF2D8E29C8799F008CA78E /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/Alert.strings; sourceTree = ""; }; 43DF2D8F29C8799F008CA78E /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/BiometricAuthentication.strings; sourceTree = ""; }; 43DF2D9029C8799F008CA78E /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/EditCard.strings; sourceTree = ""; }; @@ -5357,6 +5427,8 @@ 43E68A5E2B5E83DE004BC945 /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/TabToolbar.strings; sourceTree = ""; }; 43E699ED2AF9014B00030DDD /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/Shopping.strings; sourceTree = ""; }; 43E69EAF254D064E00B591C2 /* SimpleTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleTab.swift; sourceTree = ""; }; + 43E6BE132C57AF7600C2152C /* bs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bs; path = bs.lproj/ScanQRCode.strings; sourceTree = ""; }; + 43E6BE152C57AF7600C2152C /* bs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bs; path = bs.lproj/Toolbar.strings; sourceTree = ""; }; 43E730C22C20522100892124 /* is */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = is; path = is.lproj/ActivityStream.strings; sourceTree = ""; }; 43E730C32C20522100892124 /* is */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = is; path = is.lproj/AddressToolbar.strings; sourceTree = ""; }; 43E730C42C20522100892124 /* is */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = is; path = is.lproj/EnhancedTrackingProtection.strings; sourceTree = ""; }; @@ -5447,6 +5519,7 @@ 43EC79AD2C3C00BF00519D98 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/Share.strings"; sourceTree = ""; }; 43EC79AE2C3C00BF00519D98 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/Shopping.strings"; sourceTree = ""; }; 43ECB7C52BE8F3410024824F /* hy-AM */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "hy-AM"; path = "hy-AM.lproj/Microsurvey.strings"; sourceTree = ""; }; + 43ED215A2C57AFEC0014F10F /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/Toolbar.strings; sourceTree = ""; }; 43ED29612B305FD800481A75 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/ContextualHints.strings; sourceTree = ""; }; 43ED29622B305FD800481A75 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/CredentialProvider.strings; sourceTree = ""; }; 43ED29632B305FD800481A75 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Credentials.strings; sourceTree = ""; }; @@ -5617,6 +5690,7 @@ 43FAF1A82C2050C200C52557 /* en-US */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-US"; path = "en-US.lproj/QRCode.strings"; sourceTree = ""; }; 43FB409E2A0BCB650006C10B /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/FirefoxSync.strings; sourceTree = ""; }; 43FB409F2A0BCB650006C10B /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Upgrade.strings; sourceTree = ""; }; + 43FB540B2C57AFFA00562B25 /* en-CA */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-CA"; path = "en-CA.lproj/Toolbar.strings"; sourceTree = ""; }; 43FBF67F2ACADCF400F86E9E /* be */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = be; path = be.lproj/Share.strings; sourceTree = ""; }; 43FC1AAB2AC1A22C00989CA0 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Share.strings; sourceTree = ""; }; 43FC1AAC2AC1A22C00989CA0 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/TabLocation.strings; sourceTree = ""; }; @@ -12191,6 +12265,7 @@ 43C50B4E2A0BCAA800C6A134 /* FirefoxSync.strings */, 43A7153B2A2DF94F00DD5747 /* Footer.strings */, E4E0BB171AFBC9E4008D6260 /* Info.plist */, + 43E6BE142C57AF7600C2152C /* Toolbar.strings */, 43B627742C3C001E00A188E8 /* ScanQRCode.strings */, 43D3ED962C3BFFC900E33D46 /* EditAddress.strings */, 43903A902C20502A00ACF76E /* QRCode.strings */, @@ -13649,6 +13724,7 @@ 431F0C4A2AC1A112006D7D49 /* TabLocation.strings in Resources */, 43903A8F2C20502A00ACF76E /* EnhancedTrackingProtection.strings in Resources */, 43A878172B838FF90039D6B7 /* PasswordAutofill.strings in Resources */, + 43E6BE162C57AF7600C2152C /* Toolbar.strings in Resources */, D59643E725C9B8E000EAB8B9 /* Intro.strings in Resources */, D59643F325C9B8E000EAB8B9 /* Storage.strings in Resources */, D59643E925C9B8E000EAB8B9 /* Menu.strings in Resources */, @@ -16325,6 +16401,7 @@ 439CB65D2AE68F1F00A19D54 /* sq */, 4364EA952B1DE9FB003A1240 /* bs */, 43EB5FA72B2728080063D23E /* ug */, + 4300B0DE2C57B06E00F609C1 /* es-MX */, ); name = SelectCreditCard.strings; sourceTree = ""; @@ -16390,6 +16467,7 @@ 43CCB1A22B27249B00D6B1C0 /* br */, 43EB5FAC2B2728080063D23E /* ug */, 439E22242C04A5620061A923 /* su */, + 4300B0DF2C57B06E00F609C1 /* es-MX */, ); name = TabLocation.strings; sourceTree = ""; @@ -17192,6 +17270,8 @@ 430901D52C3C00DB00D5F3AC /* eu */, 431B95F62C453A89003B17BF /* en-CA */, 4375F0E12C453BC4001F3A55 /* hu */, + 4300B0D92C57B06E00F609C1 /* es-MX */, + 437E67412C57B4AB00A8791A /* th */, ); name = ActivityStream.strings; sourceTree = ""; @@ -17251,6 +17331,7 @@ 430901D62C3C00DB00D5F3AC /* eu */, 431B95F72C453A89003B17BF /* en-CA */, 4375F0E22C453BC4001F3A55 /* hu */, + 437E67422C57B4AB00A8791A /* th */, ); name = AddressToolbar.strings; sourceTree = ""; @@ -17310,6 +17391,8 @@ 430901D82C3C00DB00D5F3AC /* eu */, 431B95F92C453A89003B17BF /* en-CA */, 4375F0E42C453BC4001F3A55 /* hu */, + 4300B0DB2C57B06E00F609C1 /* es-MX */, + 437E67442C57B4AB00A8791A /* th */, ); name = EnhancedTrackingProtection.strings; sourceTree = ""; @@ -17367,6 +17450,7 @@ 43B5176E2C3C0217004F9302 /* kab */, 431B95FA2C453A89003B17BF /* en-CA */, 4375F0E52C453BC4001F3A55 /* hu */, + 437E67452C57B4AB00A8791A /* th */, ); name = QRCode.strings; sourceTree = ""; @@ -17920,6 +18004,7 @@ 4301323E2ADD559F00B1FAD7 /* sq */, 4364EA9D2B1DE9FB003A1240 /* bs */, 43EB5FAF2B2728080063D23E /* ug */, + 4300B0E12C57B06E00F609C1 /* es-MX */, ); name = UpdateCard.strings; sourceTree = ""; @@ -18175,6 +18260,7 @@ 439E221D2C04A5610061A923 /* su */, 43CCB4D12C32C526001F2EBB /* ca */, 43B890FC2C32C60B0049F033 /* es-MX */, + 433020F72C57B40600AF5EE2 /* sat-Olck */, ); name = Credentials.strings; sourceTree = ""; @@ -18412,6 +18498,16 @@ 4338F50D2C453D8800851075 /* rm */, 43F6E7632C453DF70018EEA4 /* sq */, 4383E28B2C453EAA00B775A3 /* vi */, + 43E6BE132C57AF7600C2152C /* bs */, + 43383DEA2C57AF94001BCD0E /* co */, + 435B35652C57AFA200F1C0BE /* cs */, + 436957A82C57AFB100B079FE /* cy */, + 4378EFA82C57AFBF0031897A /* da */, + 4300B0DD2C57B06E00F609C1 /* es-MX */, + 4390F7E22C57B1E700F52D3C /* ja */, + 438B16432C57B39C007BD1A3 /* pl */, + 43B3869C2C57B446007728B6 /* sl */, + 437E67462C57B4AB00A8791A /* th */, ); name = ScanQRCode.strings; sourceTree = ""; @@ -18473,6 +18569,7 @@ 438ABE532C0DDB6C00528A07 /* br */, 43B68F092C1690270012DAE2 /* th */, 43CCB4D62C32C527001F2EBB /* ca */, + 4300B0DC2C57B06E00F609C1 /* es-MX */, ); name = Microsurvey.strings; sourceTree = ""; @@ -18664,6 +18761,15 @@ 4375F0E32C453BC4001F3A55 /* hu */, 4338F50C2C453D8800851075 /* rm */, 43F6E7622C453DF70018EEA4 /* sq */, + 43383DE92C57AF94001BCD0E /* co */, + 4378EFA72C57AFBF0031897A /* da */, + 4300B0DA2C57B06E00F609C1 /* es-MX */, + 4390F7E12C57B1E700F52D3C /* ja */, + 438E812A2C57B30F004E1492 /* nb */, + 438B16422C57B39C007BD1A3 /* pl */, + 433020F82C57B40700AF5EE2 /* sat-Olck */, + 4396C29A2C57B42700837488 /* si */, + 437E67432C57B4AB00A8791A /* th */, ); name = EditAddress.strings; sourceTree = ""; @@ -18873,6 +18979,56 @@ name = SearchHeaderTitle.strings; sourceTree = ""; }; + 43E6BE142C57AF7600C2152C /* Toolbar.strings */ = { + isa = PBXVariantGroup; + children = ( + 43E6BE152C57AF7600C2152C /* bs */, + 43383DEB2C57AF94001BCD0E /* co */, + 435B35662C57AFA200F1C0BE /* cs */, + 4378EFA92C57AFBF0031897A /* da */, + 4386E32C2C57AFCF00C97DCD /* de */, + 43DF2A222C57AFDD0083E728 /* dsb */, + 43ED215A2C57AFEC0014F10F /* el */, + 43FB540B2C57AFFA00562B25 /* en-CA */, + 430ADCC62C57B00800B0A55B /* en-GB */, + 431813AE2C57B017007C3268 /* en-US */, + 438C39022C57B042005CD2CC /* es-AR */, + 439A03F62C57B051003675A3 /* es-CL */, + 4300B0E02C57B06E00F609C1 /* es-MX */, + 433954F62C57B0A900EC1EAE /* fi */, + 4391326B2C57B0BB00805AE1 /* fr */, + 43211E6B2C57B11F003F9FAF /* he */, + 43961E7E2C57B15B00762948 /* hsb */, + 43B388562C57B1830004C424 /* hy-AM */, + 430B81E02C57B198008C994B /* ia */, + 4329BDC32C57B1BF007F18C7 /* is */, + 434ED7EC2C57B1D4000C86E4 /* it */, + 4390F7E32C57B1E800F52D3C /* ja */, + 437A0B5A2C57B22500FCF751 /* kab */, + 4315028A2C57B23B005BB18E /* kk */, + 4389B08A2C57B27500C52A68 /* ko */, + 43AB384A2C57B33900F19287 /* nl */, + 430439F42C57B34D005518C3 /* nn */, + 43328A002C57B38800444F7E /* pa-IN */, + 438B16442C57B39C007BD1A3 /* pl */, + 439A9F662C57B3AF00448564 /* pt-BR */, + 43A9086F2C57B3C300698450 /* pt-PT */, + 436705DA2C57B3D7002C7FE6 /* rm */, + 431D82792C57B3F600062D71 /* ru */, + 43A4B26E2C57B43700EF1B91 /* sk */, + 43B3869D2C57B446007728B6 /* sl */, + 43C2B2312C57B4560010E539 /* sq */, + 432985492C57B47B00FE7CA2 /* sv */, + 437E67472C57B4AB00A8791A /* th */, + 43B956C12C57B4C800F0E77B /* tr */, + 43D6F80C2C57B4E7004BFBB8 /* ug */, + 43571C312C57B52200A2DD89 /* vi */, + 43BFE5BA2C57B54100CFB4C5 /* zh-CN */, + 43CE9F3D2C57B5500069B3AF /* zh-TW */, + ); + name = Toolbar.strings; + sourceTree = ""; + }; 43F118FE2A52E42400C44C6C /* CustomizeFirefoxHome.strings */ = { isa = PBXVariantGroup; children = ( diff --git a/firefox-ios/Shared/Supporting Files/bs.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/bs.lproj/EditAddress.strings index e47078cb4a7c..00ae4763887f 100644 --- a/firefox-ios/Shared/Supporting Files/bs.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/bs.lproj/EditAddress.strings @@ -88,3 +88,54 @@ /* Label for the telephone number field, allowing users to input their contact number. This is essential for communication and service provision, ensuring contact details are autofilled correctly. */ "Addresses.EditAddress.AutofillAddressTel.v129" = "Telefon"; +/* Label for the input field for the townland, a specific type of land division used in rural areas. Enhances address detail for users in regions where townlands are a common addressing component. */ +"Addresses.EditAddress.AutofillAddressTownland.v129" = "Townland"; + +/* Label for the field to input the name of a village or township. This is crucial for addresses in rural areas, ensuring the autofill feature accurately captures all necessary geographical details. */ +"Addresses.EditAddress.AutofillAddressVillageTownship.v129" = "Selo ili grad"; + +/* Label for the ZIP code field, primarily used in the United States for mail sorting. Key for autofill to accurately complete addresses for shipping, billing, and service provision. */ +"Addresses.EditAddress.AutofillAddressZip.v129" = "Poštanski broj"; + +/* Label for the button to cancel the current autofill operation or exit the form without saving changes. Provides users with an option to back out of a process without making any modifications. */ +"Addresses.EditAddress.AutofillCancelButton.v129" = "Otkaži"; + +/* Title for the option allowing users to edit an existing saved address. This is used within the settings for autofill, enabling users to update their address details for accurate form autofilling. */ +"Addresses.EditAddress.AutofillEditAddressTitle.v129" = "Uredi adresu"; + +/* Title for the input field where users can enter their street address. This is used within the settings for autofill, allowing users to provide their street address for accurate form autofilling. */ +"Addresses.EditAddress.AutofillEditStreetAddressTitle.v129" = "Adresa"; + +/* Label for the button to save the current address details entered or edited by the user. This action confirms the user's changes and updates their autofill settings accordingly. */ +"Addresses.EditAddress.AutofillSaveButton.v129" = "Sačuvaj"; + +/* Title for the option allowing users to view an existing saved address. This is used within the settings for autofill, enabling users to see their address details for accurate form autofilling. */ +"Addresses.EditAddress.AutofillViewAddressTitle.v129" = "Prikaži adresu"; + +/* Button label for closing the view where user can view their address info. */ +"Addresses.EditAddress.CloseNavBarButtonLabel.v129" = "Zatvori"; + +/* Button label for editing the address details shown in the form. */ +"Addresses.EditAddress.EditNavBarButtonLabel.v129" = "Uredi"; + +/* Title for button that offers the user the option to remove an address. */ +"Addresses.EditAddress.RemoveAddressButtonTitle.v129" = "Ukloni adresu"; + +/* Toast message confirming that an address has been successfully removed. */ +"Addresses.Toast.AddressRemovedConfirmation.v129" = "Adresa je uklonjena"; + +/* Toast message confirming that an address has been successfully saved. */ +"Addresses.Toast.AddressSavedConfirmation.v129" = "Adresa je sačuvana"; + +/* Toast message indicating an error occurred while trying to save an address. */ +"Addresses.Toast.AddressSaveError.v129" = "Adresa se ne može sačuvati"; + +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Adresa se ne može ukloniti"; + +/* Suggestion to try again after an error occurred while trying to save an address. */ +"Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Pokušaj ponovo"; + +/* Toast message confirming that an address has been successfully updated. */ +"Addresses.Toast.AddressUpdatedConfirmation.v129" = "Informacije o adresi su ažurirane"; + diff --git a/firefox-ios/Shared/Supporting Files/bs.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/bs.lproj/EnhancedTrackingProtection.strings index 16beec2ba692..5689d9147d96 100644 --- a/firefox-ios/Shared/Supporting Files/bs.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/bs.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,15 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Veza nije sigurna"; +/* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Kolačići za praćenje između web stranica: %@"; + +/* Text to let users know how many fingerprinters were blocked on the current website. The placeholder will show the number of fingerprinters detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.Fingerprinter.v129" = "Sakupljači digitalnih otisaka: %@"; + +/* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Programi za praćenje na društvenim mrežama: %@"; + /* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked Text to let users know that no trackers were found on the current website. */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Tragači blokirani: %@"; @@ -54,6 +63,9 @@ /* A switch to disable enhanced tracking protection inside the menu. */ "Menu.EnhancedTrackingProtection.SwitchOff.Text.v128" = "Zaštite su ISKLJUČENE. Predlažemo da ga ponovo uključite."; +/* A switch to disable enhanced tracking protection inside the menu. */ +"Menu.EnhancedTrackingProtection.SwitchOff.Text.v129" = "Zaštite su ISKLJUČENE. Predlažemo da ih ponovo uključite."; + /* A switch to disable enhanced tracking protection inside the menu. */ "Menu.EnhancedTrackingProtection.SwitchOn.Text.v128" = "Ako nešto izgleda pokvareno na ovoj stranici, pokušajte to isključiti."; diff --git a/firefox-ios/Shared/Supporting Files/bs.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/bs.lproj/Microsurvey.strings index e4ea46fb374a..3020ba9f936c 100644 --- a/firefox-ios/Shared/Supporting Files/bs.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/bs.lproj/Microsurvey.strings @@ -31,6 +31,9 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the title for the header on the screen. */ "Microsurvey.Survey.HeaderLabel.v127" = "Popunite ovu anketu"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the title for the header on the screen. */ +"Microsurvey.Survey.HeaderLabel.v129" = "Molimo popunite anketu"; + /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the logo image that appears on the bottom sheet that informs the user that it is coming from the app specifically. Placeholder is for the app name. */ "Microsurvey.Survey.LogoImage.AccessibilityLabel.v129" = "%@ logo"; @@ -49,6 +52,9 @@ /* On the microsurvey, this is the title for one of the options that the user can select to answer the survey. */ "Microsurvey.Survey.Options.LikertScaleOption5.v127" = "Vrlo nezadovoljan"; +/* On the microsurvey, this is the title for one of the options that the user can select to answer the survey. It indicates that the user has not use the feature that the survey is inquiring about. */ +"Microsurvey.Survey.Options.LikertScaleOption6.v129" = "Ne koristim ga"; + /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states the order the survey option in the list of options. First placeholder is the number the option is in the list and the second placeholder is the total number of options such as 1 out of 6. */ "Microsurvey.Survey.OptionsOrder.AccessibilityLabel.v129" = "%1$@ od %2$@"; diff --git a/firefox-ios/Shared/Supporting Files/bs.lproj/PasswordAutofill.strings b/firefox-ios/Shared/Supporting Files/bs.lproj/PasswordAutofill.strings index 42d920b62f0d..d1d6ae06da7a 100644 --- a/firefox-ios/Shared/Supporting Files/bs.lproj/PasswordAutofill.strings +++ b/firefox-ios/Shared/Supporting Files/bs.lproj/PasswordAutofill.strings @@ -1,3 +1,6 @@ +/* This label is used in a cell found in the list of autofill login options in place of an actual username to denote that no username was saved for this login */ +"PasswordAutofill.LoginListCellNoUsername.v129" = "(nema korisničkog imena)"; + /* This label is used for a button in the password list screen allowing users to manage their saved passwords. It's meant to direct users to where they can add, remove, or edit their saved passwords. */ "PasswordAutofill.ManagePasswordsButton.v124" = "Upravljajte lozinkama"; diff --git a/firefox-ios/Shared/Supporting Files/bs.lproj/ScanQRCode.strings b/firefox-ios/Shared/Supporting Files/bs.lproj/ScanQRCode.strings new file mode 100644 index 000000000000..7d996b43089b --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/bs.lproj/ScanQRCode.strings @@ -0,0 +1,9 @@ +/* Allow button to open URL from scanned QR Code */ +"ScanQRCode.ConfirmOpenURL.AllowButton.v129" = "Dozvoli"; + +/* Deny button to cancel opening URL from scanned QR Code */ +"ScanQRCode.ConfirmOpenURL.DenyButton.v129" = "Odbij"; + +/* Text of the prompt to ask user permission to open a URL from a scanned QR code. Placeholder is app name. */ +"ScanQRCode.ConfirmOpenURL.Message.v129" = "Dozvoliti %@ da se otvori?"; + diff --git a/firefox-ios/Shared/Supporting Files/bs.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/bs.lproj/Toolbar.strings new file mode 100644 index 000000000000..e7731c0e434e --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/bs.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Novi tab"; + diff --git a/firefox-ios/Shared/Supporting Files/co.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/co.lproj/EditAddress.strings new file mode 100644 index 000000000000..cf21681d1037 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/co.lproj/EditAddress.strings @@ -0,0 +1,141 @@ +/* Title for the cancel button in the remove address alert. */ +"Addresses.EditAddress.Alert.CancelButton.v129" = "Abbandunà"; + +/* Message explaining the consequences of removing an address from all synced devices. */ +"Addresses.EditAddress.Alert.Message.v129" = "L’indirizzu serà cacciatu da tutti i vostri apparechji sincrunizati."; + +/* Title for the remove button in the remove address alert. */ +"Addresses.EditAddress.Alert.RemoveButton.v129" = "Caccià"; + +/* Title for the alert indicating the action to remove an address. */ +"Addresses.EditAddress.Alert.Title.v129" = "Caccià l’indirizzu"; + +/* Title for the interface option where users can add a new address for autofill purposes. This facilitates quicker form completion by automatically filling in the user's address information. */ +"Addresses.EditAddress.AutofillAddAddressTitle.v129" = "Aghjunghje un indirizzu"; + +/* Label for the area field, allowing users to specify a particular area within a city or region. This detail can improve the specificity and accuracy of autofilled addresses. */ +"Addresses.EditAddress.AutofillAddressArea.v129" = "Area"; + +/* Label for the field where users input the city part of their address. This information is crucial for mail delivery and service provision, ensuring accurate city identification in autofill settings. */ +"Addresses.EditAddress.AutofillAddressCity.v129" = "Cità"; + +/* Label for the field where users can specify just the country, used in contexts where full address details are not required. Simplifies autofill when only country information is necessary. */ +"Addresses.EditAddress.AutofillAddressCountryOnly.v129" = "Paese"; + +/* Label for the country or region field in address forms, allowing users to specify their country or territorial region. This is fundamental for international mail and services, ensuring autofill accuracy across borders. */ +"Addresses.EditAddress.AutofillAddressCountryRegion.v129" = "Paese o regione"; + +/* Label for the county field, crucial for addressing in regions where county lines play a key role in postal services. Enhances autofill accuracy by including county information. */ +"Addresses.EditAddress.AutofillAddressCounty.v129" = "Pieve"; + +/* Label for the department field, used in countries like France and Colombia where departments are a key administrative division. Ensures correct departmental information is autofilled. */ +"Addresses.EditAddress.AutofillAddressDepartment.v129" = "Dipartimentu"; + +/* Label for the district field in the address form, allowing users to specify their district for more precise location identification. This aids in refining address details for accurate autofill. */ +"Addresses.EditAddress.AutofillAddressDistrict.v129" = "Circundariu"; + +/* Label for the Do/Si field, pertinent to addresses in South Korea. Do/Si refers to provincial level divisions, and specifying this enhances address accuracy in autofill settings. */ +"Addresses.EditAddress.AutofillAddressDoSi.v129" = "Do/Si"; + +/* Label for the Eircode field, specific to Ireland. It's a unique postal code system that helps in precise location identification, enhancing the effectiveness of autofill. */ +"Addresses.EditAddress.AutofillAddressEircode.v129" = "Eircode"; + +/* Label for the email address field, where users input their email. Critical for digital communication and account verification, this ensures email addresses are autofilled accurately. */ +"Addresses.EditAddress.AutofillAddressEmail.v129" = "Indirizzu elettronicu"; + +/* Label for the emirate field, essential for addresses in the United Arab Emirates. Including emirate details ensures the autofill feature accurately represents user addresses. */ +"Addresses.EditAddress.AutofillAddressEmirate.v129" = "Emiratu"; + +/* Label for the field where users specify the name of an island, if applicable. Important for addresses in archipelagic regions, aiding in precise location identification during autofill. */ +"Addresses.EditAddress.AutofillAddressIsland.v129" = "Isula"; + +/* Label for the field where the user inputs their full name as part of an address form. Essential for personalized form submissions and ensuring information accuracy in autofilled forms. */ +"Addresses.EditAddress.AutofillAddressName.v129" = "Nome"; + +/* Label for the field where users can input the name of their neighborhood. This detail adds precision to addresses, especially in densely populated areas, improving the accuracy of autofill. */ +"Addresses.EditAddress.AutofillAddressNeighborhood.v129" = "Quartieru"; + +/* Label for the oblast field, relevant for addresses in countries like Russia and Ukraine. Oblasts are a significant administrative division, and their specification aids in autofill accuracy. */ +"Addresses.EditAddress.AutofillAddressOblast.v129" = "Oblast"; + +/* Label for the input field designated for the organization's name related to the address. Helps in distinguishing addresses used for business or personal purposes in autofill settings. */ +"Addresses.EditAddress.AutofillAddressOrganization.v129" = "Urganismu"; + +/* Label for the parish field, significant in places where parishes are used for local administration and addressing. Ensures users can specify parish details for better autofill accuracy. */ +"Addresses.EditAddress.AutofillAddressParish.v129" = "Parochja"; + +/* Label for the PIN (Postal Index Number) field, used in India. It's a code representing a specific area, crucial for accurate mail delivery and autofill functionality. */ +"Addresses.EditAddress.AutofillAddressPin.v129" = "Pin"; + +/* Label for the postal code field, universally used in address forms to specify the area code for mail sorting. Essential for autofill to ensure mail and services are accurately routed. */ +"Addresses.EditAddress.AutofillAddressPostalCode.v129" = "Codice pustale"; + +/* Label for the post town field, used primarily in the UK and some other regions for mail sorting. Essential for users in applicable areas to specify for correct mail delivery through autofill. */ +"Addresses.EditAddress.AutofillAddressPostTown.v129" = "Cità pustale"; + +/* Label for the prefecture field, essential for addresses in countries like Japan where prefectures are a major administrative division. Aids in precise location specification for autofill. */ +"Addresses.EditAddress.AutofillAddressPrefecture.v129" = "Prefettura"; + +/* Label for the province field, required in countries where provinces are a primary administrative division. Helps in pinpointing the user's location more accurately for autofill purposes. */ +"Addresses.EditAddress.AutofillAddressProvince.v129" = "Pruvincia"; + +/* Label for the state field, a necessary component of addresses in many countries, especially the USA. It ensures that state-specific details are correctly filled in forms using autofill. */ +"Addresses.EditAddress.AutofillAddressState.v129" = "Statu"; + +/* Label for the suburb field, enabling users to add suburb details to their address. This is important for accurate delivery and services in suburban areas, enhancing autofill functionality. */ +"Addresses.EditAddress.AutofillAddressSuburb.v129" = "Circondu"; + +/* Label for the telephone number field, allowing users to input their contact number. This is essential for communication and service provision, ensuring contact details are autofilled correctly. */ +"Addresses.EditAddress.AutofillAddressTel.v129" = "Telefonu"; + +/* Label for the input field for the townland, a specific type of land division used in rural areas. Enhances address detail for users in regions where townlands are a common addressing component. */ +"Addresses.EditAddress.AutofillAddressTownland.v129" = "Paisolu"; + +/* Label for the field to input the name of a village or township. This is crucial for addresses in rural areas, ensuring the autofill feature accurately captures all necessary geographical details. */ +"Addresses.EditAddress.AutofillAddressVillageTownship.v129" = "Paese o cantone"; + +/* Label for the ZIP code field, primarily used in the United States for mail sorting. Key for autofill to accurately complete addresses for shipping, billing, and service provision. */ +"Addresses.EditAddress.AutofillAddressZip.v129" = "Codice pustale (Stati Uniti)"; + +/* Label for the button to cancel the current autofill operation or exit the form without saving changes. Provides users with an option to back out of a process without making any modifications. */ +"Addresses.EditAddress.AutofillCancelButton.v129" = "Abbandunà"; + +/* Title for the option allowing users to edit an existing saved address. This is used within the settings for autofill, enabling users to update their address details for accurate form autofilling. */ +"Addresses.EditAddress.AutofillEditAddressTitle.v129" = "Mudificà l’indirizzu"; + +/* Title for the input field where users can enter their street address. This is used within the settings for autofill, allowing users to provide their street address for accurate form autofilling. */ +"Addresses.EditAddress.AutofillEditStreetAddressTitle.v129" = "Indirizzu pustale"; + +/* Label for the button to save the current address details entered or edited by the user. This action confirms the user's changes and updates their autofill settings accordingly. */ +"Addresses.EditAddress.AutofillSaveButton.v129" = "Arregistrà"; + +/* Title for the option allowing users to view an existing saved address. This is used within the settings for autofill, enabling users to see their address details for accurate form autofilling. */ +"Addresses.EditAddress.AutofillViewAddressTitle.v129" = "Fighjà l’indirizzu"; + +/* Button label for closing the view where user can view their address info. */ +"Addresses.EditAddress.CloseNavBarButtonLabel.v129" = "Chjode"; + +/* Button label for editing the address details shown in the form. */ +"Addresses.EditAddress.EditNavBarButtonLabel.v129" = "Mudificà"; + +/* Title for button that offers the user the option to remove an address. */ +"Addresses.EditAddress.RemoveAddressButtonTitle.v129" = "Caccià l’indirizzu"; + +/* Toast message confirming that an address has been successfully removed. */ +"Addresses.Toast.AddressRemovedConfirmation.v129" = "Indirizzu cacciatu"; + +/* Toast message confirming that an address has been successfully saved. */ +"Addresses.Toast.AddressSavedConfirmation.v129" = "Indirizzu arregistratu"; + +/* Toast message indicating an error occurred while trying to save an address. */ +"Addresses.Toast.AddressSaveError.v129" = "L’indirizzu ùn pò micca esse arregistratu"; + +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "L’indirizzu ùn pò micca esse cacciatu"; + +/* Suggestion to try again after an error occurred while trying to save an address. */ +"Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Pruvà torna"; + +/* Toast message confirming that an address has been successfully updated. */ +"Addresses.Toast.AddressUpdatedConfirmation.v129" = "Infurmazioni d’indirizzu mudificate"; + diff --git a/firefox-ios/Shared/Supporting Files/co.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/co.lproj/EnhancedTrackingProtection.strings index 7c6e80c96974..36a2948be7e2 100644 --- a/firefox-ios/Shared/Supporting Files/co.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/co.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,15 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Cunnessione micca assicurata"; +/* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Canistrelli di spiunagiu intersiti : %@"; + +/* Text to let users know how many fingerprinters were blocked on the current website. The placeholder will show the number of fingerprinters detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.Fingerprinter.v129" = "Detettori d’impronta numerica : %@"; + +/* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Perseguitatori di rete suciale : %@"; + /* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked Text to let users know that no trackers were found on the current website. */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Perseguitatori bluccati : %@"; @@ -54,6 +63,9 @@ /* A switch to disable enhanced tracking protection inside the menu. */ "Menu.EnhancedTrackingProtection.SwitchOff.Text.v128" = "E prutezzioni sò disattivate. Vi ricumandemu d’attivalle torna."; +/* A switch to disable enhanced tracking protection inside the menu. */ +"Menu.EnhancedTrackingProtection.SwitchOff.Text.v129" = "E prutezzioni sò disattivate. Vi ricumandemu di riattivalle torna."; + /* A switch to disable enhanced tracking protection inside the menu. */ "Menu.EnhancedTrackingProtection.SwitchOn.Text.v128" = "S’è qualcosa ùn pare micca funziunà nant’à stu situ, pruvate di disattivà sta funzione."; diff --git a/firefox-ios/Shared/Supporting Files/co.lproj/PasswordAutofill.strings b/firefox-ios/Shared/Supporting Files/co.lproj/PasswordAutofill.strings index 359b0f87986f..d7efabd56cd0 100644 --- a/firefox-ios/Shared/Supporting Files/co.lproj/PasswordAutofill.strings +++ b/firefox-ios/Shared/Supporting Files/co.lproj/PasswordAutofill.strings @@ -1,3 +1,6 @@ +/* This label is used in a cell found in the list of autofill login options in place of an actual username to denote that no username was saved for this login */ +"PasswordAutofill.LoginListCellNoUsername.v129" = "(nisunu nome d’utilizatore)"; + /* This label is used for a button in the password list screen allowing users to manage their saved passwords. It's meant to direct users to where they can add, remove, or edit their saved passwords. */ "PasswordAutofill.ManagePasswordsButton.v124" = "Amministrà e parolle d’intesa"; diff --git a/firefox-ios/Shared/Supporting Files/co.lproj/ScanQRCode.strings b/firefox-ios/Shared/Supporting Files/co.lproj/ScanQRCode.strings new file mode 100644 index 000000000000..c331f818c01b --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/co.lproj/ScanQRCode.strings @@ -0,0 +1,9 @@ +/* Allow button to open URL from scanned QR Code */ +"ScanQRCode.ConfirmOpenURL.AllowButton.v129" = "Permette"; + +/* Deny button to cancel opening URL from scanned QR Code */ +"ScanQRCode.ConfirmOpenURL.DenyButton.v129" = "Ricusà"; + +/* Text of the prompt to ask user permission to open a URL from a scanned QR code. Placeholder is app name. */ +"ScanQRCode.ConfirmOpenURL.Message.v129" = "Permette l’apertura da %@ ?"; + diff --git a/firefox-ios/Shared/Supporting Files/co.lproj/Shopping.strings b/firefox-ios/Shared/Supporting Files/co.lproj/Shopping.strings index 6a818cea8e44..f4aaa96b87a0 100644 --- a/firefox-ios/Shared/Supporting Files/co.lproj/Shopping.strings +++ b/firefox-ios/Shared/Supporting Files/co.lproj/Shopping.strings @@ -248,8 +248,8 @@ "Shopping.Sheet.Title.v120" = "Verificadore d’avisu"; /* Text for body of error card displayed to the user when the device is disconnected from the network. */ -"Shopping.WarningCard.CheckNoConnection.Description.v120" = "Verificate a vostra cunnessione di reta è pruvate di ricaricà a pagina."; +"Shopping.WarningCard.CheckNoConnection.Description.v120" = "Verificate a vostra cunnessione à a reta è pruvate di ricaricà a pagina."; /* Title for error card displayed to the user when the device is disconnected from the network. */ -"Shopping.WarningCard.CheckNoConnection.Title.v120" = "Nisuna cunnessione di reta"; +"Shopping.WarningCard.CheckNoConnection.Title.v120" = "Nisuna cunnessione à a reta"; diff --git a/firefox-ios/Shared/Supporting Files/co.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/co.lproj/Toolbar.strings new file mode 100644 index 000000000000..775392f15b94 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/co.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Unghjetta nova"; + diff --git a/firefox-ios/Shared/Supporting Files/cs.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/cs.lproj/EditAddress.strings index 30ce8f3ddd39..d1aa5bf08f3e 100644 --- a/firefox-ios/Shared/Supporting Files/cs.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/cs.lproj/EditAddress.strings @@ -121,3 +121,21 @@ /* Title for button that offers the user the option to remove an address. */ "Addresses.EditAddress.RemoveAddressButtonTitle.v129" = "Odebrat adresu"; +/* Toast message confirming that an address has been successfully removed. */ +"Addresses.Toast.AddressRemovedConfirmation.v129" = "Adresa byla odebrána"; + +/* Toast message confirming that an address has been successfully saved. */ +"Addresses.Toast.AddressSavedConfirmation.v129" = "Adresa byla uložena"; + +/* Toast message indicating an error occurred while trying to save an address. */ +"Addresses.Toast.AddressSaveError.v129" = "Adresu se nepodařilo uložit"; + +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Adresu se nepodařilo odebrat"; + +/* Suggestion to try again after an error occurred while trying to save an address. */ +"Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Zkusit znovu"; + +/* Toast message confirming that an address has been successfully updated. */ +"Addresses.Toast.AddressUpdatedConfirmation.v129" = "Informace o adrese byla aktualizována"; + diff --git a/firefox-ios/Shared/Supporting Files/cs.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/cs.lproj/EnhancedTrackingProtection.strings index 7289f55d2ec0..7d745c23a7f8 100644 --- a/firefox-ios/Shared/Supporting Files/cs.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/cs.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,15 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Spojení není zabezpečené"; +/* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Sledovací cross-site cookies: %@"; + +/* Text to let users know how many fingerprinters were blocked on the current website. The placeholder will show the number of fingerprinters detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.Fingerprinter.v129" = "Vytváření otisku prohlížeče: %@"; + +/* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Sledovací prvky sociálních sítí: %@"; + /* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked Text to let users know that no trackers were found on the current website. */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Zablokované sledovací prvky: %@"; @@ -54,6 +63,9 @@ /* A switch to disable enhanced tracking protection inside the menu. */ "Menu.EnhancedTrackingProtection.SwitchOff.Text.v128" = "Ochrana je vypnuta. Doporučujeme ji znovu zapnout."; +/* A switch to disable enhanced tracking protection inside the menu. */ +"Menu.EnhancedTrackingProtection.SwitchOff.Text.v129" = "Ochrana je VYPNUTÁ. Doporučujeme ji znovu zapnout."; + /* A switch to disable enhanced tracking protection inside the menu. */ "Menu.EnhancedTrackingProtection.SwitchOn.Text.v128" = "Pokud se vám zdá, že je něco na této stránce nefunkční, zkuste to vypnout."; diff --git a/firefox-ios/Shared/Supporting Files/cs.lproj/PasswordAutofill.strings b/firefox-ios/Shared/Supporting Files/cs.lproj/PasswordAutofill.strings index a8d992ad724a..dd957155eb05 100644 --- a/firefox-ios/Shared/Supporting Files/cs.lproj/PasswordAutofill.strings +++ b/firefox-ios/Shared/Supporting Files/cs.lproj/PasswordAutofill.strings @@ -1,3 +1,6 @@ +/* This label is used in a cell found in the list of autofill login options in place of an actual username to denote that no username was saved for this login */ +"PasswordAutofill.LoginListCellNoUsername.v129" = "(žádné uživatelské jméno)"; + /* This label is used for a button in the password list screen allowing users to manage their saved passwords. It's meant to direct users to where they can add, remove, or edit their saved passwords. */ "PasswordAutofill.ManagePasswordsButton.v124" = "Správa hesel"; diff --git a/firefox-ios/Shared/Supporting Files/cs.lproj/ScanQRCode.strings b/firefox-ios/Shared/Supporting Files/cs.lproj/ScanQRCode.strings new file mode 100644 index 000000000000..3f3b504a5968 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/cs.lproj/ScanQRCode.strings @@ -0,0 +1,9 @@ +/* Allow button to open URL from scanned QR Code */ +"ScanQRCode.ConfirmOpenURL.AllowButton.v129" = "Povolit"; + +/* Deny button to cancel opening URL from scanned QR Code */ +"ScanQRCode.ConfirmOpenURL.DenyButton.v129" = "Zakázat"; + +/* Text of the prompt to ask user permission to open a URL from a scanned QR code. Placeholder is app name. */ +"ScanQRCode.ConfirmOpenURL.Message.v129" = "Povolit aplikaci %@ ji otevřít?"; + diff --git a/firefox-ios/Shared/Supporting Files/cs.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/cs.lproj/Toolbar.strings new file mode 100644 index 000000000000..4eec7ea2d40d --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/cs.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Nový panel"; + diff --git a/firefox-ios/Shared/Supporting Files/cy.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/cy.lproj/EditAddress.strings index 58bedcbce683..ffb343e9439f 100644 --- a/firefox-ios/Shared/Supporting Files/cy.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/cy.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "Nid Oedd Modd Cadw'r Cyfeiriad"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Nid Oedd Modd Dileu'r Cyfeiriad"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Ceisiwch eto"; diff --git a/firefox-ios/Shared/Supporting Files/cy.lproj/PasswordAutofill.strings b/firefox-ios/Shared/Supporting Files/cy.lproj/PasswordAutofill.strings index e2f3d4fece34..68f069f4c1f7 100644 --- a/firefox-ios/Shared/Supporting Files/cy.lproj/PasswordAutofill.strings +++ b/firefox-ios/Shared/Supporting Files/cy.lproj/PasswordAutofill.strings @@ -1,3 +1,6 @@ +/* This label is used in a cell found in the list of autofill login options in place of an actual username to denote that no username was saved for this login */ +"PasswordAutofill.LoginListCellNoUsername.v129" = "(dim enw defnyddiwr)"; + /* This label is used for a button in the password list screen allowing users to manage their saved passwords. It's meant to direct users to where they can add, remove, or edit their saved passwords. */ "PasswordAutofill.ManagePasswordsButton.v124" = "Rheoli cyfrineiriau"; diff --git a/firefox-ios/Shared/Supporting Files/cy.lproj/ScanQRCode.strings b/firefox-ios/Shared/Supporting Files/cy.lproj/ScanQRCode.strings new file mode 100644 index 000000000000..c8921eabbb96 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/cy.lproj/ScanQRCode.strings @@ -0,0 +1,9 @@ +/* Allow button to open URL from scanned QR Code */ +"ScanQRCode.ConfirmOpenURL.AllowButton.v129" = "Caniatáu"; + +/* Deny button to cancel opening URL from scanned QR Code */ +"ScanQRCode.ConfirmOpenURL.DenyButton.v129" = "Gwrthod"; + +/* Text of the prompt to ask user permission to open a URL from a scanned QR code. Placeholder is app name. */ +"ScanQRCode.ConfirmOpenURL.Message.v129" = "Caniatáu i %@ agor?"; + diff --git a/firefox-ios/Shared/Supporting Files/da.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/da.lproj/EditAddress.strings new file mode 100644 index 000000000000..4d78e65b1d5e --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/da.lproj/EditAddress.strings @@ -0,0 +1,141 @@ +/* Title for the cancel button in the remove address alert. */ +"Addresses.EditAddress.Alert.CancelButton.v129" = "Annuller"; + +/* Message explaining the consequences of removing an address from all synced devices. */ +"Addresses.EditAddress.Alert.Message.v129" = "Adressen vil blive fjernet fra alle dine synkroniserede enheder."; + +/* Title for the remove button in the remove address alert. */ +"Addresses.EditAddress.Alert.RemoveButton.v129" = "Fjern"; + +/* Title for the alert indicating the action to remove an address. */ +"Addresses.EditAddress.Alert.Title.v129" = "Fjern adresse"; + +/* Title for the interface option where users can add a new address for autofill purposes. This facilitates quicker form completion by automatically filling in the user's address information. */ +"Addresses.EditAddress.AutofillAddAddressTitle.v129" = "Tilføj adresse"; + +/* Label for the area field, allowing users to specify a particular area within a city or region. This detail can improve the specificity and accuracy of autofilled addresses. */ +"Addresses.EditAddress.AutofillAddressArea.v129" = "Area"; + +/* Label for the field where users input the city part of their address. This information is crucial for mail delivery and service provision, ensuring accurate city identification in autofill settings. */ +"Addresses.EditAddress.AutofillAddressCity.v129" = "By"; + +/* Label for the field where users can specify just the country, used in contexts where full address details are not required. Simplifies autofill when only country information is necessary. */ +"Addresses.EditAddress.AutofillAddressCountryOnly.v129" = "Land"; + +/* Label for the country or region field in address forms, allowing users to specify their country or territorial region. This is fundamental for international mail and services, ensuring autofill accuracy across borders. */ +"Addresses.EditAddress.AutofillAddressCountryRegion.v129" = "Land eller region"; + +/* Label for the county field, crucial for addressing in regions where county lines play a key role in postal services. Enhances autofill accuracy by including county information. */ +"Addresses.EditAddress.AutofillAddressCounty.v129" = "County"; + +/* Label for the department field, used in countries like France and Colombia where departments are a key administrative division. Ensures correct departmental information is autofilled. */ +"Addresses.EditAddress.AutofillAddressDepartment.v129" = "Department"; + +/* Label for the district field in the address form, allowing users to specify their district for more precise location identification. This aids in refining address details for accurate autofill. */ +"Addresses.EditAddress.AutofillAddressDistrict.v129" = "District"; + +/* Label for the Do/Si field, pertinent to addresses in South Korea. Do/Si refers to provincial level divisions, and specifying this enhances address accuracy in autofill settings. */ +"Addresses.EditAddress.AutofillAddressDoSi.v129" = "Do/Si"; + +/* Label for the Eircode field, specific to Ireland. It's a unique postal code system that helps in precise location identification, enhancing the effectiveness of autofill. */ +"Addresses.EditAddress.AutofillAddressEircode.v129" = "Eircode"; + +/* Label for the email address field, where users input their email. Critical for digital communication and account verification, this ensures email addresses are autofilled accurately. */ +"Addresses.EditAddress.AutofillAddressEmail.v129" = "Mailadresse"; + +/* Label for the emirate field, essential for addresses in the United Arab Emirates. Including emirate details ensures the autofill feature accurately represents user addresses. */ +"Addresses.EditAddress.AutofillAddressEmirate.v129" = "Emirat"; + +/* Label for the field where users specify the name of an island, if applicable. Important for addresses in archipelagic regions, aiding in precise location identification during autofill. */ +"Addresses.EditAddress.AutofillAddressIsland.v129" = "Ø"; + +/* Label for the field where the user inputs their full name as part of an address form. Essential for personalized form submissions and ensuring information accuracy in autofilled forms. */ +"Addresses.EditAddress.AutofillAddressName.v129" = "Navn"; + +/* Label for the field where users can input the name of their neighborhood. This detail adds precision to addresses, especially in densely populated areas, improving the accuracy of autofill. */ +"Addresses.EditAddress.AutofillAddressNeighborhood.v129" = "Neighborhood"; + +/* Label for the oblast field, relevant for addresses in countries like Russia and Ukraine. Oblasts are a significant administrative division, and their specification aids in autofill accuracy. */ +"Addresses.EditAddress.AutofillAddressOblast.v129" = "Oblast"; + +/* Label for the input field designated for the organization's name related to the address. Helps in distinguishing addresses used for business or personal purposes in autofill settings. */ +"Addresses.EditAddress.AutofillAddressOrganization.v129" = "Organisation"; + +/* Label for the parish field, significant in places where parishes are used for local administration and addressing. Ensures users can specify parish details for better autofill accuracy. */ +"Addresses.EditAddress.AutofillAddressParish.v129" = "Parish"; + +/* Label for the PIN (Postal Index Number) field, used in India. It's a code representing a specific area, crucial for accurate mail delivery and autofill functionality. */ +"Addresses.EditAddress.AutofillAddressPin.v129" = "Pin"; + +/* Label for the postal code field, universally used in address forms to specify the area code for mail sorting. Essential for autofill to ensure mail and services are accurately routed. */ +"Addresses.EditAddress.AutofillAddressPostalCode.v129" = "Postnummer"; + +/* Label for the post town field, used primarily in the UK and some other regions for mail sorting. Essential for users in applicable areas to specify for correct mail delivery through autofill. */ +"Addresses.EditAddress.AutofillAddressPostTown.v129" = "Post town"; + +/* Label for the prefecture field, essential for addresses in countries like Japan where prefectures are a major administrative division. Aids in precise location specification for autofill. */ +"Addresses.EditAddress.AutofillAddressPrefecture.v129" = "Prefecture"; + +/* Label for the province field, required in countries where provinces are a primary administrative division. Helps in pinpointing the user's location more accurately for autofill purposes. */ +"Addresses.EditAddress.AutofillAddressProvince.v129" = "Område"; + +/* Label for the state field, a necessary component of addresses in many countries, especially the USA. It ensures that state-specific details are correctly filled in forms using autofill. */ +"Addresses.EditAddress.AutofillAddressState.v129" = "Stat"; + +/* Label for the suburb field, enabling users to add suburb details to their address. This is important for accurate delivery and services in suburban areas, enhancing autofill functionality. */ +"Addresses.EditAddress.AutofillAddressSuburb.v129" = "Suburb"; + +/* Label for the telephone number field, allowing users to input their contact number. This is essential for communication and service provision, ensuring contact details are autofilled correctly. */ +"Addresses.EditAddress.AutofillAddressTel.v129" = "Telefonnummer"; + +/* Label for the input field for the townland, a specific type of land division used in rural areas. Enhances address detail for users in regions where townlands are a common addressing component. */ +"Addresses.EditAddress.AutofillAddressTownland.v129" = "Townland"; + +/* Label for the field to input the name of a village or township. This is crucial for addresses in rural areas, ensuring the autofill feature accurately captures all necessary geographical details. */ +"Addresses.EditAddress.AutofillAddressVillageTownship.v129" = "Village eller Township"; + +/* Label for the ZIP code field, primarily used in the United States for mail sorting. Key for autofill to accurately complete addresses for shipping, billing, and service provision. */ +"Addresses.EditAddress.AutofillAddressZip.v129" = "Zip code"; + +/* Label for the button to cancel the current autofill operation or exit the form without saving changes. Provides users with an option to back out of a process without making any modifications. */ +"Addresses.EditAddress.AutofillCancelButton.v129" = "Annuller"; + +/* Title for the option allowing users to edit an existing saved address. This is used within the settings for autofill, enabling users to update their address details for accurate form autofilling. */ +"Addresses.EditAddress.AutofillEditAddressTitle.v129" = "Rediger adresse"; + +/* Title for the input field where users can enter their street address. This is used within the settings for autofill, allowing users to provide their street address for accurate form autofilling. */ +"Addresses.EditAddress.AutofillEditStreetAddressTitle.v129" = "Postadresse"; + +/* Label for the button to save the current address details entered or edited by the user. This action confirms the user's changes and updates their autofill settings accordingly. */ +"Addresses.EditAddress.AutofillSaveButton.v129" = "Gem"; + +/* Title for the option allowing users to view an existing saved address. This is used within the settings for autofill, enabling users to see their address details for accurate form autofilling. */ +"Addresses.EditAddress.AutofillViewAddressTitle.v129" = "Vis adresse"; + +/* Button label for closing the view where user can view their address info. */ +"Addresses.EditAddress.CloseNavBarButtonLabel.v129" = "Luk"; + +/* Button label for editing the address details shown in the form. */ +"Addresses.EditAddress.EditNavBarButtonLabel.v129" = "Rediger"; + +/* Title for button that offers the user the option to remove an address. */ +"Addresses.EditAddress.RemoveAddressButtonTitle.v129" = "Fjern adresse"; + +/* Toast message confirming that an address has been successfully removed. */ +"Addresses.Toast.AddressRemovedConfirmation.v129" = "Adresse fjernet"; + +/* Toast message confirming that an address has been successfully saved. */ +"Addresses.Toast.AddressSavedConfirmation.v129" = "Adressen blev gemt"; + +/* Toast message indicating an error occurred while trying to save an address. */ +"Addresses.Toast.AddressSaveError.v129" = "Adressen kunne ikke gemmes"; + +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Adressen kunne ikke fjernes"; + +/* Suggestion to try again after an error occurred while trying to save an address. */ +"Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Prøv igen"; + +/* Toast message confirming that an address has been successfully updated. */ +"Addresses.Toast.AddressUpdatedConfirmation.v129" = "Adresse-oplysningerne blev opdateret"; + diff --git a/firefox-ios/Shared/Supporting Files/da.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/da.lproj/EnhancedTrackingProtection.strings index 0689a3d68f97..e5f81a15b529 100644 --- a/firefox-ios/Shared/Supporting Files/da.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/da.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,15 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Forbindelsen er ikke sikker"; +/* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Sporings-cookies på tværs af websteder: %@"; + +/* Text to let users know how many fingerprinters were blocked on the current website. The placeholder will show the number of fingerprinters detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.Fingerprinter.v129" = "Fingerprinters: %@"; + +/* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Sporing via sociale medier: %@"; + /* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked Text to let users know that no trackers were found on the current website. */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Forsøg på sporing blokeret: %@"; @@ -54,6 +63,9 @@ /* A switch to disable enhanced tracking protection inside the menu. */ "Menu.EnhancedTrackingProtection.SwitchOff.Text.v128" = "Beskyttelse er SLÅET FRA. Vi anbefaler, at du slår det til igen."; +/* A switch to disable enhanced tracking protection inside the menu. */ +"Menu.EnhancedTrackingProtection.SwitchOff.Text.v129" = "Beskyttelse er SLÅET FRA. Vi anbefaler, at du slår det til igen."; + /* A switch to disable enhanced tracking protection inside the menu. */ "Menu.EnhancedTrackingProtection.SwitchOn.Text.v128" = "Hvis noget på webstedet ikke ser ud til at virke som det skal, så prøv at slå beskyttelse fra."; diff --git a/firefox-ios/Shared/Supporting Files/da.lproj/PasswordAutofill.strings b/firefox-ios/Shared/Supporting Files/da.lproj/PasswordAutofill.strings index 711ff5834c46..006515f83b65 100644 --- a/firefox-ios/Shared/Supporting Files/da.lproj/PasswordAutofill.strings +++ b/firefox-ios/Shared/Supporting Files/da.lproj/PasswordAutofill.strings @@ -1,3 +1,6 @@ +/* This label is used in a cell found in the list of autofill login options in place of an actual username to denote that no username was saved for this login */ +"PasswordAutofill.LoginListCellNoUsername.v129" = "(intet brugernavn)"; + /* This label is used for a button in the password list screen allowing users to manage their saved passwords. It's meant to direct users to where they can add, remove, or edit their saved passwords. */ "PasswordAutofill.ManagePasswordsButton.v124" = "Håndter adgangskoder"; diff --git a/firefox-ios/Shared/Supporting Files/da.lproj/ScanQRCode.strings b/firefox-ios/Shared/Supporting Files/da.lproj/ScanQRCode.strings new file mode 100644 index 000000000000..b693442ac70b --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/da.lproj/ScanQRCode.strings @@ -0,0 +1,9 @@ +/* Allow button to open URL from scanned QR Code */ +"ScanQRCode.ConfirmOpenURL.AllowButton.v129" = "Tillad"; + +/* Deny button to cancel opening URL from scanned QR Code */ +"ScanQRCode.ConfirmOpenURL.DenyButton.v129" = "Afvis"; + +/* Text of the prompt to ask user permission to open a URL from a scanned QR code. Placeholder is app name. */ +"ScanQRCode.ConfirmOpenURL.Message.v129" = "Tillad at %@ åbnes?"; + diff --git a/firefox-ios/Shared/Supporting Files/da.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/da.lproj/Toolbar.strings new file mode 100644 index 000000000000..896bdfe93054 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/da.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Nyt faneblad"; + diff --git a/firefox-ios/Shared/Supporting Files/de.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/de.lproj/EditAddress.strings index 2f8c2e92b5c2..48a2690a7d75 100644 --- a/firefox-ios/Shared/Supporting Files/de.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/de.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "Adresse konnte nicht gespeichert werden"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Adresse konnte nicht entfernt werden"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Erneut versuchen"; diff --git a/firefox-ios/Shared/Supporting Files/de.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/de.lproj/Toolbar.strings new file mode 100644 index 000000000000..f25301eed189 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/de.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Neuer Tab"; + diff --git a/firefox-ios/Shared/Supporting Files/dsb.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/dsb.lproj/EditAddress.strings index 0421095ce1ed..81356f6d05cb 100644 --- a/firefox-ios/Shared/Supporting Files/dsb.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/dsb.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "Adresa njedajo se składowaś"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Adresa njedajo se wótwónoźeś"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Hyšći raz wopytaś"; diff --git a/firefox-ios/Shared/Supporting Files/dsb.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/dsb.lproj/Toolbar.strings new file mode 100644 index 000000000000..889d0875fbdd --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/dsb.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Nowy rejtarik"; + diff --git a/firefox-ios/Shared/Supporting Files/el.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/el.lproj/EditAddress.strings index 2d7531c75c33..9759c32ba665 100644 --- a/firefox-ios/Shared/Supporting Files/el.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/el.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "Δεν ήταν δυνατή η αποθήκευση της διεύθυνσης"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Δεν ήταν δυνατή η αφαίρεση της διεύθυνσης"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Δοκιμή ξανά"; diff --git a/firefox-ios/Shared/Supporting Files/el.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/el.lproj/Toolbar.strings new file mode 100644 index 000000000000..935028033f07 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/el.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Νέα καρτέλα"; + diff --git a/firefox-ios/Shared/Supporting Files/en-CA.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/en-CA.lproj/EditAddress.strings index e931684b6cae..bc5d40c3374b 100644 --- a/firefox-ios/Shared/Supporting Files/en-CA.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/en-CA.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "Address Couldn’t Be Saved"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Address Couldn’t Be Removed"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Try again"; diff --git a/firefox-ios/Shared/Supporting Files/en-CA.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/en-CA.lproj/Toolbar.strings new file mode 100644 index 000000000000..7784884c18f8 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/en-CA.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "New Tab"; + diff --git a/firefox-ios/Shared/Supporting Files/en-GB.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/en-GB.lproj/EditAddress.strings index cd1ebd0e3e37..a3521a221373 100644 --- a/firefox-ios/Shared/Supporting Files/en-GB.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/en-GB.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "Address Couldn’t Be Saved"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Address Couldn’t Be Removed"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Try again"; diff --git a/firefox-ios/Shared/Supporting Files/en-GB.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/en-GB.lproj/Toolbar.strings new file mode 100644 index 000000000000..7784884c18f8 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/en-GB.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "New Tab"; + diff --git a/firefox-ios/Shared/Supporting Files/en-US.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/en-US.lproj/EditAddress.strings index 1304bf15e803..02b1fa4defc1 100644 --- a/firefox-ios/Shared/Supporting Files/en-US.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/en-US.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "Address Couldn’t Be Saved"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Address Couldn’t Be Removed"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Try again"; diff --git a/firefox-ios/Shared/Supporting Files/en-US.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/en-US.lproj/Toolbar.strings new file mode 100644 index 000000000000..7784884c18f8 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/en-US.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "New Tab"; + diff --git a/firefox-ios/Shared/Supporting Files/es-AR.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/es-AR.lproj/EditAddress.strings index ee112aa7eb6e..cc42ad8969dc 100644 --- a/firefox-ios/Shared/Supporting Files/es-AR.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/es-AR.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "No se pudo guardar la dirección"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "No se pudo eliminar la dirección"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Probá de nuevo"; diff --git a/firefox-ios/Shared/Supporting Files/es-AR.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/es-AR.lproj/Toolbar.strings new file mode 100644 index 000000000000..f5b1dc1cc2e1 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/es-AR.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Nueva pestaña"; + diff --git a/firefox-ios/Shared/Supporting Files/es-CL.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/es-CL.lproj/EditAddress.strings index a96c54388ebd..75e8944a71a0 100644 --- a/firefox-ios/Shared/Supporting Files/es-CL.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/es-CL.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "No se pudo guardar la dirección"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "No se pudo eliminar la dirección"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Volver a intentarlo"; diff --git a/firefox-ios/Shared/Supporting Files/es-CL.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/es-CL.lproj/Toolbar.strings new file mode 100644 index 000000000000..f5b1dc1cc2e1 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/es-CL.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Nueva pestaña"; + diff --git a/firefox-ios/Shared/Supporting Files/es-MX.lproj/ActivityStream.strings b/firefox-ios/Shared/Supporting Files/es-MX.lproj/ActivityStream.strings new file mode 100644 index 000000000000..5ad67a81186b --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/es-MX.lproj/ActivityStream.strings @@ -0,0 +1,6 @@ +/* String used in the section title of the Bookmarks section on Home Screen. */ +"ActivityStream.Bookmarks.Title.v128" = "Marcadores"; + +/* Show all button text for Bookmarks items on the home page, which opens the Bookmarks panel when tapped. */ +"Bookmarks.Actions.More.v128" = "Mostrar todo"; + diff --git a/firefox-ios/Shared/Supporting Files/es-MX.lproj/Alerts.strings b/firefox-ios/Shared/Supporting Files/es-MX.lproj/Alerts.strings index 13d2d34182ae..f785b99e3198 100644 --- a/firefox-ios/Shared/Supporting Files/es-MX.lproj/Alerts.strings +++ b/firefox-ios/Shared/Supporting Files/es-MX.lproj/Alerts.strings @@ -1,3 +1,6 @@ +/* When tapping the fire icon in private mode, an alert comes up asking to confirm if you want to delete all browsing data and end your private session. This is the body text for the alert. */ +"Alerts.FeltDeletion.Body.v122" = "Cierra todas las pestañas privadas y elimina el historial, las cookies y todos los demás datos del sitio."; + /* When tapping the fire icon in private mode, an alert comes up asking to confirm if you want to delete all browsing data and end your private session. This is the cancel action for the alert, cancelling ending your session. */ "Alerts.FeltDeletion.Button.Cancel.v122" = "Cancelar"; diff --git a/firefox-ios/Shared/Supporting Files/es-MX.lproj/CustomizeFirefoxHome.strings b/firefox-ios/Shared/Supporting Files/es-MX.lproj/CustomizeFirefoxHome.strings index d76f70680ef0..ec19f4221d58 100644 --- a/firefox-ios/Shared/Supporting Files/es-MX.lproj/CustomizeFirefoxHome.strings +++ b/firefox-ios/Shared/Supporting Files/es-MX.lproj/CustomizeFirefoxHome.strings @@ -1,3 +1,6 @@ +/* In the settings menu, in the Firefox homepage customization section, this is the title for the option that allows users to toggle Bookmarks section on the Firefox homepage on or off */ +"Settings.Home.Option.Bookmarks.v128" = "Marcadores"; + /* In the settings menu, in the Firefox homepage customization section, this is the subtitle for the option that allows users to turn the Pocket Recommendations section on the Firefox homepage on or off. The placeholder is the pocket app name. */ "Settings.Home.Option.ThoughtProvokingStories.subtitle.v116" = "Artículos desarrollados por %@"; diff --git a/firefox-ios/Shared/Supporting Files/es-MX.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/es-MX.lproj/EditAddress.strings new file mode 100644 index 000000000000..fd22c013175e --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/es-MX.lproj/EditAddress.strings @@ -0,0 +1,36 @@ +/* Title for the cancel button in the remove address alert. */ +"Addresses.EditAddress.Alert.CancelButton.v129" = "Cancelar"; + +/* Title for the interface option where users can add a new address for autofill purposes. This facilitates quicker form completion by automatically filling in the user's address information. */ +"Addresses.EditAddress.AutofillAddAddressTitle.v129" = "Agregar dirección"; + +/* Label for the field where users input the city part of their address. This information is crucial for mail delivery and service provision, ensuring accurate city identification in autofill settings. */ +"Addresses.EditAddress.AutofillAddressCity.v129" = "Ciudad"; + +/* Label for the field where users can specify just the country, used in contexts where full address details are not required. Simplifies autofill when only country information is necessary. */ +"Addresses.EditAddress.AutofillAddressCountryOnly.v129" = "País"; + +/* Label for the country or region field in address forms, allowing users to specify their country or territorial region. This is fundamental for international mail and services, ensuring autofill accuracy across borders. */ +"Addresses.EditAddress.AutofillAddressCountryRegion.v129" = "País o región"; + +/* Label for the county field, crucial for addressing in regions where county lines play a key role in postal services. Enhances autofill accuracy by including county information. */ +"Addresses.EditAddress.AutofillAddressCounty.v129" = "Municipio"; + +/* Label for the email address field, where users input their email. Critical for digital communication and account verification, this ensures email addresses are autofilled accurately. */ +"Addresses.EditAddress.AutofillAddressEmail.v129" = "Correo electrónico"; + +/* Label for the postal code field, universally used in address forms to specify the area code for mail sorting. Essential for autofill to ensure mail and services are accurately routed. */ +"Addresses.EditAddress.AutofillAddressPostalCode.v129" = "Código postal"; + +/* Label for the prefecture field, essential for addresses in countries like Japan where prefectures are a major administrative division. Aids in precise location specification for autofill. */ +"Addresses.EditAddress.AutofillAddressPrefecture.v129" = "Prefectura"; + +/* Label for the province field, required in countries where provinces are a primary administrative division. Helps in pinpointing the user's location more accurately for autofill purposes. */ +"Addresses.EditAddress.AutofillAddressProvince.v129" = "Provincia"; + +/* Label for the state field, a necessary component of addresses in many countries, especially the USA. It ensures that state-specific details are correctly filled in forms using autofill. */ +"Addresses.EditAddress.AutofillAddressState.v129" = "Estado"; + +/* Label for the button to cancel the current autofill operation or exit the form without saving changes. Provides users with an option to back out of a process without making any modifications. */ +"Addresses.EditAddress.AutofillCancelButton.v129" = "Cancelar"; + diff --git a/firefox-ios/Shared/Supporting Files/es-MX.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/es-MX.lproj/EnhancedTrackingProtection.strings new file mode 100644 index 000000000000..8ab36f8966a0 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/es-MX.lproj/EnhancedTrackingProtection.strings @@ -0,0 +1,3 @@ +/* The title for the privacy settings button inside the enhanced tracking protection screen. */ +"Menu.EnhancedTrackingProtection.PrivacySettings.Title.v128" = "Ajustes de privacidad"; + diff --git a/firefox-ios/Shared/Supporting Files/es-MX.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/es-MX.lproj/Microsurvey.strings new file mode 100644 index 000000000000..3b50a27cac72 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/es-MX.lproj/Microsurvey.strings @@ -0,0 +1,15 @@ +/* On top of the bottom toolbar, there can be a microsurvey prompt, this is the title for the button that appears on the prompt that allows the user to tap on and navigates them to the microsurvey to respond to. */ +"Microsurvey.Prompt.Button.v127" = "Continuar"; + +/* On top of the bottom toolbar, there can be a microsurvey prompt, this is the accessibility label for the close button that appears on the prompt that allows the user to dismiss the microsurvey prompt. */ +"Microsurvey.Prompt.Close.Button.AccessibilityLabel.v127" = "Cerrar"; + +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this the title of button on the survey that a user can tap on to submit their responses. */ +"Microsurvey.Survey.Button.v127" = "Enviar"; + +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label for close button that dismisses the sheet. */ +"Microsurvey.Survey.Close.Button.AccessibilityLabel.v127" = "Cerrar"; + +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was selected. */ +"Microsurvey.Survey.RadioButton.Selected.AccessibilityLabel.v129" = "Seleccionado"; + diff --git a/firefox-ios/Shared/Supporting Files/es-MX.lproj/Onboarding.strings b/firefox-ios/Shared/Supporting Files/es-MX.lproj/Onboarding.strings index 996ab7eff2ed..6bc0de69383c 100644 --- a/firefox-ios/Shared/Supporting Files/es-MX.lproj/Onboarding.strings +++ b/firefox-ios/Shared/Supporting Files/es-MX.lproj/Onboarding.strings @@ -16,6 +16,15 @@ /* String used to describe the option to continue to the next onboarding card in Firefox Onboarding screens. Placeholder is for the app name. */ "Onboarding.Customization.Intro.Continue.Action.v123" = "Personalizar %@"; +/* String used to describe the option to skip the customization cards in Firefox Onboarding screens and start browsing. */ +"Onboarding.Customization.Intro.Skip.Action.v123" = "Empieza a navegar"; + +/* String used to describe the title of the customization onboarding page in our Onboarding screens. Placeholder is for the app name. */ +"Onboarding.Customization.Intro.Title.v123" = "%@ te da el control"; + +/* String used to describe the option to save the user setting and continue to the next onboarding in Firefox Onboarding screens. */ +"Onboarding.Customization.Theme.Continue.Action.v123" = "Guardar y Continuar"; + /* On the theme customization onboarding card, the string used to describe the option to set the theme to dark theme from the available choices. */ "Onboarding.Customization.Theme.Dark.Action.v123" = "Oscuro"; diff --git a/firefox-ios/Shared/Supporting Files/es-MX.lproj/PasswordAutofill.strings b/firefox-ios/Shared/Supporting Files/es-MX.lproj/PasswordAutofill.strings index 6ee8a5e356e4..f2287ef67da0 100644 --- a/firefox-ios/Shared/Supporting Files/es-MX.lproj/PasswordAutofill.strings +++ b/firefox-ios/Shared/Supporting Files/es-MX.lproj/PasswordAutofill.strings @@ -4,3 +4,6 @@ /* This label is used in the password list screen header as a question, prompting the user if they want to use a saved password for logging in. */ "PasswordAutofill.UseSavedPasswordFromHeader.v124" = "¿Usar contraseña guardada?"; +/* Displayed inside the keyboard hint when a user is entering their login credentials and has at least one saved password. Indicates that there are stored passwords available for use in filling out the login form. */ +"PasswordAutofill.UseSavedPasswordFromKeyboard.v124" = "Usar contraseña guardada"; + diff --git a/firefox-ios/Shared/Supporting Files/es-MX.lproj/RememberCard.strings b/firefox-ios/Shared/Supporting Files/es-MX.lproj/RememberCard.strings index 574f4a208148..0732cf6e799c 100644 --- a/firefox-ios/Shared/Supporting Files/es-MX.lproj/RememberCard.strings +++ b/firefox-ios/Shared/Supporting Files/es-MX.lproj/RememberCard.strings @@ -4,3 +4,9 @@ /* This value is used as the title for the remember credit card page */ "CreditCard.RememberCard.MainTitle.v122" = "¿Guardar esta tarjeta de forma segura?"; +/* This value is used as the title for the Not Now button in the remember credit card page */ +"CreditCard.RememberCard.SecondaryButtonTitle.v115" = "Ahora no"; + +/* This value is used as the toast message for the saving success alert in the remember credit card page */ +"CreditCard.RememberCard.SecondaryButtonTitle.v116" = "Nueva tarjeta guardada"; + diff --git a/firefox-ios/Shared/Supporting Files/es-MX.lproj/ScanQRCode.strings b/firefox-ios/Shared/Supporting Files/es-MX.lproj/ScanQRCode.strings new file mode 100644 index 000000000000..30a711e3be60 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/es-MX.lproj/ScanQRCode.strings @@ -0,0 +1,3 @@ +/* Allow button to open URL from scanned QR Code */ +"ScanQRCode.ConfirmOpenURL.AllowButton.v129" = "Permitir"; + diff --git a/firefox-ios/Shared/Supporting Files/es-MX.lproj/SelectCreditCard.strings b/firefox-ios/Shared/Supporting Files/es-MX.lproj/SelectCreditCard.strings new file mode 100644 index 000000000000..bc69098b0ea7 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/es-MX.lproj/SelectCreditCard.strings @@ -0,0 +1,3 @@ +/* This value is used as the title for the select a credit card from list of available cards. */ +"CreditCard.SelectCreditCard.MainTitle.v122" = "Usar tarjeta guardada"; + diff --git a/firefox-ios/Shared/Supporting Files/es-MX.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/es-MX.lproj/Settings.strings index dbf2d3095aca..dda9228169d0 100644 --- a/firefox-ios/Shared/Supporting Files/es-MX.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/es-MX.lproj/Settings.strings @@ -1,15 +1,48 @@ +/* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ +"Addresses.Settings.SavedAddressesSectionTitle.v124" = "DIRECCIONES GUARDADAS"; + +/* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ +"Addresses.Settings.Switch.Description.v124" = "Incluye números de teléfono y direcciones de correo electrónico"; + +/* Title label for user to use the toggle settings to allow saving and autofilling of addresses for webpages. */ +"Addresses.Settings.Switch.Title.v124" = "Guardar y completar direcciones"; + +/* Displayed inside the keyboard hint when a user is entering their address and has at least one saved address. Indicates that there are stored addresses available for use in filling out a form. */ +"Addresses.Settings.UseSavedAddressFromKeyboard.v124" = "Usar dirección guardada"; + +/* Accessibility label for the add button in autofill settings screen. Pressing this button presents a modal that allows users to add a card by entering the credit card information. */ +"CreditCard.Settings.AddCard.AccessibilityLabel.v121" = "Agregar tarjeta"; + /* Description label for when there are no credit cards shown in credit card list in autofill settings screen. */ "CreditCard.Settings.EmptyListDescription.v112" = "Guarda la información de tu tarjeta de forma segura para pagar más rápido la próxima vez."; +/* When a user is in the process or has finished making a purchase with a card not saved in Firefox's list of stored cards, we ask the user if they would like to save this card for future purchases. This string indicates to users that they can deny Firefox from remembering the card that is being used. */ +"CreditCard.Settings.NotNow.v122" = "Ahora no"; + +/* When a user is in the process or has finished making a purchase with a card not saved in Firefox's list of stored cards, we ask the user if they would like to save this card for future purchases. This string is a title string of the overall message that asks the user if they would like Firefox to remember the card that is being used. */ +"CreditCard.Settings.RememberThisCard.v122" = "¿Guardar esta tarjeta de forma segura?"; + +/* When a user is in the process or has finished making a purchase with a remembered card, and if the credit card information doesn't match the contents of the stored information of that card, we show this string. We ask this user if they would like Firefox update the staled information of that credit card. */ +"CreditCard.Settings.UpdateThisCard.v122" = "¿Actualizar tarjeta?"; + +/* When a user is in the process or has finished making a purchase with a card not saved in Firefox's list of stored cards, we ask the user if they would like to save this card for future purchases. This string asks users to confirm if they would like Firefox to remember the card that is being used. */ +"CreditCard.Settings.Yes.v122" = "Actualizar"; + /* When a user is in the process of making a purchase and has at least one saved credit card, a view above the keyboard shows actions a user can take. When tapping this label, the keyboard will dismiss from view. */ "CreditCards.Settings.Done.v114" = "Hecho"; /* When a user is in the process or has finished making a purchase, and has at least one card saved, we show this tappable string. This indicates to users that they can navigate to their list of stored credit cards in the app's credit card list screen. */ "CreditCards.Settings.ManageCards.v112" = "Administrar tarjetas"; +/* When a user is in the process of making a purchase, and has at least one saved card, we show this label used as a title. This indicates to the user that there are stored cards available for use on this pending purchase. */ +"CreditCards.Settings.UseASavedCard.v122" = "Usar tarjeta guardada"; + /* When a user is in the process of making a purchase, and has at least one saved card, we show this label inside the keyboard hint. This indicates to the user that there are stored cards available for use on this pending purchase. */ "CreditCards.Settings.UseSavedCardFromKeyboard.v112" = "Usar tarjeta guardada"; +/* Settings section title for the old Firefox account */ +"FxA.FirefoxAccount.v119" = "Cuenta"; + /* Label used as an item in Settings screen. When touched, it will take user to address autofill settings page to that will allow user to add or modify saved addresses to allow for autofill in a webpage. */ "Settings.AddressAutofill.Title.v126" = "Direcciones"; diff --git a/firefox-ios/Shared/Supporting Files/es-MX.lproj/Shopping.strings b/firefox-ios/Shared/Supporting Files/es-MX.lproj/Shopping.strings index 0f949afbd62b..353c2ae4fbfd 100644 --- a/firefox-ios/Shared/Supporting Files/es-MX.lproj/Shopping.strings +++ b/firefox-ios/Shared/Supporting Files/es-MX.lproj/Shopping.strings @@ -61,3 +61,18 @@ /* Title for info card when Fakespot cannot analyze reviews for a certain product type */ "Shopping.InfoCard.FakespotDoesNotAnalyzeReviews.Title.v120" = "No se pueden verificar estas reseñas"; +/* Primary action title for info card when the product needs analysis */ +"Shopping.InfoCard.NeedsAnalysis.PrimaryAction.v120" = "Comprobar ahora"; + +/* Text for the secondary button of the Shopping Experience Opt In onboarding Card (Fakespot) */ +"Shopping.OptInCard.SecondaryButton.Title.v120" = "Ahora no"; + +/* Show Firefox Browser Terms of Use page from the Privacy section in the Shopping Experience Opt In onboarding Card (Fakespot). See https://www.mozilla.org/privacy/firefox/ */ +"Shopping.OptInCard.TermsOfUse.Button.Title.v120" = "Términos de uso"; + +/* Show Fakespot Terms of Use page in the Shopping Experience Opt In onboarding Card (Fakespot). The parameter will be replace by the Fakespot name. */ +"Shopping.OptInCard.TermsOfUse.Button.Title.v123" = "Términos de uso de %@"; + +/* Accessibility label for the Grade labels used in 'How we determine review quality' card and 'How reliable are these reviews' card displayed in the shopping review quality bottom sheet. The placeholder will be replaced by a grade letter (e.g. A). The grading system contains letters from A-F. */ +"Shopping.ReliabilityScore.Grade.A11y.Label.v120" = "Calificación %@"; + diff --git a/firefox-ios/Shared/Supporting Files/es-MX.lproj/TabLocation.strings b/firefox-ios/Shared/Supporting Files/es-MX.lproj/TabLocation.strings new file mode 100644 index 000000000000..95b4ca951d46 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/es-MX.lproj/TabLocation.strings @@ -0,0 +1,15 @@ +/* Accessibility label for the security icon in url bar */ +"TabLocation.ETP.On.NotSecure.A11y.Label.v119" = "Conexión no segura"; + +/* Accessibility label for the security icon in url bar */ +"TabLocation.ETP.On.Secure.A11y.Label.v119" = "Conexión segura"; + +/* Accessibility label for the share button in url bar */ +"TabLocation.Share.A11y.Label.v119" = "Compartir esta página"; + +/* Large content title for the share button. This title is displayed when using accessible font sizes is enabled */ +"TabLocation.ShareButton.AccessibilityLabel.v122" = "Compartir"; + +/* Large content title for the button shown in editing mode to remove this site from the top sites panel. */ +"TopSites.RemoveButton.LargeContentTitle.v122" = "Eliminar página"; + diff --git a/firefox-ios/Shared/Supporting Files/es-MX.lproj/TabsTray.strings b/firefox-ios/Shared/Supporting Files/es-MX.lproj/TabsTray.strings index 7b4c0e2c280c..0c9e8adfe27e 100644 --- a/firefox-ios/Shared/Supporting Files/es-MX.lproj/TabsTray.strings +++ b/firefox-ios/Shared/Supporting Files/es-MX.lproj/TabsTray.strings @@ -7,3 +7,9 @@ /* When the user closes tabs in the tab tray, a popup will appear informing them how many tabs were closed. This is the text for the popup. The placeholder is the number of tabs */ "CloseTabsToast.Title.v113" = "Pestañas cerradas: %d"; +/* This is the swipe action title for closing an inactive tab by swiping, located in the Inactive Tabs section of the Tabs Tray */ +"InactiveTabs.TabTray.CloseSwipeActionTitle.v115" = "Cerrar"; + +/* Button label to sync tabs in your account */ +"TabsTray.SyncTabs.SyncTabsButton.Title.v119" = "Sincronizar pestañas"; + diff --git a/firefox-ios/Shared/Supporting Files/es-MX.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/es-MX.lproj/Toolbar.strings new file mode 100644 index 000000000000..f5b1dc1cc2e1 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/es-MX.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Nueva pestaña"; + diff --git a/firefox-ios/Shared/Supporting Files/es-MX.lproj/UpdateCard.strings b/firefox-ios/Shared/Supporting Files/es-MX.lproj/UpdateCard.strings new file mode 100644 index 000000000000..1a617b11edff --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/es-MX.lproj/UpdateCard.strings @@ -0,0 +1,6 @@ +/* This value is used as the title for the Not Now button in the update credit card page */ +"CreditCard.UpdateCard.NotNowButtonTitle.v115" = "Ahora no"; + +/* This value is used as the title for the button in the update credit card page. It indicates the action to update the details f9 the card. */ +"CreditCard.UpdateCard.YesButtonTitle.v122" = "Actualizar"; + diff --git a/firefox-ios/Shared/Supporting Files/fi.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/fi.lproj/EditAddress.strings index 3f2b1bdd11a8..8e234f0a3997 100644 --- a/firefox-ios/Shared/Supporting Files/fi.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/fi.lproj/EditAddress.strings @@ -97,6 +97,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "Osoitetta ei voitu tallentaa"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Osoitetta ei voitu poistaa"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Yritä uudelleen"; diff --git a/firefox-ios/Shared/Supporting Files/fi.lproj/Shopping.strings b/firefox-ios/Shared/Supporting Files/fi.lproj/Shopping.strings index 188063865907..85a6733f9c35 100644 --- a/firefox-ios/Shared/Supporting Files/fi.lproj/Shopping.strings +++ b/firefox-ios/Shared/Supporting Files/fi.lproj/Shopping.strings @@ -163,6 +163,12 @@ /* Adjusted rating label from How we determine review quality card displayed in the shopping review quality bottom sheet. The *text inside asterisks* denotes part of the string to bold, please leave the text inside the '*' so that it is bolded correctly. */ "Shopping.ReviewQualityCard.AdjustedRating.Label.v120" = "*Oikaistu arvosana* perustuu vain niihin arvosteluihin, jotka koemme luotettaviksi."; +/* Accessibility label for the up chevron, from 'How we determine review quality' card displayed in the shopping review quality bottom sheet. */ +"Shopping.ReviewQualityCard.Collapse.AccessibilityLabel.v120" = "Supista \"Kuinka määritämme arvostelun laadun\"-kortti"; + +/* Accessibility label for the down chevron, from 'How we determine review quality' card displayed in the shopping review quality bottom sheet. */ +"Shopping.ReviewQualityCard.Expand.AccessibilityLabel.v120" = "Laajenna \"Kuinka määritämme arvostelun laadun\"-kortti"; + /* Title of the 'How we determine review quality' card displayed in the shopping review quality bottom sheet. */ "Shopping.ReviewQualityCard.Label.Title.v120" = "Kuinka määritämme arvostelun laadun"; @@ -193,6 +199,9 @@ /* Accessibility label for the recommended products label and switch, grouped together. The first placeholder is for the recommended products label, and the second placeholder is for the state of the switch: On/Off. */ "Shopping.SettingsCard.Expand.GroupedRecommendedProductsAndSwitch.AccessibilityLabel.v123" = "%1$@, kytkinpainike, %2$@."; +/* Action title of the footer underneath the Settings Card displayed in the shopping review quality bottom sheet. The first parameter will be replaced by the Fakespot app name and the second parameter by the company name of Mozilla. */ +"Shopping.SettingsCard.Footer.Action.v120" = "Arvostelujen tarkistuksen tarjoaa %2$@n %1$@"; + /* Title of the settings card displayed in the shopping review quality bottom sheet. */ "Shopping.SettingsCard.Label.Title.v120" = "Asetukset"; diff --git a/firefox-ios/Shared/Supporting Files/fi.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/fi.lproj/Toolbar.strings new file mode 100644 index 000000000000..d39f497a4442 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/fi.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Uusi välilehti"; + diff --git a/firefox-ios/Shared/Supporting Files/fr.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/fr.lproj/EditAddress.strings index 175198fce209..366f9942c18b 100644 --- a/firefox-ios/Shared/Supporting Files/fr.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/fr.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "L’adresse n’a pas pu être enregistrée"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "L’adresse n’a pas pu être supprimée"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Réessayer"; diff --git a/firefox-ios/Shared/Supporting Files/fr.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/fr.lproj/Toolbar.strings new file mode 100644 index 000000000000..451c964e1463 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/fr.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Nouvel onglet"; + diff --git a/firefox-ios/Shared/Supporting Files/he.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/he.lproj/EditAddress.strings index 013eaa1ccf22..036996a988b3 100644 --- a/firefox-ios/Shared/Supporting Files/he.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/he.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "לא ניתן היה לשמור את הכתובת"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "לא ניתן היה להסיר את הכתובת"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "ניסיון חוזר"; diff --git a/firefox-ios/Shared/Supporting Files/he.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/he.lproj/Toolbar.strings new file mode 100644 index 000000000000..fe5da6b97990 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/he.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "לשונית חדשה"; + diff --git a/firefox-ios/Shared/Supporting Files/hsb.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/hsb.lproj/EditAddress.strings index 10831add7c37..6be3e86aa9bf 100644 --- a/firefox-ios/Shared/Supporting Files/hsb.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/hsb.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "Adresa njeda so składować"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Adresa njeda so wotstronić"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Hišće raz spytać"; diff --git a/firefox-ios/Shared/Supporting Files/hsb.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/hsb.lproj/Toolbar.strings new file mode 100644 index 000000000000..915c4b516f0c --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hsb.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Nowy rajtark"; + diff --git a/firefox-ios/Shared/Supporting Files/hy-AM.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/hy-AM.lproj/EditAddress.strings index f4a7de7e203c..6b6df38a981f 100644 --- a/firefox-ios/Shared/Supporting Files/hy-AM.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/hy-AM.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "Հասցեն չհաջողվեց պահել"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Հասցեն չհաջողվեց հեռացնել"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Կրկին փորձել"; diff --git a/firefox-ios/Shared/Supporting Files/hy-AM.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/hy-AM.lproj/Toolbar.strings new file mode 100644 index 000000000000..87db8eee8d13 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hy-AM.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Նոր ներդիր"; + diff --git a/firefox-ios/Shared/Supporting Files/ia.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/ia.lproj/EditAddress.strings index 49f01ede7105..2f248c55e4d4 100644 --- a/firefox-ios/Shared/Supporting Files/ia.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/ia.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "Le adresse non pote esser salvate"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Le adresse non pote esser removite"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Retentar"; diff --git a/firefox-ios/Shared/Supporting Files/ia.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/ia.lproj/Toolbar.strings new file mode 100644 index 000000000000..238d35aa1633 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/ia.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Nove scheda"; + diff --git a/firefox-ios/Shared/Supporting Files/is.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/is.lproj/EditAddress.strings index 438cb7743db7..6ce85425d408 100644 --- a/firefox-ios/Shared/Supporting Files/is.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/is.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "Ekki tókst að vista heimilisfang"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Ekki tókst að fjarlægja heimilisfang"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Reyna aftur"; diff --git a/firefox-ios/Shared/Supporting Files/is.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/is.lproj/Toolbar.strings new file mode 100644 index 000000000000..ae327d8f3585 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/is.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Nýr flipi"; + diff --git a/firefox-ios/Shared/Supporting Files/it.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/it.lproj/EditAddress.strings index f0dcab6067be..b5edad48f5a9 100644 --- a/firefox-ios/Shared/Supporting Files/it.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/it.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "Impossibile salvare l’indirizzo"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Impossibile rimuovere l’indirizzo"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Riprova"; diff --git a/firefox-ios/Shared/Supporting Files/it.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/it.lproj/Toolbar.strings new file mode 100644 index 000000000000..58f5638fe011 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/it.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Nuova scheda"; + diff --git a/firefox-ios/Shared/Supporting Files/ja.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/ja.lproj/EditAddress.strings new file mode 100644 index 000000000000..c704d5ba9cb9 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/ja.lproj/EditAddress.strings @@ -0,0 +1,141 @@ +/* Title for the cancel button in the remove address alert. */ +"Addresses.EditAddress.Alert.CancelButton.v129" = "キャンセル"; + +/* Message explaining the consequences of removing an address from all synced devices. */ +"Addresses.EditAddress.Alert.Message.v129" = "同期しているすべての端末から住所が削除されます。"; + +/* Title for the remove button in the remove address alert. */ +"Addresses.EditAddress.Alert.RemoveButton.v129" = "削除"; + +/* Title for the alert indicating the action to remove an address. */ +"Addresses.EditAddress.Alert.Title.v129" = "住所を削除"; + +/* Title for the interface option where users can add a new address for autofill purposes. This facilitates quicker form completion by automatically filling in the user's address information. */ +"Addresses.EditAddress.AutofillAddAddressTitle.v129" = "住所を追加"; + +/* Label for the area field, allowing users to specify a particular area within a city or region. This detail can improve the specificity and accuracy of autofilled addresses. */ +"Addresses.EditAddress.AutofillAddressArea.v129" = "地区"; + +/* Label for the field where users input the city part of their address. This information is crucial for mail delivery and service provision, ensuring accurate city identification in autofill settings. */ +"Addresses.EditAddress.AutofillAddressCity.v129" = "市"; + +/* Label for the field where users can specify just the country, used in contexts where full address details are not required. Simplifies autofill when only country information is necessary. */ +"Addresses.EditAddress.AutofillAddressCountryOnly.v129" = "国"; + +/* Label for the country or region field in address forms, allowing users to specify their country or territorial region. This is fundamental for international mail and services, ensuring autofill accuracy across borders. */ +"Addresses.EditAddress.AutofillAddressCountryRegion.v129" = "国または地域"; + +/* Label for the county field, crucial for addressing in regions where county lines play a key role in postal services. Enhances autofill accuracy by including county information. */ +"Addresses.EditAddress.AutofillAddressCounty.v129" = "郡"; + +/* Label for the department field, used in countries like France and Colombia where departments are a key administrative division. Ensures correct departmental information is autofilled. */ +"Addresses.EditAddress.AutofillAddressDepartment.v129" = "県"; + +/* Label for the district field in the address form, allowing users to specify their district for more precise location identification. This aids in refining address details for accurate autofill. */ +"Addresses.EditAddress.AutofillAddressDistrict.v129" = "区"; + +/* Label for the Do/Si field, pertinent to addresses in South Korea. Do/Si refers to provincial level divisions, and specifying this enhances address accuracy in autofill settings. */ +"Addresses.EditAddress.AutofillAddressDoSi.v129" = "道/市"; + +/* Label for the Eircode field, specific to Ireland. It's a unique postal code system that helps in precise location identification, enhancing the effectiveness of autofill. */ +"Addresses.EditAddress.AutofillAddressEircode.v129" = "Eircode"; + +/* Label for the email address field, where users input their email. Critical for digital communication and account verification, this ensures email addresses are autofilled accurately. */ +"Addresses.EditAddress.AutofillAddressEmail.v129" = "メールアドレス"; + +/* Label for the emirate field, essential for addresses in the United Arab Emirates. Including emirate details ensures the autofill feature accurately represents user addresses. */ +"Addresses.EditAddress.AutofillAddressEmirate.v129" = "首長国"; + +/* Label for the field where users specify the name of an island, if applicable. Important for addresses in archipelagic regions, aiding in precise location identification during autofill. */ +"Addresses.EditAddress.AutofillAddressIsland.v129" = "島"; + +/* Label for the field where the user inputs their full name as part of an address form. Essential for personalized form submissions and ensuring information accuracy in autofilled forms. */ +"Addresses.EditAddress.AutofillAddressName.v129" = "氏名"; + +/* Label for the field where users can input the name of their neighborhood. This detail adds precision to addresses, especially in densely populated areas, improving the accuracy of autofill. */ +"Addresses.EditAddress.AutofillAddressNeighborhood.v129" = "地域"; + +/* Label for the oblast field, relevant for addresses in countries like Russia and Ukraine. Oblasts are a significant administrative division, and their specification aids in autofill accuracy. */ +"Addresses.EditAddress.AutofillAddressOblast.v129" = "州"; + +/* Label for the input field designated for the organization's name related to the address. Helps in distinguishing addresses used for business or personal purposes in autofill settings. */ +"Addresses.EditAddress.AutofillAddressOrganization.v129" = "組織名"; + +/* Label for the parish field, significant in places where parishes are used for local administration and addressing. Ensures users can specify parish details for better autofill accuracy. */ +"Addresses.EditAddress.AutofillAddressParish.v129" = "教区"; + +/* Label for the PIN (Postal Index Number) field, used in India. It's a code representing a specific area, crucial for accurate mail delivery and autofill functionality. */ +"Addresses.EditAddress.AutofillAddressPin.v129" = "PIN"; + +/* Label for the postal code field, universally used in address forms to specify the area code for mail sorting. Essential for autofill to ensure mail and services are accurately routed. */ +"Addresses.EditAddress.AutofillAddressPostalCode.v129" = "郵便番号"; + +/* Label for the post town field, used primarily in the UK and some other regions for mail sorting. Essential for users in applicable areas to specify for correct mail delivery through autofill. */ +"Addresses.EditAddress.AutofillAddressPostTown.v129" = "ポストタウン"; + +/* Label for the prefecture field, essential for addresses in countries like Japan where prefectures are a major administrative division. Aids in precise location specification for autofill. */ +"Addresses.EditAddress.AutofillAddressPrefecture.v129" = "都道府県"; + +/* Label for the province field, required in countries where provinces are a primary administrative division. Helps in pinpointing the user's location more accurately for autofill purposes. */ +"Addresses.EditAddress.AutofillAddressProvince.v129" = "州/省/県"; + +/* Label for the state field, a necessary component of addresses in many countries, especially the USA. It ensures that state-specific details are correctly filled in forms using autofill. */ +"Addresses.EditAddress.AutofillAddressState.v129" = "州"; + +/* Label for the suburb field, enabling users to add suburb details to their address. This is important for accurate delivery and services in suburban areas, enhancing autofill functionality. */ +"Addresses.EditAddress.AutofillAddressSuburb.v129" = "地区"; + +/* Label for the telephone number field, allowing users to input their contact number. This is essential for communication and service provision, ensuring contact details are autofilled correctly. */ +"Addresses.EditAddress.AutofillAddressTel.v129" = "電話番号"; + +/* Label for the input field for the townland, a specific type of land division used in rural areas. Enhances address detail for users in regions where townlands are a common addressing component. */ +"Addresses.EditAddress.AutofillAddressTownland.v129" = "タウンランド"; + +/* Label for the field to input the name of a village or township. This is crucial for addresses in rural areas, ensuring the autofill feature accurately captures all necessary geographical details. */ +"Addresses.EditAddress.AutofillAddressVillageTownship.v129" = "村または郡区"; + +/* Label for the ZIP code field, primarily used in the United States for mail sorting. Key for autofill to accurately complete addresses for shipping, billing, and service provision. */ +"Addresses.EditAddress.AutofillAddressZip.v129" = "ZIP Code"; + +/* Label for the button to cancel the current autofill operation or exit the form without saving changes. Provides users with an option to back out of a process without making any modifications. */ +"Addresses.EditAddress.AutofillCancelButton.v129" = "キャンセル"; + +/* Title for the option allowing users to edit an existing saved address. This is used within the settings for autofill, enabling users to update their address details for accurate form autofilling. */ +"Addresses.EditAddress.AutofillEditAddressTitle.v129" = "住所の編集"; + +/* Title for the input field where users can enter their street address. This is used within the settings for autofill, allowing users to provide their street address for accurate form autofilling. */ +"Addresses.EditAddress.AutofillEditStreetAddressTitle.v129" = "番地・通り名"; + +/* Label for the button to save the current address details entered or edited by the user. This action confirms the user's changes and updates their autofill settings accordingly. */ +"Addresses.EditAddress.AutofillSaveButton.v129" = "保存"; + +/* Title for the option allowing users to view an existing saved address. This is used within the settings for autofill, enabling users to see their address details for accurate form autofilling. */ +"Addresses.EditAddress.AutofillViewAddressTitle.v129" = "住所を表示"; + +/* Button label for closing the view where user can view their address info. */ +"Addresses.EditAddress.CloseNavBarButtonLabel.v129" = "閉じる"; + +/* Button label for editing the address details shown in the form. */ +"Addresses.EditAddress.EditNavBarButtonLabel.v129" = "編集"; + +/* Title for button that offers the user the option to remove an address. */ +"Addresses.EditAddress.RemoveAddressButtonTitle.v129" = "住所を削除"; + +/* Toast message confirming that an address has been successfully removed. */ +"Addresses.Toast.AddressRemovedConfirmation.v129" = "住所を削除しました"; + +/* Toast message confirming that an address has been successfully saved. */ +"Addresses.Toast.AddressSavedConfirmation.v129" = "住所を保存しました"; + +/* Toast message indicating an error occurred while trying to save an address. */ +"Addresses.Toast.AddressSaveError.v129" = "住所を保存できませんでした"; + +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "住所を削除できませんでした"; + +/* Suggestion to try again after an error occurred while trying to save an address. */ +"Addresses.Toast.AddressSaveRetrySuggestion.v129" = "再試行"; + +/* Toast message confirming that an address has been successfully updated. */ +"Addresses.Toast.AddressUpdatedConfirmation.v129" = "住所を更新しました"; + diff --git a/firefox-ios/Shared/Supporting Files/ja.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/ja.lproj/EnhancedTrackingProtection.strings index 0c59e2f5c514..0ad9e3f6db33 100644 --- a/firefox-ios/Shared/Supporting Files/ja.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/ja.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,15 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "安全でない接続"; +/* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "クロスサイトトラッキング Cookie: %@"; + +/* Text to let users know how many fingerprinters were blocked on the current website. The placeholder will show the number of fingerprinters detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.Fingerprinter.v129" = "フィンガープリント: %@"; + +/* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "ソーシャルメディアトラッカー: %@"; + /* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked Text to let users know that no trackers were found on the current website. */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "ブロックされた追跡: %@"; @@ -54,6 +63,9 @@ /* A switch to disable enhanced tracking protection inside the menu. */ "Menu.EnhancedTrackingProtection.SwitchOff.Text.v128" = "保護機能がオフになっています。再度オンにすることをおすすめします。"; +/* A switch to disable enhanced tracking protection inside the menu. */ +"Menu.EnhancedTrackingProtection.SwitchOff.Text.v129" = "保護機能がオフになっています。再度オンにすることをおすすめします。"; + /* A switch to disable enhanced tracking protection inside the menu. */ "Menu.EnhancedTrackingProtection.SwitchOn.Text.v128" = "このサイトでの動作がおかしい場合は、オフにしてみてください。"; diff --git a/firefox-ios/Shared/Supporting Files/ja.lproj/PasswordAutofill.strings b/firefox-ios/Shared/Supporting Files/ja.lproj/PasswordAutofill.strings index c756d6cfa2a5..7ea005aecc7b 100644 --- a/firefox-ios/Shared/Supporting Files/ja.lproj/PasswordAutofill.strings +++ b/firefox-ios/Shared/Supporting Files/ja.lproj/PasswordAutofill.strings @@ -1,3 +1,6 @@ +/* This label is used in a cell found in the list of autofill login options in place of an actual username to denote that no username was saved for this login */ +"PasswordAutofill.LoginListCellNoUsername.v129" = "(ユーザー名なし)"; + /* This label is used for a button in the password list screen allowing users to manage their saved passwords. It's meant to direct users to where they can add, remove, or edit their saved passwords. */ "PasswordAutofill.ManagePasswordsButton.v124" = "パスワードを管理"; diff --git a/firefox-ios/Shared/Supporting Files/ja.lproj/ScanQRCode.strings b/firefox-ios/Shared/Supporting Files/ja.lproj/ScanQRCode.strings new file mode 100644 index 000000000000..bc8c1ef8b3ad --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/ja.lproj/ScanQRCode.strings @@ -0,0 +1,9 @@ +/* Allow button to open URL from scanned QR Code */ +"ScanQRCode.ConfirmOpenURL.AllowButton.v129" = "許可"; + +/* Deny button to cancel opening URL from scanned QR Code */ +"ScanQRCode.ConfirmOpenURL.DenyButton.v129" = "拒否"; + +/* Text of the prompt to ask user permission to open a URL from a scanned QR code. Placeholder is app name. */ +"ScanQRCode.ConfirmOpenURL.Message.v129" = "%@ で開くことを許可しますか?"; + diff --git a/firefox-ios/Shared/Supporting Files/ja.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/ja.lproj/Toolbar.strings new file mode 100644 index 000000000000..9c8d5e15bd21 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/ja.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "新規タブ"; + diff --git a/firefox-ios/Shared/Supporting Files/kab.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/kab.lproj/EditAddress.strings index fece81c5d278..cd476812f298 100644 --- a/firefox-ios/Shared/Supporting Files/kab.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/kab.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "Tansa ur tezmir ara ad tettwasekles"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Tansa ur tezmir ara ad tettwasekles"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Ɛreḍ tikkelt niḍen"; diff --git a/firefox-ios/Shared/Supporting Files/kab.lproj/Shopping.strings b/firefox-ios/Shared/Supporting Files/kab.lproj/Shopping.strings index 1aeb6be6ca7c..0a22e218d43b 100644 --- a/firefox-ios/Shared/Supporting Files/kab.lproj/Shopping.strings +++ b/firefox-ios/Shared/Supporting Files/kab.lproj/Shopping.strings @@ -55,6 +55,9 @@ /* Title of the review highlights displayed in the shopping review quality bottom sheet. */ "Shopping.HighlightsCard.Title.v120" = "Tamuɣli s wazal-is seg yilɣa imaynuten"; +/* Title for info card when Fakespot cannot analyze reviews for a certain product type */ +"Shopping.InfoCard.FakespotDoesNotAnalyzeReviews.Description.v120" = "Nesḥasef, ur nezmir ara ad nessefqed taɣara n ucegger i kra n wanawen n yifarisen. Amedya, tikarḍiwin n yisefkan d yisuddam n tvidyutin, aẓawan d wuraren."; + /* Title for info card when Fakespot cannot analyze reviews for a certain product type */ "Shopping.InfoCard.FakespotDoesNotAnalyzeReviews.Title.v120" = "Ur nezmir ara ad nsenqed tamawin-a"; @@ -82,6 +85,9 @@ /* Title for info card when there are not enough reviews for a product */ "Shopping.InfoCard.NotEnoughReviews.Title.v120" = "Ulac ddeqs n tamiwin akka tura"; +/* Description for the information card displayed by the review checker feature when the product the user is looking at is out of stock. This description is used for info card where the user can report if it's back in stock. */ +"Shopping.InfoCard.ProductNotInStock.Description.v121" = "Ma twalaḍ afaris-a yuɣal-d deg taggazt, ini-aɣ-t-id, ad nexdem akken ara nessefqed iceggiren."; + /* Primary action label for the information card displayed by the review checker feature when the product the user is looking at is out of stock. This primary action label is used for info card button where the user can report if it's back in stock. */ "Shopping.InfoCard.ProductNotInStock.PrimaryAction.v121" = "Mmel tuɣalin n ufaris deg tawsa"; @@ -118,6 +124,12 @@ /* Text for the disclaimer that appears underneath the rating image of the Shopping Experience Opt In onboarding Card (Fakespot). After the colon, there will be two links, each on their own line. The first link is to a Privacy policy. The second link is to Terms of use. */ "Shopping.OptInCard.Disclaimer.Text.v123" = "S ufran n “Ih, ɛreḍ-it” ad tqebleḍ iferdisen-a:"; +/* Label for the first paragraph of the Shopping Experience Opt In onboarding Card (Fakespot). The first parameter will be the website the user is coming from when viewing this screen (default Amazon). The second parameter will be replaced by the app name. This string is almost identical with 'Shopping.OptInCard.FirstParagraph.Description', but without Best Buy and Walmart websites, which are not available in many locales. */ +"Shopping.OptInCard.FirstParagraph.AmazonOnly.Description.v122" = "Wali taneflest n yiceggiren ɣef ufaris deg %1$@ send ad taɣeḍ. Amcegger, tamahilt tarmitant seg %2$@, tebna akken iwata deg yiminig."; + +/* Label for the first paragraph of the Shopping Experience Opt In onboarding Card (Fakespot). The first parameter will be the website the user is coming from when viewing this screen (default Amazon). The second parameter will be replaced by the app name. The third and fourth parameters will be the other two websites that are currently supported (Amazon, Best Buy or Walmart) besides the one used for the first parameter. */ +"Shopping.OptInCard.FirstParagraph.Description.v120" = "Wali taneflest n yiceggiren ɣef ufaris deg %1$@ send ad taɣeḍ. Amcegger, tamahilt tarmitant seg %2$@, tebna akken iwata deg yiminig. Tetteddu ɣef %3$@ akked %4$@."; + /* Label for the header of the Shopping Experience Opt In onboarding Card (Fakespot) */ "Shopping.OptInCard.HeaderLabel.Title.v120" = "Ɛreḍ amnir-nneɣ yettwamanen i timawin n ufaris"; @@ -160,12 +172,24 @@ /* Description of the reliability ratings for rating 'D' and 'F' displayed in the shopping review quality bottom sheet. */ "Shopping.ReviewQuality.ReliabilityRating.DF.Description.v120" = "Ilɣa yirinaflasen"; +/* Adjusted rating label from How we determine review quality card displayed in the shopping review quality bottom sheet. The *text inside asterisks* denotes part of the string to bold, please leave the text inside the '*' so that it is bolded correctly. */ +"Shopping.ReviewQualityCard.AdjustedRating.Label.v120" = "Alɣu n *amwati* yebna kan ɣef yiceggiren i nettwali deg-sen taneflest."; + /* Accessibility label for the up chevron, from 'How we determine review quality' card displayed in the shopping review quality bottom sheet. */ "Shopping.ReviewQualityCard.Collapse.AccessibilityLabel.v120" = "Fneẓ takarḍa n wamek ara nettguccul alɣu n tɣara"; /* Accessibility label for the down chevron, from 'How we determine review quality' card displayed in the shopping review quality bottom sheet. */ "Shopping.ReviewQualityCard.Expand.AccessibilityLabel.v120" = "Snefli takarḍa n wamek ara nettguccul alɣu n tɣara"; +/* Label of the headline from How we determine review quality card displayed in the shopping review quality bottom sheet. The first parameter will be replaced by the Fakespot app name and the second parameter by the company name of Mozilla. */ +"Shopping.ReviewQualityCard.Headline.Label.v120" = "Nesseqdac tatiknulujit AI seg %1$@ s %2$@ akken ad nessefqed arkad n yiceggiren n ufaris. Aya ad k-iεawen kan ad tektaleḍ taɣara n uceggir, mačči taɣara n ufaris."; + +/* Highlights label from How we determine review quality card displayed in the shopping review quality bottom sheet. The parameter substitutes the partner website the user is coming from. The *text inside asterisks* denotes part of the string to bold, please leave the text inside the '*' so that it is bolded correctly. */ +"Shopping.ReviewQualityCard.Highlights.Label.v120" = "*Asebruraq* seg %1@ n yiceggiren deg 80 n wussan-a ineggura i nettwali yella lettkal fell-asen."; + +/* Highlights label from How we determine review quality card displayed in the shopping review quality bottom sheet. The parameter substitutes the partner website the user is coming from. The *text inside asterisks* denotes part of the string to bold, please leave the text inside the '*' so that it is bolded correctly. */ +"Shopping.ReviewQualityCard.Highlights.Label.v126" = "*Asebruraq* seg %@ n yiceggiren deg 80 n wussan-a ineggura i nettwali yella lettkal fell-asen."; + /* Title of the 'How we determine review quality' card displayed in the shopping review quality bottom sheet. */ "Shopping.ReviewQualityCard.Label.Title.v120" = "Amek ara nettguccul alɣu n tɣara"; @@ -175,6 +199,15 @@ /* Mixed reviews label from How we determine review quality card displayed in the shopping review quality bottom sheet. */ "Shopping.ReviewQualityCard.MixedReviews.Label.v120" = "Nettwali iwellihen sdukklen iwellihen inaflasen d yiwellihen arinaflasen"; +/* Reliable reviews label from How we determine review quality card displayed in the shopping review quality bottom sheet. */ +"Shopping.ReviewQualityCard.ReliableReviews.Label.v120" = "Iceggiren igerrzen. Nettwali iceggiren zemren ad d-ilin seg yimsaɣen n tidet i d-yeǧǧan iceggiren imeɣtiyen, ur nebni ɣef tḥila."; + +/* Label of the sub headline from How we determine review quality card displayed in the shopping review quality bottom sheet. The *text inside asterisks* denotes part of the string to bold, please leave the text inside the '*' so that it is bolded correctly. */ +"Shopping.ReviewQualityCard.SubHeadline.Label.v120" = "Ad nmudd *asekkil n ugemmay* i yiceggiren ɣef yal afaris, seg A ɣer F."; + +/* Unreliable reviews label from How we determine review quality card displayed in the shopping review quality bottom sheet. */ +"Shopping.ReviewQualityCard.UnreliableReviews.Label.v120" = "Iceggiren ur yettwamanen ara. Nettwali iceggiren zemren ad ilin d tikellax neɣ kkan-d seg yimciggar ur nesεi azal."; + /* Accessibility label for the up chevron icon used to collapse or minimize the Settings Card within the shopping product review bottom sheet. */ "Shopping.SettingsCard.Collapse.AccessibilityLabel.v120" = "Fneẓ takarḍa n yiɣewwaren"; diff --git a/firefox-ios/Shared/Supporting Files/kab.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/kab.lproj/Toolbar.strings new file mode 100644 index 000000000000..143a987fc343 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/kab.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Iccer amaynut"; + diff --git a/firefox-ios/Shared/Supporting Files/kk.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/kk.lproj/EditAddress.strings index 677f6a149c85..c1ebd42982b8 100644 --- a/firefox-ios/Shared/Supporting Files/kk.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/kk.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "Адресті сақтау мүмкін емес"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Адресті өшіру мүмкін емес"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Қайтадан көру"; diff --git a/firefox-ios/Shared/Supporting Files/kk.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/kk.lproj/Toolbar.strings new file mode 100644 index 000000000000..1c21c2d5fa11 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/kk.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Жаңа бет"; + diff --git a/firefox-ios/Shared/Supporting Files/ko.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/ko.lproj/EditAddress.strings index fda2b3fadbbb..f6339420f87c 100644 --- a/firefox-ios/Shared/Supporting Files/ko.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/ko.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "주소를 저장할 수 없습니다."; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "주소를 삭제할 수 없습니다."; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "다시 시도"; diff --git a/firefox-ios/Shared/Supporting Files/ko.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/ko.lproj/Toolbar.strings new file mode 100644 index 000000000000..5dfb97d7645b --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/ko.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "새 탭"; + diff --git a/firefox-ios/Shared/Supporting Files/nb.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/nb.lproj/EditAddress.strings new file mode 100644 index 000000000000..f3891e7b73b3 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/nb.lproj/EditAddress.strings @@ -0,0 +1,126 @@ +/* Title for the cancel button in the remove address alert. */ +"Addresses.EditAddress.Alert.CancelButton.v129" = "Avbryt"; + +/* Message explaining the consequences of removing an address from all synced devices. */ +"Addresses.EditAddress.Alert.Message.v129" = "Adressen vil bli fjernet fra alle de synkroniserte enhetene dine."; + +/* Title for the remove button in the remove address alert. */ +"Addresses.EditAddress.Alert.RemoveButton.v129" = "Fjern"; + +/* Title for the alert indicating the action to remove an address. */ +"Addresses.EditAddress.Alert.Title.v129" = "Fjern adresse"; + +/* Title for the interface option where users can add a new address for autofill purposes. This facilitates quicker form completion by automatically filling in the user's address information. */ +"Addresses.EditAddress.AutofillAddAddressTitle.v129" = "Legg til adresse"; + +/* Label for the area field, allowing users to specify a particular area within a city or region. This detail can improve the specificity and accuracy of autofilled addresses. */ +"Addresses.EditAddress.AutofillAddressArea.v129" = "Område"; + +/* Label for the field where users input the city part of their address. This information is crucial for mail delivery and service provision, ensuring accurate city identification in autofill settings. */ +"Addresses.EditAddress.AutofillAddressCity.v129" = "Sted"; + +/* Label for the field where users can specify just the country, used in contexts where full address details are not required. Simplifies autofill when only country information is necessary. */ +"Addresses.EditAddress.AutofillAddressCountryOnly.v129" = "Land"; + +/* Label for the country or region field in address forms, allowing users to specify their country or territorial region. This is fundamental for international mail and services, ensuring autofill accuracy across borders. */ +"Addresses.EditAddress.AutofillAddressCountryRegion.v129" = "Land eller region"; + +/* Label for the county field, crucial for addressing in regions where county lines play a key role in postal services. Enhances autofill accuracy by including county information. */ +"Addresses.EditAddress.AutofillAddressCounty.v129" = "Land"; + +/* Label for the department field, used in countries like France and Colombia where departments are a key administrative division. Ensures correct departmental information is autofilled. */ +"Addresses.EditAddress.AutofillAddressDepartment.v129" = "Avdeling"; + +/* Label for the district field in the address form, allowing users to specify their district for more precise location identification. This aids in refining address details for accurate autofill. */ +"Addresses.EditAddress.AutofillAddressDistrict.v129" = "Distrikt"; + +/* Label for the Do/Si field, pertinent to addresses in South Korea. Do/Si refers to provincial level divisions, and specifying this enhances address accuracy in autofill settings. */ +"Addresses.EditAddress.AutofillAddressDoSi.v129" = "Do/Si"; + +/* Label for the Eircode field, specific to Ireland. It's a unique postal code system that helps in precise location identification, enhancing the effectiveness of autofill. */ +"Addresses.EditAddress.AutofillAddressEircode.v129" = "Eircode"; + +/* Label for the email address field, where users input their email. Critical for digital communication and account verification, this ensures email addresses are autofilled accurately. */ +"Addresses.EditAddress.AutofillAddressEmail.v129" = "E-post"; + +/* Label for the emirate field, essential for addresses in the United Arab Emirates. Including emirate details ensures the autofill feature accurately represents user addresses. */ +"Addresses.EditAddress.AutofillAddressEmirate.v129" = "Emirat"; + +/* Label for the field where users specify the name of an island, if applicable. Important for addresses in archipelagic regions, aiding in precise location identification during autofill. */ +"Addresses.EditAddress.AutofillAddressIsland.v129" = "Øy"; + +/* Label for the field where the user inputs their full name as part of an address form. Essential for personalized form submissions and ensuring information accuracy in autofilled forms. */ +"Addresses.EditAddress.AutofillAddressName.v129" = "Navn"; + +/* Label for the field where users can input the name of their neighborhood. This detail adds precision to addresses, especially in densely populated areas, improving the accuracy of autofill. */ +"Addresses.EditAddress.AutofillAddressNeighborhood.v129" = "Nabolag"; + +/* Label for the oblast field, relevant for addresses in countries like Russia and Ukraine. Oblasts are a significant administrative division, and their specification aids in autofill accuracy. */ +"Addresses.EditAddress.AutofillAddressOblast.v129" = "Oblast"; + +/* Label for the input field designated for the organization's name related to the address. Helps in distinguishing addresses used for business or personal purposes in autofill settings. */ +"Addresses.EditAddress.AutofillAddressOrganization.v129" = "Organisasjon"; + +/* Label for the parish field, significant in places where parishes are used for local administration and addressing. Ensures users can specify parish details for better autofill accuracy. */ +"Addresses.EditAddress.AutofillAddressParish.v129" = "Sogn"; + +/* Label for the PIN (Postal Index Number) field, used in India. It's a code representing a specific area, crucial for accurate mail delivery and autofill functionality. */ +"Addresses.EditAddress.AutofillAddressPin.v129" = "Pin"; + +/* Label for the postal code field, universally used in address forms to specify the area code for mail sorting. Essential for autofill to ensure mail and services are accurately routed. */ +"Addresses.EditAddress.AutofillAddressPostalCode.v129" = "Postnummer"; + +/* Label for the post town field, used primarily in the UK and some other regions for mail sorting. Essential for users in applicable areas to specify for correct mail delivery through autofill. */ +"Addresses.EditAddress.AutofillAddressPostTown.v129" = "Poststed"; + +/* Label for the prefecture field, essential for addresses in countries like Japan where prefectures are a major administrative division. Aids in precise location specification for autofill. */ +"Addresses.EditAddress.AutofillAddressPrefecture.v129" = "Prefektur"; + +/* Label for the province field, required in countries where provinces are a primary administrative division. Helps in pinpointing the user's location more accurately for autofill purposes. */ +"Addresses.EditAddress.AutofillAddressProvince.v129" = "Provins"; + +/* Label for the state field, a necessary component of addresses in many countries, especially the USA. It ensures that state-specific details are correctly filled in forms using autofill. */ +"Addresses.EditAddress.AutofillAddressState.v129" = "Stat"; + +/* Label for the suburb field, enabling users to add suburb details to their address. This is important for accurate delivery and services in suburban areas, enhancing autofill functionality. */ +"Addresses.EditAddress.AutofillAddressSuburb.v129" = "Forstad"; + +/* Label for the telephone number field, allowing users to input their contact number. This is essential for communication and service provision, ensuring contact details are autofilled correctly. */ +"Addresses.EditAddress.AutofillAddressTel.v129" = "Telefon"; + +/* Label for the input field for the townland, a specific type of land division used in rural areas. Enhances address detail for users in regions where townlands are a common addressing component. */ +"Addresses.EditAddress.AutofillAddressTownland.v129" = "Tettsted"; + +/* Label for the field to input the name of a village or township. This is crucial for addresses in rural areas, ensuring the autofill feature accurately captures all necessary geographical details. */ +"Addresses.EditAddress.AutofillAddressVillageTownship.v129" = "Tettsted eller liten by"; + +/* Label for the ZIP code field, primarily used in the United States for mail sorting. Key for autofill to accurately complete addresses for shipping, billing, and service provision. */ +"Addresses.EditAddress.AutofillAddressZip.v129" = "Postnummer"; + +/* Label for the button to cancel the current autofill operation or exit the form without saving changes. Provides users with an option to back out of a process without making any modifications. */ +"Addresses.EditAddress.AutofillCancelButton.v129" = "Avbryt"; + +/* Title for the option allowing users to edit an existing saved address. This is used within the settings for autofill, enabling users to update their address details for accurate form autofilling. */ +"Addresses.EditAddress.AutofillEditAddressTitle.v129" = "Rediger adresse"; + +/* Title for the input field where users can enter their street address. This is used within the settings for autofill, allowing users to provide their street address for accurate form autofilling. */ +"Addresses.EditAddress.AutofillEditStreetAddressTitle.v129" = "Gateadresse"; + +/* Label for the button to save the current address details entered or edited by the user. This action confirms the user's changes and updates their autofill settings accordingly. */ +"Addresses.EditAddress.AutofillSaveButton.v129" = "Lagre"; + +/* Title for the option allowing users to view an existing saved address. This is used within the settings for autofill, enabling users to see their address details for accurate form autofilling. */ +"Addresses.EditAddress.AutofillViewAddressTitle.v129" = "Vis adresse"; + +/* Button label for closing the view where user can view their address info. */ +"Addresses.EditAddress.CloseNavBarButtonLabel.v129" = "Lukk"; + +/* Button label for editing the address details shown in the form. */ +"Addresses.EditAddress.EditNavBarButtonLabel.v129" = "Rediger"; + +/* Title for button that offers the user the option to remove an address. */ +"Addresses.EditAddress.RemoveAddressButtonTitle.v129" = "Fjern adresse"; + +/* Toast message confirming that an address has been successfully removed. */ +"Addresses.Toast.AddressRemovedConfirmation.v129" = "Adresse fjernet"; + diff --git a/firefox-ios/Shared/Supporting Files/nl.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/nl.lproj/EditAddress.strings index 3af5da40d614..f6fa6fa8dddf 100644 --- a/firefox-ios/Shared/Supporting Files/nl.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/nl.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "Adres kan niet worden opgeslagen"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Adres kan niet worden verwijderd"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Opnieuw proberen"; diff --git a/firefox-ios/Shared/Supporting Files/nl.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/nl.lproj/Toolbar.strings new file mode 100644 index 000000000000..ccd4752f79b7 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/nl.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Nieuw tabblad"; + diff --git a/firefox-ios/Shared/Supporting Files/nn.lproj/Alerts.strings b/firefox-ios/Shared/Supporting Files/nn.lproj/Alerts.strings index bf5909aa60ad..91bebea6030f 100644 --- a/firefox-ios/Shared/Supporting Files/nn.lproj/Alerts.strings +++ b/firefox-ios/Shared/Supporting Files/nn.lproj/Alerts.strings @@ -17,7 +17,7 @@ "Alerts.RestoreTabs.Button.Yes.v109" = "Gjenopprett faner"; /* The body of the restore tabs pop-up alert. This alert shows when opening up Firefox after it crashed. */ -"Alerts.RestoreTabs.Message.v109" = "Beklagar det. Gjenopprett faner for å fortsetje der du slutta."; +"Alerts.RestoreTabs.Message.v109" = "Beklagar det. Gjenopprett faner for å halde fram der du slutta."; /* The title of the restore tabs pop-up alert. This alert shows when opening up Firefox after it crashed. The placeholder will be the Firefox name. */ "Alerts.RestoreTabs.Title.v109.v2" = "%@ krasja. Vil du gjenopprette fanene dine?"; diff --git a/firefox-ios/Shared/Supporting Files/nn.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/nn.lproj/EditAddress.strings index 1b1ab6afdbb9..dea32d1bb048 100644 --- a/firefox-ios/Shared/Supporting Files/nn.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/nn.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "Klarte ikkje å lagre adresse"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Klarte ikkje å fjerne adresse"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Prøv igjen"; diff --git a/firefox-ios/Shared/Supporting Files/nn.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/nn.lproj/Toolbar.strings new file mode 100644 index 000000000000..54abf2257395 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/nn.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Ny fane"; + diff --git a/firefox-ios/Shared/Supporting Files/pa-IN.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/pa-IN.lproj/EditAddress.strings index 846414681194..c8c9218badad 100644 --- a/firefox-ios/Shared/Supporting Files/pa-IN.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/pa-IN.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "ਸਿਰਨਾਵੇਂ ਨੂੰ ਸੰਭਾਲਿਆ ਨਹੀਂ ਜਾ ਸਕਿਆ"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "ਸਿਰਨਾਵੇਂ ਨੂੰ ਹਟਾਇਆ ਨਹੀਂ ਜਾ ਸਕਿਆ"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "ਫੇਰ ਕੋਸ਼ਿਸ਼ ਕਰੋ"; diff --git a/firefox-ios/Shared/Supporting Files/pa-IN.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/pa-IN.lproj/Toolbar.strings new file mode 100644 index 000000000000..05f9d815bc83 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/pa-IN.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "ਨਵੀਂ ਟੈਬ"; + diff --git a/firefox-ios/Shared/Supporting Files/pl.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/pl.lproj/EditAddress.strings new file mode 100644 index 000000000000..7b5da32cf52e --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/pl.lproj/EditAddress.strings @@ -0,0 +1,141 @@ +/* Title for the cancel button in the remove address alert. */ +"Addresses.EditAddress.Alert.CancelButton.v129" = "Anuluj"; + +/* Message explaining the consequences of removing an address from all synced devices. */ +"Addresses.EditAddress.Alert.Message.v129" = "Adres zostanie usunięty ze wszystkich synchronizowanych urządzeń."; + +/* Title for the remove button in the remove address alert. */ +"Addresses.EditAddress.Alert.RemoveButton.v129" = "Usuń"; + +/* Title for the alert indicating the action to remove an address. */ +"Addresses.EditAddress.Alert.Title.v129" = "Usuń adres"; + +/* Title for the interface option where users can add a new address for autofill purposes. This facilitates quicker form completion by automatically filling in the user's address information. */ +"Addresses.EditAddress.AutofillAddAddressTitle.v129" = "Dodaj adres"; + +/* Label for the area field, allowing users to specify a particular area within a city or region. This detail can improve the specificity and accuracy of autofilled addresses. */ +"Addresses.EditAddress.AutofillAddressArea.v129" = "Obszar"; + +/* Label for the field where users input the city part of their address. This information is crucial for mail delivery and service provision, ensuring accurate city identification in autofill settings. */ +"Addresses.EditAddress.AutofillAddressCity.v129" = "Miasto"; + +/* Label for the field where users can specify just the country, used in contexts where full address details are not required. Simplifies autofill when only country information is necessary. */ +"Addresses.EditAddress.AutofillAddressCountryOnly.v129" = "Państwo"; + +/* Label for the country or region field in address forms, allowing users to specify their country or territorial region. This is fundamental for international mail and services, ensuring autofill accuracy across borders. */ +"Addresses.EditAddress.AutofillAddressCountryRegion.v129" = "Państwo lub region"; + +/* Label for the county field, crucial for addressing in regions where county lines play a key role in postal services. Enhances autofill accuracy by including county information. */ +"Addresses.EditAddress.AutofillAddressCounty.v129" = "Hrabstwo"; + +/* Label for the department field, used in countries like France and Colombia where departments are a key administrative division. Ensures correct departmental information is autofilled. */ +"Addresses.EditAddress.AutofillAddressDepartment.v129" = "Departament"; + +/* Label for the district field in the address form, allowing users to specify their district for more precise location identification. This aids in refining address details for accurate autofill. */ +"Addresses.EditAddress.AutofillAddressDistrict.v129" = "Dystrykt"; + +/* Label for the Do/Si field, pertinent to addresses in South Korea. Do/Si refers to provincial level divisions, and specifying this enhances address accuracy in autofill settings. */ +"Addresses.EditAddress.AutofillAddressDoSi.v129" = "Do/Si"; + +/* Label for the Eircode field, specific to Ireland. It's a unique postal code system that helps in precise location identification, enhancing the effectiveness of autofill. */ +"Addresses.EditAddress.AutofillAddressEircode.v129" = "Eircode"; + +/* Label for the email address field, where users input their email. Critical for digital communication and account verification, this ensures email addresses are autofilled accurately. */ +"Addresses.EditAddress.AutofillAddressEmail.v129" = "E-mail"; + +/* Label for the emirate field, essential for addresses in the United Arab Emirates. Including emirate details ensures the autofill feature accurately represents user addresses. */ +"Addresses.EditAddress.AutofillAddressEmirate.v129" = "Emirat"; + +/* Label for the field where users specify the name of an island, if applicable. Important for addresses in archipelagic regions, aiding in precise location identification during autofill. */ +"Addresses.EditAddress.AutofillAddressIsland.v129" = "Wyspa"; + +/* Label for the field where the user inputs their full name as part of an address form. Essential for personalized form submissions and ensuring information accuracy in autofilled forms. */ +"Addresses.EditAddress.AutofillAddressName.v129" = "Imię i nazwisko"; + +/* Label for the field where users can input the name of their neighborhood. This detail adds precision to addresses, especially in densely populated areas, improving the accuracy of autofill. */ +"Addresses.EditAddress.AutofillAddressNeighborhood.v129" = "Neighborhood"; + +/* Label for the oblast field, relevant for addresses in countries like Russia and Ukraine. Oblasts are a significant administrative division, and their specification aids in autofill accuracy. */ +"Addresses.EditAddress.AutofillAddressOblast.v129" = "Obwód"; + +/* Label for the input field designated for the organization's name related to the address. Helps in distinguishing addresses used for business or personal purposes in autofill settings. */ +"Addresses.EditAddress.AutofillAddressOrganization.v129" = "Organizacja"; + +/* Label for the parish field, significant in places where parishes are used for local administration and addressing. Ensures users can specify parish details for better autofill accuracy. */ +"Addresses.EditAddress.AutofillAddressParish.v129" = "Parish"; + +/* Label for the PIN (Postal Index Number) field, used in India. It's a code representing a specific area, crucial for accurate mail delivery and autofill functionality. */ +"Addresses.EditAddress.AutofillAddressPin.v129" = "Pin"; + +/* Label for the postal code field, universally used in address forms to specify the area code for mail sorting. Essential for autofill to ensure mail and services are accurately routed. */ +"Addresses.EditAddress.AutofillAddressPostalCode.v129" = "Kod pocztowy"; + +/* Label for the post town field, used primarily in the UK and some other regions for mail sorting. Essential for users in applicable areas to specify for correct mail delivery through autofill. */ +"Addresses.EditAddress.AutofillAddressPostTown.v129" = "Post town"; + +/* Label for the prefecture field, essential for addresses in countries like Japan where prefectures are a major administrative division. Aids in precise location specification for autofill. */ +"Addresses.EditAddress.AutofillAddressPrefecture.v129" = "Prefektura"; + +/* Label for the province field, required in countries where provinces are a primary administrative division. Helps in pinpointing the user's location more accurately for autofill purposes. */ +"Addresses.EditAddress.AutofillAddressProvince.v129" = "Prowincja"; + +/* Label for the state field, a necessary component of addresses in many countries, especially the USA. It ensures that state-specific details are correctly filled in forms using autofill. */ +"Addresses.EditAddress.AutofillAddressState.v129" = "Stan"; + +/* Label for the suburb field, enabling users to add suburb details to their address. This is important for accurate delivery and services in suburban areas, enhancing autofill functionality. */ +"Addresses.EditAddress.AutofillAddressSuburb.v129" = "Suburb"; + +/* Label for the telephone number field, allowing users to input their contact number. This is essential for communication and service provision, ensuring contact details are autofilled correctly. */ +"Addresses.EditAddress.AutofillAddressTel.v129" = "Telefon"; + +/* Label for the input field for the townland, a specific type of land division used in rural areas. Enhances address detail for users in regions where townlands are a common addressing component. */ +"Addresses.EditAddress.AutofillAddressTownland.v129" = "Townland"; + +/* Label for the field to input the name of a village or township. This is crucial for addresses in rural areas, ensuring the autofill feature accurately captures all necessary geographical details. */ +"Addresses.EditAddress.AutofillAddressVillageTownship.v129" = "Wioska lub township"; + +/* Label for the ZIP code field, primarily used in the United States for mail sorting. Key for autofill to accurately complete addresses for shipping, billing, and service provision. */ +"Addresses.EditAddress.AutofillAddressZip.v129" = "Kod ZIP"; + +/* Label for the button to cancel the current autofill operation or exit the form without saving changes. Provides users with an option to back out of a process without making any modifications. */ +"Addresses.EditAddress.AutofillCancelButton.v129" = "Anuluj"; + +/* Title for the option allowing users to edit an existing saved address. This is used within the settings for autofill, enabling users to update their address details for accurate form autofilling. */ +"Addresses.EditAddress.AutofillEditAddressTitle.v129" = "Edytuj adres"; + +/* Title for the input field where users can enter their street address. This is used within the settings for autofill, allowing users to provide their street address for accurate form autofilling. */ +"Addresses.EditAddress.AutofillEditStreetAddressTitle.v129" = "Adres"; + +/* Label for the button to save the current address details entered or edited by the user. This action confirms the user's changes and updates their autofill settings accordingly. */ +"Addresses.EditAddress.AutofillSaveButton.v129" = "Zachowaj"; + +/* Title for the option allowing users to view an existing saved address. This is used within the settings for autofill, enabling users to see their address details for accurate form autofilling. */ +"Addresses.EditAddress.AutofillViewAddressTitle.v129" = "Wyświetl adres"; + +/* Button label for closing the view where user can view their address info. */ +"Addresses.EditAddress.CloseNavBarButtonLabel.v129" = "Zamknij"; + +/* Button label for editing the address details shown in the form. */ +"Addresses.EditAddress.EditNavBarButtonLabel.v129" = "Edytuj"; + +/* Title for button that offers the user the option to remove an address. */ +"Addresses.EditAddress.RemoveAddressButtonTitle.v129" = "Usuń adres"; + +/* Toast message confirming that an address has been successfully removed. */ +"Addresses.Toast.AddressRemovedConfirmation.v129" = "Usunięto adres"; + +/* Toast message confirming that an address has been successfully saved. */ +"Addresses.Toast.AddressSavedConfirmation.v129" = "Zachowano adres"; + +/* Toast message indicating an error occurred while trying to save an address. */ +"Addresses.Toast.AddressSaveError.v129" = "Nie można zachować adresu"; + +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Nie można usunąć adresu"; + +/* Suggestion to try again after an error occurred while trying to save an address. */ +"Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Spróbuj ponownie"; + +/* Toast message confirming that an address has been successfully updated. */ +"Addresses.Toast.AddressUpdatedConfirmation.v129" = "Uaktualniono adres"; + diff --git a/firefox-ios/Shared/Supporting Files/pl.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/pl.lproj/EnhancedTrackingProtection.strings index 86c6240fc6c4..6724515c143b 100644 --- a/firefox-ios/Shared/Supporting Files/pl.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/pl.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,15 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Niezabezpieczone połączenie"; +/* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Ciasteczka śledzące między witrynami: %@"; + +/* Text to let users know how many fingerprinters were blocked on the current website. The placeholder will show the number of fingerprinters detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.Fingerprinter.v129" = "Elementy śledzące przez zbieranie informacji o konfiguracji: %@"; + +/* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Elementy śledzące serwisów społecznościowych: %@"; + /* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked Text to let users know that no trackers were found on the current website. */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Zablokowane elementy śledzące: %@"; @@ -54,6 +63,9 @@ /* A switch to disable enhanced tracking protection inside the menu. */ "Menu.EnhancedTrackingProtection.SwitchOff.Text.v128" = "Ochrona jest wyłączona. Zalecamy ponowne jej włączenie."; +/* A switch to disable enhanced tracking protection inside the menu. */ +"Menu.EnhancedTrackingProtection.SwitchOff.Text.v129" = "Ochrona jest wyłączona. Zalecamy ponowne jej włączenie."; + /* A switch to disable enhanced tracking protection inside the menu. */ "Menu.EnhancedTrackingProtection.SwitchOn.Text.v128" = "Jeśli coś na tej witrynie nie działa, spróbuj ją wyłączyć."; diff --git a/firefox-ios/Shared/Supporting Files/pl.lproj/PasswordAutofill.strings b/firefox-ios/Shared/Supporting Files/pl.lproj/PasswordAutofill.strings index 5d7b7f658e35..b7e7e543e4f7 100644 --- a/firefox-ios/Shared/Supporting Files/pl.lproj/PasswordAutofill.strings +++ b/firefox-ios/Shared/Supporting Files/pl.lproj/PasswordAutofill.strings @@ -1,3 +1,6 @@ +/* This label is used in a cell found in the list of autofill login options in place of an actual username to denote that no username was saved for this login */ +"PasswordAutofill.LoginListCellNoUsername.v129" = "(bez nazwy użytkownika)"; + /* This label is used for a button in the password list screen allowing users to manage their saved passwords. It's meant to direct users to where they can add, remove, or edit their saved passwords. */ "PasswordAutofill.ManagePasswordsButton.v124" = "Zarządzaj hasłami"; diff --git a/firefox-ios/Shared/Supporting Files/pl.lproj/ScanQRCode.strings b/firefox-ios/Shared/Supporting Files/pl.lproj/ScanQRCode.strings new file mode 100644 index 000000000000..069ce497b62b --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/pl.lproj/ScanQRCode.strings @@ -0,0 +1,9 @@ +/* Allow button to open URL from scanned QR Code */ +"ScanQRCode.ConfirmOpenURL.AllowButton.v129" = "Zezwól"; + +/* Deny button to cancel opening URL from scanned QR Code */ +"ScanQRCode.ConfirmOpenURL.DenyButton.v129" = "Odmów"; + +/* Text of the prompt to ask user permission to open a URL from a scanned QR code. Placeholder is app name. */ +"ScanQRCode.ConfirmOpenURL.Message.v129" = "Czy zezwolić aplikacji %@ na otwarcie?"; + diff --git a/firefox-ios/Shared/Supporting Files/pl.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/pl.lproj/Toolbar.strings new file mode 100644 index 000000000000..0cabac60c3a7 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/pl.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Nowa karta"; + diff --git a/firefox-ios/Shared/Supporting Files/pt-BR.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/pt-BR.lproj/EditAddress.strings index 6cd31595768e..0874f765ac7d 100644 --- a/firefox-ios/Shared/Supporting Files/pt-BR.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/pt-BR.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "O endereço não pôde ser salvo"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "O endereço não pôde ser removido"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Tentar novamente"; diff --git a/firefox-ios/Shared/Supporting Files/pt-BR.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/pt-BR.lproj/Toolbar.strings new file mode 100644 index 000000000000..79a59ed9dba8 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/pt-BR.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Nova aba"; + diff --git a/firefox-ios/Shared/Supporting Files/pt-PT.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/pt-PT.lproj/EditAddress.strings index f70bda954c20..4cd0f716fb77 100644 --- a/firefox-ios/Shared/Supporting Files/pt-PT.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/pt-PT.lproj/EditAddress.strings @@ -41,7 +41,7 @@ "Addresses.EditAddress.AutofillAddressEircode.v129" = "Eircode"; /* Label for the email address field, where users input their email. Critical for digital communication and account verification, this ensures email addresses are autofilled accurately. */ -"Addresses.EditAddress.AutofillAddressEmail.v129" = "Email"; +"Addresses.EditAddress.AutofillAddressEmail.v129" = "E-mail"; /* Label for the emirate field, essential for addresses in the United Arab Emirates. Including emirate details ensures the autofill feature accurately represents user addresses. */ "Addresses.EditAddress.AutofillAddressEmirate.v129" = "Emirado"; @@ -62,10 +62,10 @@ "Addresses.EditAddress.AutofillAddressOrganization.v129" = "Organização"; /* Label for the parish field, significant in places where parishes are used for local administration and addressing. Ensures users can specify parish details for better autofill accuracy. */ -"Addresses.EditAddress.AutofillAddressParish.v129" = "Freguesia"; +"Addresses.EditAddress.AutofillAddressParish.v129" = "Paróquia"; /* Label for the PIN (Postal Index Number) field, used in India. It's a code representing a specific area, crucial for accurate mail delivery and autofill functionality. */ -"Addresses.EditAddress.AutofillAddressPin.v129" = "Afixar"; +"Addresses.EditAddress.AutofillAddressPin.v129" = "PIN"; /* Label for the postal code field, universally used in address forms to specify the area code for mail sorting. Essential for autofill to ensure mail and services are accurately routed. */ "Addresses.EditAddress.AutofillAddressPostalCode.v129" = "Código postal"; @@ -92,10 +92,10 @@ "Addresses.EditAddress.AutofillAddressTownland.v129" = "Cidade"; /* Label for the field to input the name of a village or township. This is crucial for addresses in rural areas, ensuring the autofill feature accurately captures all necessary geographical details. */ -"Addresses.EditAddress.AutofillAddressVillageTownship.v129" = "Aldeia ou município"; +"Addresses.EditAddress.AutofillAddressVillageTownship.v129" = "Vila ou município"; /* Label for the ZIP code field, primarily used in the United States for mail sorting. Key for autofill to accurately complete addresses for shipping, billing, and service provision. */ -"Addresses.EditAddress.AutofillAddressZip.v129" = "Código postal"; +"Addresses.EditAddress.AutofillAddressZip.v129" = "Código ZIP"; /* Label for the button to cancel the current autofill operation or exit the form without saving changes. Provides users with an option to back out of a process without making any modifications. */ "Addresses.EditAddress.AutofillCancelButton.v129" = "Cancelar"; @@ -128,7 +128,10 @@ "Addresses.Toast.AddressSavedConfirmation.v129" = "Endereço guardado"; /* Toast message indicating an error occurred while trying to save an address. */ -"Addresses.Toast.AddressSaveError.v129" = "O endereço não pôde ser guardado"; +"Addresses.Toast.AddressSaveError.v129" = "Não foi possível guardar o endereço"; + +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "O endereço não pôde ser removido"; /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Tentar novamente"; diff --git a/firefox-ios/Shared/Supporting Files/pt-PT.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/pt-PT.lproj/EnhancedTrackingProtection.strings index 6c6c16637257..abe11d32adfe 100644 --- a/firefox-ios/Shared/Supporting Files/pt-PT.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/pt-PT.lproj/EnhancedTrackingProtection.strings @@ -64,7 +64,7 @@ "Menu.EnhancedTrackingProtection.SwitchOff.Text.v128" = "As proteções estão desativadas. Sugerimos que a sua reativação."; /* A switch to disable enhanced tracking protection inside the menu. */ -"Menu.EnhancedTrackingProtection.SwitchOff.Text.v129" = "As proteções estão desativadas. Sugerimos que os ligue novamente."; +"Menu.EnhancedTrackingProtection.SwitchOff.Text.v129" = "As proteções estão desativadas. Sugerimos que as ligue novamente."; /* A switch to disable enhanced tracking protection inside the menu. */ "Menu.EnhancedTrackingProtection.SwitchOn.Text.v128" = "Se parecer que algo não está a funcionar neste site, experimente desativar."; diff --git a/firefox-ios/Shared/Supporting Files/pt-PT.lproj/ScanQRCode.strings b/firefox-ios/Shared/Supporting Files/pt-PT.lproj/ScanQRCode.strings index 6d7a2c107a58..d4c25be1f145 100644 --- a/firefox-ios/Shared/Supporting Files/pt-PT.lproj/ScanQRCode.strings +++ b/firefox-ios/Shared/Supporting Files/pt-PT.lproj/ScanQRCode.strings @@ -5,5 +5,5 @@ "ScanQRCode.ConfirmOpenURL.DenyButton.v129" = "Recusar"; /* Text of the prompt to ask user permission to open a URL from a scanned QR code. Placeholder is app name. */ -"ScanQRCode.ConfirmOpenURL.Message.v129" = "Permitir que o %@ abra?"; +"ScanQRCode.ConfirmOpenURL.Message.v129" = "Permitir que %@ abra?"; diff --git a/firefox-ios/Shared/Supporting Files/pt-PT.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/pt-PT.lproj/Toolbar.strings new file mode 100644 index 000000000000..c2e904d4eea7 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/pt-PT.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Novo separador"; + diff --git a/firefox-ios/Shared/Supporting Files/rm.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/rm.lproj/EditAddress.strings index 497908034cf3..3b8768bba291 100644 --- a/firefox-ios/Shared/Supporting Files/rm.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/rm.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "Betg reussì da memorisar l’adressa"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Betg reussì dad allontanar l’adressa"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Empruvar anc ina giada"; diff --git a/firefox-ios/Shared/Supporting Files/rm.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/rm.lproj/Toolbar.strings new file mode 100644 index 000000000000..a2c37eac1fda --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/rm.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Nov tab"; + diff --git a/firefox-ios/Shared/Supporting Files/ru.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/ru.lproj/EditAddress.strings index 8a0f6ccfd821..38d6fe16e6ab 100644 --- a/firefox-ios/Shared/Supporting Files/ru.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/ru.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "Не удалось сохранить адрес"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Не удалось удалить адрес"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Попробовать снова"; diff --git a/firefox-ios/Shared/Supporting Files/ru.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/ru.lproj/Toolbar.strings new file mode 100644 index 000000000000..9070c6c4cba3 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/ru.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Новая вкладка"; + diff --git a/firefox-ios/Shared/Supporting Files/sat-Olck.lproj/Credentials.strings b/firefox-ios/Shared/Supporting Files/sat-Olck.lproj/Credentials.strings new file mode 100644 index 000000000000..ad684d07d5db --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/sat-Olck.lproj/Credentials.strings @@ -0,0 +1,6 @@ +/* Message shown when you enter Logins & Passwords without having a device passcode set. */ +"Logins.DevicePasscodeRequired.Message.v122" = "ᱫᱟᱱᱟᱝ ᱥᱟᱵᱟᱫᱽ ᱠᱚ ᱟᱡ ᱛᱮ ᱥᱟᱺᱪᱟᱣ ᱞᱟᱹᱜᱤᱫ, ᱢᱮᱫᱦᱟᱸ ID, ᱴᱤᱯᱟᱹᱶ ID ᱟᱨᱵᱟᱝᱠᱷᱟᱱ ᱢᱤᱫᱴᱟᱝ ᱥᱟᱫᱷᱚᱱ ᱫᱟᱱᱟᱝᱠᱳᱰ ᱥᱟᱺᱪᱟᱣ ᱢᱮ ᱾"; + +/* Message shown when you enter Payment Methods without having a device passcode set. */ +"Logins.PaymentMethods.DevicePasscodeRequired.Message.v124.v2" = "ᱟᱡ ᱛᱮ ᱠᱨᱮᱰᱤᱴ ᱠᱟᱰ ᱥᱟᱺᱪᱟᱣ ᱟᱨ ᱯᱮᱨᱮᱡ ᱞᱟᱹᱜᱤᱫ, ᱢᱮᱫᱦᱟᱸ ID, ᱴᱤᱯᱟᱹᱶ ID ᱟᱨᱵᱟᱝᱠᱷᱟᱱ ᱢᱤᱫᱴᱟᱝ ᱥᱟᱫᱷᱚᱱ ᱫᱟᱱᱟᱝᱠᱳᱰ ᱥᱟᱺᱪᱟᱣ ᱢᱮ ᱾"; + diff --git a/firefox-ios/Shared/Supporting Files/sat-Olck.lproj/CustomizeFirefoxHome.strings b/firefox-ios/Shared/Supporting Files/sat-Olck.lproj/CustomizeFirefoxHome.strings index 26bd804839ae..0c9880aee25f 100644 --- a/firefox-ios/Shared/Supporting Files/sat-Olck.lproj/CustomizeFirefoxHome.strings +++ b/firefox-ios/Shared/Supporting Files/sat-Olck.lproj/CustomizeFirefoxHome.strings @@ -1,3 +1,6 @@ +/* In the settings menu, in the Firefox homepage customization section, this is the title for the option that allows users to toggle Bookmarks section on the Firefox homepage on or off */ +"Settings.Home.Option.Bookmarks.v128" = "ᱵᱩᱠᱢᱟᱨᱠ ᱠᱚ"; + /* In the settings menu, in the Firefox homepage customization section, this is the subtitle for the option that allows users to turn the Pocket Recommendations section on the Firefox homepage on or off. The placeholder is the pocket app name. */ "Settings.Home.Option.ThoughtProvokingStories.subtitle.v116" = "%@ ᱫᱟᱨᱟᱭ ᱛᱮ ᱫᱟᱲᱮ ᱮᱢ ᱠᱟᱱ ᱚᱱᱚᱞᱠᱚ"; diff --git a/firefox-ios/Shared/Supporting Files/sat-Olck.lproj/Edit Card.strings b/firefox-ios/Shared/Supporting Files/sat-Olck.lproj/Edit Card.strings index 66d3ab3f3400..42b6ae0be173 100644 --- a/firefox-ios/Shared/Supporting Files/sat-Olck.lproj/Edit Card.strings +++ b/firefox-ios/Shared/Supporting Files/sat-Olck.lproj/Edit Card.strings @@ -1,3 +1,3 @@ /* Title label for the view where user can edit their credit card info */ -"CreditCard.EditCard.EditCreditCardTitle.v113" = "ᱠᱨᱮᱰᱤᱴ ᱠᱟᱰ ᱥᱟᱯᱲᱟᱣ ᱢᱮ"; +"CreditCard.EditCard.EditCreditCardTitle.v122" = "ᱠᱟᱰ ᱥᱟᱯᱲᱟᱣ ᱢᱮ"; diff --git a/firefox-ios/Shared/Supporting Files/sat-Olck.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/sat-Olck.lproj/EditAddress.strings new file mode 100644 index 000000000000..77bef59da5b6 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/sat-Olck.lproj/EditAddress.strings @@ -0,0 +1,138 @@ +/* Title for the cancel button in the remove address alert. */ +"Addresses.EditAddress.Alert.CancelButton.v129" = "ᱵᱟᱹᱰᱨᱟᱹ"; + +/* Message explaining the consequences of removing an address from all synced devices. */ +"Addresses.EditAddress.Alert.Message.v129" = "ᱱᱚᱶᱟ ᱴᱷᱤᱠᱬᱟᱹ ᱫᱚ ᱟᱢᱟᱜ ᱡᱷᱚᱛᱚ ᱟᱹᱭᱩᱨ ᱢᱤᱫ ᱟᱠᱟᱱ ᱥᱟᱫᱷᱚᱱ ᱠᱷᱚᱱ ᱚᱪᱚᱜᱚᱜᱼᱟ ᱾"; + +/* Title for the remove button in the remove address alert. */ +"Addresses.EditAddress.Alert.RemoveButton.v129" = "ᱚᱪᱚᱜᱽ ᱢᱮ"; + +/* Title for the alert indicating the action to remove an address. */ +"Addresses.EditAddress.Alert.Title.v129" = "ᱴᱷᱤᱠᱬᱟᱹ ᱚᱪᱚᱜᱽ ᱢᱮ"; + +/* Title for the interface option where users can add a new address for autofill purposes. This facilitates quicker form completion by automatically filling in the user's address information. */ +"Addresses.EditAddress.AutofillAddAddressTitle.v129" = "ᱴᱷᱤᱠᱬᱟᱹ ᱥᱮᱞᱮᱫ ᱢᱮ"; + +/* Label for the area field, allowing users to specify a particular area within a city or region. This detail can improve the specificity and accuracy of autofilled addresses. */ +"Addresses.EditAddress.AutofillAddressArea.v129" = "ᱡᱟᱭᱜᱟ"; + +/* Label for the field where users input the city part of their address. This information is crucial for mail delivery and service provision, ensuring accurate city identification in autofill settings. */ +"Addresses.EditAddress.AutofillAddressCity.v129" = "ᱥᱚᱦᱚᱨ"; + +/* Label for the field where users can specify just the country, used in contexts where full address details are not required. Simplifies autofill when only country information is necessary. */ +"Addresses.EditAddress.AutofillAddressCountryOnly.v129" = "ᱫᱤᱥᱚᱢ"; + +/* Label for the country or region field in address forms, allowing users to specify their country or territorial region. This is fundamental for international mail and services, ensuring autofill accuracy across borders. */ +"Addresses.EditAddress.AutofillAddressCountryRegion.v129" = "ᱫᱤᱥᱚᱢ ᱟᱨᱵᱟᱝ ᱡᱟᱭᱜᱟ"; + +/* Label for the county field, crucial for addressing in regions where county lines play a key role in postal services. Enhances autofill accuracy by including county information. */ +"Addresses.EditAddress.AutofillAddressCounty.v129" = "ᱫᱤᱥᱚᱢ"; + +/* Label for the department field, used in countries like France and Colombia where departments are a key administrative division. Ensures correct departmental information is autofilled. */ +"Addresses.EditAddress.AutofillAddressDepartment.v129" = "ᱛᱟᱞᱢᱟ"; + +/* Label for the district field in the address form, allowing users to specify their district for more precise location identification. This aids in refining address details for accurate autofill. */ +"Addresses.EditAddress.AutofillAddressDistrict.v129" = "ᱡᱤᱞᱟ"; + +/* Label for the Do/Si field, pertinent to addresses in South Korea. Do/Si refers to provincial level divisions, and specifying this enhances address accuracy in autofill settings. */ +"Addresses.EditAddress.AutofillAddressDoSi.v129" = "Do/Si"; + +/* Label for the Eircode field, specific to Ireland. It's a unique postal code system that helps in precise location identification, enhancing the effectiveness of autofill. */ +"Addresses.EditAddress.AutofillAddressEircode.v129" = "ᱤᱭᱮᱨᱠᱳᱰ"; + +/* Label for the email address field, where users input their email. Critical for digital communication and account verification, this ensures email addresses are autofilled accurately. */ +"Addresses.EditAddress.AutofillAddressEmail.v129" = "ᱤᱢᱮᱞ"; + +/* Label for the emirate field, essential for addresses in the United Arab Emirates. Including emirate details ensures the autofill feature accurately represents user addresses. */ +"Addresses.EditAddress.AutofillAddressEmirate.v129" = "ᱮᱢᱤᱨᱮᱴ"; + +/* Label for the field where users specify the name of an island, if applicable. Important for addresses in archipelagic regions, aiding in precise location identification during autofill. */ +"Addresses.EditAddress.AutofillAddressIsland.v129" = "ᱟᱭᱞᱮᱱᱰ"; + +/* Label for the field where the user inputs their full name as part of an address form. Essential for personalized form submissions and ensuring information accuracy in autofilled forms. */ +"Addresses.EditAddress.AutofillAddressName.v129" = "ᱧᱩᱛᱩᱢ"; + +/* Label for the field where users can input the name of their neighborhood. This detail adds precision to addresses, especially in densely populated areas, improving the accuracy of autofill. */ +"Addresses.EditAddress.AutofillAddressNeighborhood.v129" = "ᱥᱩᱨᱥᱩᱨᱦᱚᱲ"; + +/* Label for the oblast field, relevant for addresses in countries like Russia and Ukraine. Oblasts are a significant administrative division, and their specification aids in autofill accuracy. */ +"Addresses.EditAddress.AutofillAddressOblast.v129" = "ᱚᱵᱞᱟᱥᱴ"; + +/* Label for the input field designated for the organization's name related to the address. Helps in distinguishing addresses used for business or personal purposes in autofill settings. */ +"Addresses.EditAddress.AutofillAddressOrganization.v129" = "ᱜᱟᱶᱛᱟ"; + +/* Label for the parish field, significant in places where parishes are used for local administration and addressing. Ensures users can specify parish details for better autofill accuracy. */ +"Addresses.EditAddress.AutofillAddressParish.v129" = "ᱯᱮᱨᱤᱥ"; + +/* Label for the PIN (Postal Index Number) field, used in India. It's a code representing a specific area, crucial for accurate mail delivery and autofill functionality. */ +"Addresses.EditAddress.AutofillAddressPin.v129" = "ᱞᱟᱴᱷᱟ"; + +/* Label for the postal code field, universally used in address forms to specify the area code for mail sorting. Essential for autofill to ensure mail and services are accurately routed. */ +"Addresses.EditAddress.AutofillAddressPostalCode.v129" = "ᱯᱚᱥᱴ ᱠᱳᱰ"; + +/* Label for the post town field, used primarily in the UK and some other regions for mail sorting. Essential for users in applicable areas to specify for correct mail delivery through autofill. */ +"Addresses.EditAddress.AutofillAddressPostTown.v129" = "ᱯᱚᱥᱴ ᱴᱚᱣᱩᱱ"; + +/* Label for the prefecture field, essential for addresses in countries like Japan where prefectures are a major administrative division. Aids in precise location specification for autofill. */ +"Addresses.EditAddress.AutofillAddressPrefecture.v129" = "ᱯᱨᱤᱯᱷᱮᱠᱪᱚᱨ"; + +/* Label for the province field, required in countries where provinces are a primary administrative division. Helps in pinpointing the user's location more accurately for autofill purposes. */ +"Addresses.EditAddress.AutofillAddressProvince.v129" = "ᱯᱚᱱᱚᱛ"; + +/* Label for the state field, a necessary component of addresses in many countries, especially the USA. It ensures that state-specific details are correctly filled in forms using autofill. */ +"Addresses.EditAddress.AutofillAddressState.v129" = "ᱯᱚᱱᱚᱛ"; + +/* Label for the suburb field, enabling users to add suburb details to their address. This is important for accurate delivery and services in suburban areas, enhancing autofill functionality. */ +"Addresses.EditAddress.AutofillAddressSuburb.v129" = "ᱥᱟᱹᱵᱟᱹᱨᱵ"; + +/* Label for the telephone number field, allowing users to input their contact number. This is essential for communication and service provision, ensuring contact details are autofilled correctly. */ +"Addresses.EditAddress.AutofillAddressTel.v129" = "ᱯᱷᱚᱱ"; + +/* Label for the input field for the townland, a specific type of land division used in rural areas. Enhances address detail for users in regions where townlands are a common addressing component. */ +"Addresses.EditAddress.AutofillAddressTownland.v129" = "ᱴᱟᱣᱱᱞᱮᱱᱰ"; + +/* Label for the field to input the name of a village or township. This is crucial for addresses in rural areas, ensuring the autofill feature accurately captures all necessary geographical details. */ +"Addresses.EditAddress.AutofillAddressVillageTownship.v129" = "ᱟᱹᱛᱩ ᱟᱨᱵᱟᱝ ᱴᱚᱞᱟ"; + +/* Label for the ZIP code field, primarily used in the United States for mail sorting. Key for autofill to accurately complete addresses for shipping, billing, and service provision. */ +"Addresses.EditAddress.AutofillAddressZip.v129" = "ZIP ᱠᱳᱰ"; + +/* Label for the button to cancel the current autofill operation or exit the form without saving changes. Provides users with an option to back out of a process without making any modifications. */ +"Addresses.EditAddress.AutofillCancelButton.v129" = "ᱵᱟᱹᱰᱨᱟᱹ"; + +/* Title for the option allowing users to edit an existing saved address. This is used within the settings for autofill, enabling users to update their address details for accurate form autofilling. */ +"Addresses.EditAddress.AutofillEditAddressTitle.v129" = "ᱴᱷᱤᱠᱬᱟᱹ ᱥᱟᱯᱲᱟᱣ ᱢᱮ"; + +/* Title for the input field where users can enter their street address. This is used within the settings for autofill, allowing users to provide their street address for accurate form autofilling. */ +"Addresses.EditAddress.AutofillEditStreetAddressTitle.v129" = "ᱥᱚᱰᱚᱠ ᱴᱷᱤᱠᱬᱟᱹ"; + +/* Label for the button to save the current address details entered or edited by the user. This action confirms the user's changes and updates their autofill settings accordingly. */ +"Addresses.EditAddress.AutofillSaveButton.v129" = "ᱥᱟᱺᱪᱟᱣ ᱢᱮ"; + +/* Title for the option allowing users to view an existing saved address. This is used within the settings for autofill, enabling users to see their address details for accurate form autofilling. */ +"Addresses.EditAddress.AutofillViewAddressTitle.v129" = "ᱴᱷᱤᱠᱬᱟᱹ ᱧᱮᱞ ᱢᱮ"; + +/* Button label for closing the view where user can view their address info. */ +"Addresses.EditAddress.CloseNavBarButtonLabel.v129" = "ᱵᱚᱸᱫᱚᱭ ᱢᱮ"; + +/* Button label for editing the address details shown in the form. */ +"Addresses.EditAddress.EditNavBarButtonLabel.v129" = "ᱥᱟᱯᱲᱟᱣ"; + +/* Title for button that offers the user the option to remove an address. */ +"Addresses.EditAddress.RemoveAddressButtonTitle.v129" = "ᱴᱷᱤᱠᱬᱟᱹ ᱚᱪᱚᱜᱽ ᱢᱮ"; + +/* Toast message confirming that an address has been successfully removed. */ +"Addresses.Toast.AddressRemovedConfirmation.v129" = "ᱴᱷᱤᱠᱬᱟᱹᱠᱚ ᱚᱪᱚᱜ ᱮᱱᱟ"; + +/* Toast message confirming that an address has been successfully saved. */ +"Addresses.Toast.AddressSavedConfirmation.v129" = "ᱴᱷᱤᱠᱬᱟᱹᱠᱚ ᱥᱟᱧᱪᱟᱣ ᱮᱱᱟ"; + +/* Toast message indicating an error occurred while trying to save an address. */ +"Addresses.Toast.AddressSaveError.v129" = "ᱴᱷᱤᱠᱬᱟᱹ ᱥᱟᱧᱪᱟᱣ ᱵᱟᱭ ᱜᱟᱱ ᱞᱮᱱᱟ"; + +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "ᱴᱷᱤᱠᱬᱟᱹ ᱚᱪᱚᱜ ᱵᱟᱭ ᱜᱟᱱ ᱞᱮᱱᱟ"; + +/* Suggestion to try again after an error occurred while trying to save an address. */ +"Addresses.Toast.AddressSaveRetrySuggestion.v129" = "ᱫᱩᱦᱲᱟᱹ ᱠᱩᱨᱩᱢᱩᱴᱩᱭ ᱢᱮ"; + diff --git a/firefox-ios/Shared/Supporting Files/si.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/si.lproj/EditAddress.strings new file mode 100644 index 000000000000..120dc57b8f20 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/si.lproj/EditAddress.strings @@ -0,0 +1,90 @@ +/* Title for the cancel button in the remove address alert. */ +"Addresses.EditAddress.Alert.CancelButton.v129" = "අවලංගු"; + +/* Title for the remove button in the remove address alert. */ +"Addresses.EditAddress.Alert.RemoveButton.v129" = "ඉවත් කරන්න"; + +/* Title for the alert indicating the action to remove an address. */ +"Addresses.EditAddress.Alert.Title.v129" = "ලිපිනය ඉවත් කරන්න"; + +/* Title for the interface option where users can add a new address for autofill purposes. This facilitates quicker form completion by automatically filling in the user's address information. */ +"Addresses.EditAddress.AutofillAddAddressTitle.v129" = "ලිපිනය යොදන්න"; + +/* Label for the area field, allowing users to specify a particular area within a city or region. This detail can improve the specificity and accuracy of autofilled addresses. */ +"Addresses.EditAddress.AutofillAddressArea.v129" = "ප්‍රදේශය"; + +/* Label for the field where users input the city part of their address. This information is crucial for mail delivery and service provision, ensuring accurate city identification in autofill settings. */ +"Addresses.EditAddress.AutofillAddressCity.v129" = "නගරය"; + +/* Label for the field where users can specify just the country, used in contexts where full address details are not required. Simplifies autofill when only country information is necessary. */ +"Addresses.EditAddress.AutofillAddressCountryOnly.v129" = "රට"; + +/* Label for the country or region field in address forms, allowing users to specify their country or territorial region. This is fundamental for international mail and services, ensuring autofill accuracy across borders. */ +"Addresses.EditAddress.AutofillAddressCountryRegion.v129" = "රට හෝ කලාපය"; + +/* Label for the county field, crucial for addressing in regions where county lines play a key role in postal services. Enhances autofill accuracy by including county information. */ +"Addresses.EditAddress.AutofillAddressCounty.v129" = "රට"; + +/* Label for the department field, used in countries like France and Colombia where departments are a key administrative division. Ensures correct departmental information is autofilled. */ +"Addresses.EditAddress.AutofillAddressDepartment.v129" = "ක්‍රියාංශය"; + +/* Label for the Do/Si field, pertinent to addresses in South Korea. Do/Si refers to provincial level divisions, and specifying this enhances address accuracy in autofill settings. */ +"Addresses.EditAddress.AutofillAddressDoSi.v129" = "පළා/කොට්ඨා"; + +/* Label for the email address field, where users input their email. Critical for digital communication and account verification, this ensures email addresses are autofilled accurately. */ +"Addresses.EditAddress.AutofillAddressEmail.v129" = "වි-තැපෑල"; + +/* Label for the emirate field, essential for addresses in the United Arab Emirates. Including emirate details ensures the autofill feature accurately represents user addresses. */ +"Addresses.EditAddress.AutofillAddressEmirate.v129" = "එමිරේට්"; + +/* Label for the field where users specify the name of an island, if applicable. Important for addresses in archipelagic regions, aiding in precise location identification during autofill. */ +"Addresses.EditAddress.AutofillAddressIsland.v129" = "දූපත"; + +/* Label for the field where the user inputs their full name as part of an address form. Essential for personalized form submissions and ensuring information accuracy in autofilled forms. */ +"Addresses.EditAddress.AutofillAddressName.v129" = "නම"; + +/* Label for the input field designated for the organization's name related to the address. Helps in distinguishing addresses used for business or personal purposes in autofill settings. */ +"Addresses.EditAddress.AutofillAddressOrganization.v129" = "සංවිධානය"; + +/* Label for the parish field, significant in places where parishes are used for local administration and addressing. Ensures users can specify parish details for better autofill accuracy. */ +"Addresses.EditAddress.AutofillAddressParish.v129" = "වසම"; + +/* Label for the PIN (Postal Index Number) field, used in India. It's a code representing a specific area, crucial for accurate mail delivery and autofill functionality. */ +"Addresses.EditAddress.AutofillAddressPin.v129" = "අංකය"; + +/* Label for the postal code field, universally used in address forms to specify the area code for mail sorting. Essential for autofill to ensure mail and services are accurately routed. */ +"Addresses.EditAddress.AutofillAddressPostalCode.v129" = "තැපැල් කේතය"; + +/* Label for the post town field, used primarily in the UK and some other regions for mail sorting. Essential for users in applicable areas to specify for correct mail delivery through autofill. */ +"Addresses.EditAddress.AutofillAddressPostTown.v129" = "තැපැල් නගරය"; + +/* Label for the province field, required in countries where provinces are a primary administrative division. Helps in pinpointing the user's location more accurately for autofill purposes. */ +"Addresses.EditAddress.AutofillAddressProvince.v129" = "පළාත"; + +/* Label for the state field, a necessary component of addresses in many countries, especially the USA. It ensures that state-specific details are correctly filled in forms using autofill. */ +"Addresses.EditAddress.AutofillAddressState.v129" = "ප්‍රාන්තය"; + +/* Label for the button to cancel the current autofill operation or exit the form without saving changes. Provides users with an option to back out of a process without making any modifications. */ +"Addresses.EditAddress.AutofillCancelButton.v129" = "අවලංගු"; + +/* Title for the option allowing users to edit an existing saved address. This is used within the settings for autofill, enabling users to update their address details for accurate form autofilling. */ +"Addresses.EditAddress.AutofillEditAddressTitle.v129" = "ලිපිනය සංස්කරණය"; + +/* Title for the input field where users can enter their street address. This is used within the settings for autofill, allowing users to provide their street address for accurate form autofilling. */ +"Addresses.EditAddress.AutofillEditStreetAddressTitle.v129" = "වීදියේ ලිපිනය"; + +/* Label for the button to save the current address details entered or edited by the user. This action confirms the user's changes and updates their autofill settings accordingly. */ +"Addresses.EditAddress.AutofillSaveButton.v129" = "සුරකින්න"; + +/* Title for the option allowing users to view an existing saved address. This is used within the settings for autofill, enabling users to see their address details for accurate form autofilling. */ +"Addresses.EditAddress.AutofillViewAddressTitle.v129" = "ලිපිනය බලන්න"; + +/* Button label for closing the view where user can view their address info. */ +"Addresses.EditAddress.CloseNavBarButtonLabel.v129" = "වසන්න"; + +/* Button label for editing the address details shown in the form. */ +"Addresses.EditAddress.EditNavBarButtonLabel.v129" = "සංස්කරණය"; + +/* Title for button that offers the user the option to remove an address. */ +"Addresses.EditAddress.RemoveAddressButtonTitle.v129" = "ලිපිනය ඉවත් කරන්න"; + diff --git a/firefox-ios/Shared/Supporting Files/si.lproj/ResearchSurface.strings b/firefox-ios/Shared/Supporting Files/si.lproj/ResearchSurface.strings index a7fd588b8a1a..db34bb5c0e84 100644 --- a/firefox-ios/Shared/Supporting Files/si.lproj/ResearchSurface.strings +++ b/firefox-ios/Shared/Supporting Files/si.lproj/ResearchSurface.strings @@ -1,5 +1,5 @@ /* On the Research Survey popup, the text that explains what the screen is about. Placeholder is for the app name. */ -"Body.Text.v112" = "කෙටි සමීක්‍ෂණයෙන් %@ දියුණු කිරීමට උදවු කරන්න."; +"Body.Text.v112" = "කෙටි සමීක්‍ෂණයෙන් %@ දියුණු කිරීමට උදව් කරන්න."; /* On the Research Survey popup, the text for the button that, when tapped, will dismiss the popup and take the user to a survey. */ "PrimaryButton.Label.v112" = "සමීක්‍ෂණය ගන්න"; diff --git a/firefox-ios/Shared/Supporting Files/sk.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/sk.lproj/EditAddress.strings index e60e99b93c95..67b96297ad95 100644 --- a/firefox-ios/Shared/Supporting Files/sk.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/sk.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "Adresu sa nepodarilo uložiť"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Adresu sa nepodarilo odstrániť"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Skúsiť znova"; diff --git a/firefox-ios/Shared/Supporting Files/sk.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/sk.lproj/Toolbar.strings new file mode 100644 index 000000000000..c23c52c9108a --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/sk.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Nová karta"; + diff --git a/firefox-ios/Shared/Supporting Files/sl.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/sl.lproj/EditAddress.strings index 0a64a85d0767..69159f9e5a9b 100644 --- a/firefox-ios/Shared/Supporting Files/sl.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/sl.lproj/EditAddress.strings @@ -88,6 +88,9 @@ /* Label for the telephone number field, allowing users to input their contact number. This is essential for communication and service provision, ensuring contact details are autofilled correctly. */ "Addresses.EditAddress.AutofillAddressTel.v129" = "Telefon"; +/* Label for the input field for the townland, a specific type of land division used in rural areas. Enhances address detail for users in regions where townlands are a common addressing component. */ +"Addresses.EditAddress.AutofillAddressTownland.v129" = "Townland"; + /* Label for the field to input the name of a village or township. This is crucial for addresses in rural areas, ensuring the autofill feature accurately captures all necessary geographical details. */ "Addresses.EditAddress.AutofillAddressVillageTownship.v129" = "Vas ali okraj"; @@ -127,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "Naslova ni bilo mogoče shraniti"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Naslova ni bilo mogoče odstraniti"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Poskusi znova"; diff --git a/firefox-ios/Shared/Supporting Files/sl.lproj/ScanQRCode.strings b/firefox-ios/Shared/Supporting Files/sl.lproj/ScanQRCode.strings new file mode 100644 index 000000000000..80730ce56a4b --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/sl.lproj/ScanQRCode.strings @@ -0,0 +1,9 @@ +/* Allow button to open URL from scanned QR Code */ +"ScanQRCode.ConfirmOpenURL.AllowButton.v129" = "Dovoli"; + +/* Deny button to cancel opening URL from scanned QR Code */ +"ScanQRCode.ConfirmOpenURL.DenyButton.v129" = "Zavrni"; + +/* Text of the prompt to ask user permission to open a URL from a scanned QR code. Placeholder is app name. */ +"ScanQRCode.ConfirmOpenURL.Message.v129" = "Dovoli odpiranje %@?"; + diff --git a/firefox-ios/Shared/Supporting Files/sl.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/sl.lproj/Settings.strings index 85f89fbedbb1..024e3ec29e9b 100644 --- a/firefox-ios/Shared/Supporting Files/sl.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/sl.lproj/Settings.strings @@ -103,6 +103,9 @@ /* Navigation title for search page in the Settings menu. */ "Settings.Search.PageTitle.v121" = "Iskanje"; +/* Description for `Show in Private Sessions` toggle, located in `Suggestions from Search Engines` section in the Search page in the Settings menu. */ +"Settings.Search.PrivateSession.Description.v125" = "Prikazuj predloge iskalnikov v zasebnih sejah"; + /* Label for toggle. Explains that in private browsing mode, the search suggestions which appears at the top of the search bar, can be toggled on or off. Located in the Private Session section in the Search page in the Settings menu. */ "Settings.Search.PrivateSession.Setting.v122" = "Prikazuj predloge v zasebnem brskanju"; @@ -124,6 +127,9 @@ /* In the search page of the Settings menu, the title for the link to the SUMO Page about Firefox Suggest. */ "Settings.Search.Suggest.LearnAboutSuggestions.v124" = "Več o Firefoxovih predlogih"; +/* Description for `Show in Private Sessions` toggle, located in `Address Bar - Firefox Suggest` section in the Search page in the Settings menu. */ +"Settings.Search.Suggest.PrivateSession.Description.v125" = "Prikazuj Firefoxove predloge v zasebnih sejah"; + /* In the Search page of the Settings menu, the title for the setting to enable search browsing history. */ "Settings.Search.Suggest.SearchBrowsingHistory.Title.v124" = "Iskanje po zgodovini iskanja"; diff --git a/firefox-ios/Shared/Supporting Files/sl.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/sl.lproj/Toolbar.strings new file mode 100644 index 000000000000..0d6618af83fe --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/sl.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Nov zavihek"; + diff --git a/firefox-ios/Shared/Supporting Files/sq.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/sq.lproj/EditAddress.strings index e4b8864f959d..b6b8e4b6a007 100644 --- a/firefox-ios/Shared/Supporting Files/sq.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/sq.lproj/EditAddress.strings @@ -124,6 +124,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "Adresa S’u Ruajt Dot"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Adresa S’u Hoq Dot"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Riprovoni"; diff --git a/firefox-ios/Shared/Supporting Files/sq.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/sq.lproj/EnhancedTrackingProtection.strings index 3599a9b5bafe..04180cb82ea4 100644 --- a/firefox-ios/Shared/Supporting Files/sq.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/sq.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Lidhje jo e sigurt"; +/* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "“Cookies” gjurmimi nga sajte në sajte: %@"; + /* Text to let users know how many fingerprinters were blocked on the current website. The placeholder will show the number of fingerprinters detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.Fingerprinter.v129" = "Krijues shenjash gishtash: %@"; diff --git a/firefox-ios/Shared/Supporting Files/sq.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/sq.lproj/Toolbar.strings new file mode 100644 index 000000000000..443e4894d9ed --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/sq.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Skedë e Re"; + diff --git a/firefox-ios/Shared/Supporting Files/sv.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/sv.lproj/EditAddress.strings index 4cdce964ae2d..fdebeee3247b 100644 --- a/firefox-ios/Shared/Supporting Files/sv.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/sv.lproj/EditAddress.strings @@ -14,7 +14,7 @@ "Addresses.EditAddress.AutofillAddAddressTitle.v129" = "Lägg till adress"; /* Label for the area field, allowing users to specify a particular area within a city or region. This detail can improve the specificity and accuracy of autofilled addresses. */ -"Addresses.EditAddress.AutofillAddressArea.v129" = "Yta"; +"Addresses.EditAddress.AutofillAddressArea.v129" = "Område"; /* Label for the field where users input the city part of their address. This information is crucial for mail delivery and service provision, ensuring accurate city identification in autofill settings. */ "Addresses.EditAddress.AutofillAddressCity.v129" = "Stad"; @@ -80,7 +80,7 @@ "Addresses.EditAddress.AutofillAddressProvince.v129" = "Län"; /* Label for the state field, a necessary component of addresses in many countries, especially the USA. It ensures that state-specific details are correctly filled in forms using autofill. */ -"Addresses.EditAddress.AutofillAddressState.v129" = "Status"; +"Addresses.EditAddress.AutofillAddressState.v129" = "Stat"; /* Label for the suburb field, enabling users to add suburb details to their address. This is important for accurate delivery and services in suburban areas, enhancing autofill functionality. */ "Addresses.EditAddress.AutofillAddressSuburb.v129" = "Förort"; @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "Adressen kunde inte sparas"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Adressen kunde inte tas bort"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Försök igen"; diff --git a/firefox-ios/Shared/Supporting Files/sv.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/sv.lproj/EnhancedTrackingProtection.strings index e25ae8521144..2162cb2abf25 100644 --- a/firefox-ios/Shared/Supporting Files/sv.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/sv.lproj/EnhancedTrackingProtection.strings @@ -64,7 +64,7 @@ "Menu.EnhancedTrackingProtection.SwitchOff.Text.v128" = "Skydd är AV. Vi föreslår att du slår på det igen."; /* A switch to disable enhanced tracking protection inside the menu. */ -"Menu.EnhancedTrackingProtection.SwitchOff.Text.v129" = "Skydd är AV. Vi föreslår att du slår på dem igen."; +"Menu.EnhancedTrackingProtection.SwitchOff.Text.v129" = "Skydd är AV. Vi föreslår att du slår på det igen."; /* A switch to disable enhanced tracking protection inside the menu. */ "Menu.EnhancedTrackingProtection.SwitchOn.Text.v128" = "Om något ser trasigt ut på den här webbplatsen, försök att stänga av det."; diff --git a/firefox-ios/Shared/Supporting Files/sv.lproj/ScanQRCode.strings b/firefox-ios/Shared/Supporting Files/sv.lproj/ScanQRCode.strings index 9913555a4590..35354c207328 100644 --- a/firefox-ios/Shared/Supporting Files/sv.lproj/ScanQRCode.strings +++ b/firefox-ios/Shared/Supporting Files/sv.lproj/ScanQRCode.strings @@ -5,5 +5,5 @@ "ScanQRCode.ConfirmOpenURL.DenyButton.v129" = "Neka"; /* Text of the prompt to ask user permission to open a URL from a scanned QR code. Placeholder is app name. */ -"ScanQRCode.ConfirmOpenURL.Message.v129" = "Tillåt %@ att öppnas?"; +"ScanQRCode.ConfirmOpenURL.Message.v129" = "Tillåta %@ att öppna?"; diff --git a/firefox-ios/Shared/Supporting Files/sv.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/sv.lproj/Toolbar.strings new file mode 100644 index 000000000000..580543ef3975 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/sv.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Ny flik"; + diff --git a/firefox-ios/Shared/Supporting Files/th.lproj/ActivityStream.strings b/firefox-ios/Shared/Supporting Files/th.lproj/ActivityStream.strings new file mode 100644 index 000000000000..f9e443e496ce --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/th.lproj/ActivityStream.strings @@ -0,0 +1,6 @@ +/* String used in the section title of the Bookmarks section on Home Screen. */ +"ActivityStream.Bookmarks.Title.v128" = "ที่คั่นหน้า"; + +/* Show all button text for Bookmarks items on the home page, which opens the Bookmarks panel when tapped. */ +"Bookmarks.Actions.More.v128" = "แสดงทั้งหมด"; + diff --git a/firefox-ios/Shared/Supporting Files/th.lproj/AddressToolbar.strings b/firefox-ios/Shared/Supporting Files/th.lproj/AddressToolbar.strings new file mode 100644 index 000000000000..7fa41a851787 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/th.lproj/AddressToolbar.strings @@ -0,0 +1,12 @@ +/* Accessibility label for the address field in the address toolbar. */ +"AddressToolbar.Location.A11y.Label.v128" = "ค้นหาหรือป้อนที่อยู่"; + +/* Placeholder for the address field in the address toolbar. */ +"AddressToolbar.Location.Placeholder.v128" = "ค้นหาหรือป้อนที่อยู่"; + +/* Accessibility label for the lock icon button in the address field of the address toolbar, responsible with Privacy & Security Settings. */ +"AddressToolbar.PrivacyAndSecuriySettings.A11y.Label.v128" = "การตั้งค่าความเป็นส่วนตัวและความปลอดภัย"; + +/* Accessibility label for the search engine icon in the address field of the address toolbar. The placeholder is getting replaced with the name of the search engine (e.g. Google). */ +"AddressToolbar.SearchEngine.A11y.Label.v128" = "เครื่องมือค้นหา: %@"; + diff --git a/firefox-ios/Shared/Supporting Files/th.lproj/CustomizeFirefoxHome.strings b/firefox-ios/Shared/Supporting Files/th.lproj/CustomizeFirefoxHome.strings index f82475fe3fd8..bfc8b35bb358 100644 --- a/firefox-ios/Shared/Supporting Files/th.lproj/CustomizeFirefoxHome.strings +++ b/firefox-ios/Shared/Supporting Files/th.lproj/CustomizeFirefoxHome.strings @@ -1,3 +1,6 @@ +/* In the settings menu, in the Firefox homepage customization section, this is the title for the option that allows users to toggle Bookmarks section on the Firefox homepage on or off */ +"Settings.Home.Option.Bookmarks.v128" = "ที่คั่นหน้า"; + /* In the settings menu, in the Firefox homepage customization section, this is the subtitle for the option that allows users to turn the Pocket Recommendations section on the Firefox homepage on or off. The placeholder is the pocket app name. */ "Settings.Home.Option.ThoughtProvokingStories.subtitle.v116" = "บทความขับเคลื่อนโดย %@"; diff --git a/firefox-ios/Shared/Supporting Files/th.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/th.lproj/EditAddress.strings new file mode 100644 index 000000000000..1b7234fba800 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/th.lproj/EditAddress.strings @@ -0,0 +1,141 @@ +/* Title for the cancel button in the remove address alert. */ +"Addresses.EditAddress.Alert.CancelButton.v129" = "ยกเลิก"; + +/* Message explaining the consequences of removing an address from all synced devices. */ +"Addresses.EditAddress.Alert.Message.v129" = "ที่อยู่นี้จะถูกเอาออกจากอุปกรณ์ที่ซิงค์ของคุณทั้งหมด"; + +/* Title for the remove button in the remove address alert. */ +"Addresses.EditAddress.Alert.RemoveButton.v129" = "เอาออก"; + +/* Title for the alert indicating the action to remove an address. */ +"Addresses.EditAddress.Alert.Title.v129" = "เอาที่อยู่ออก"; + +/* Title for the interface option where users can add a new address for autofill purposes. This facilitates quicker form completion by automatically filling in the user's address information. */ +"Addresses.EditAddress.AutofillAddAddressTitle.v129" = "เพิ่มที่อยู่"; + +/* Label for the area field, allowing users to specify a particular area within a city or region. This detail can improve the specificity and accuracy of autofilled addresses. */ +"Addresses.EditAddress.AutofillAddressArea.v129" = "เขต"; + +/* Label for the field where users input the city part of their address. This information is crucial for mail delivery and service provision, ensuring accurate city identification in autofill settings. */ +"Addresses.EditAddress.AutofillAddressCity.v129" = "เมือง"; + +/* Label for the field where users can specify just the country, used in contexts where full address details are not required. Simplifies autofill when only country information is necessary. */ +"Addresses.EditAddress.AutofillAddressCountryOnly.v129" = "ประเทศ"; + +/* Label for the country or region field in address forms, allowing users to specify their country or territorial region. This is fundamental for international mail and services, ensuring autofill accuracy across borders. */ +"Addresses.EditAddress.AutofillAddressCountryRegion.v129" = "ประเทศหรือภูมิภาค"; + +/* Label for the county field, crucial for addressing in regions where county lines play a key role in postal services. Enhances autofill accuracy by including county information. */ +"Addresses.EditAddress.AutofillAddressCounty.v129" = "เคาน์ตี"; + +/* Label for the department field, used in countries like France and Colombia where departments are a key administrative division. Ensures correct departmental information is autofilled. */ +"Addresses.EditAddress.AutofillAddressDepartment.v129" = "จังหวัด"; + +/* Label for the district field in the address form, allowing users to specify their district for more precise location identification. This aids in refining address details for accurate autofill. */ +"Addresses.EditAddress.AutofillAddressDistrict.v129" = "เขต"; + +/* Label for the Do/Si field, pertinent to addresses in South Korea. Do/Si refers to provincial level divisions, and specifying this enhances address accuracy in autofill settings. */ +"Addresses.EditAddress.AutofillAddressDoSi.v129" = "จังหวัด"; + +/* Label for the Eircode field, specific to Ireland. It's a unique postal code system that helps in precise location identification, enhancing the effectiveness of autofill. */ +"Addresses.EditAddress.AutofillAddressEircode.v129" = "เอียร์โค้ด"; + +/* Label for the email address field, where users input their email. Critical for digital communication and account verification, this ensures email addresses are autofilled accurately. */ +"Addresses.EditAddress.AutofillAddressEmail.v129" = "อีเมล"; + +/* Label for the emirate field, essential for addresses in the United Arab Emirates. Including emirate details ensures the autofill feature accurately represents user addresses. */ +"Addresses.EditAddress.AutofillAddressEmirate.v129" = "เอมิเรต"; + +/* Label for the field where users specify the name of an island, if applicable. Important for addresses in archipelagic regions, aiding in precise location identification during autofill. */ +"Addresses.EditAddress.AutofillAddressIsland.v129" = "เกาะ"; + +/* Label for the field where the user inputs their full name as part of an address form. Essential for personalized form submissions and ensuring information accuracy in autofilled forms. */ +"Addresses.EditAddress.AutofillAddressName.v129" = "ชื่อ"; + +/* Label for the field where users can input the name of their neighborhood. This detail adds precision to addresses, especially in densely populated areas, improving the accuracy of autofill. */ +"Addresses.EditAddress.AutofillAddressNeighborhood.v129" = "ชุมชน"; + +/* Label for the oblast field, relevant for addresses in countries like Russia and Ukraine. Oblasts are a significant administrative division, and their specification aids in autofill accuracy. */ +"Addresses.EditAddress.AutofillAddressOblast.v129" = "แคว้น"; + +/* Label for the input field designated for the organization's name related to the address. Helps in distinguishing addresses used for business or personal purposes in autofill settings. */ +"Addresses.EditAddress.AutofillAddressOrganization.v129" = "องค์กร"; + +/* Label for the parish field, significant in places where parishes are used for local administration and addressing. Ensures users can specify parish details for better autofill accuracy. */ +"Addresses.EditAddress.AutofillAddressParish.v129" = "ตำบล"; + +/* Label for the PIN (Postal Index Number) field, used in India. It's a code representing a specific area, crucial for accurate mail delivery and autofill functionality. */ +"Addresses.EditAddress.AutofillAddressPin.v129" = "พิน"; + +/* Label for the postal code field, universally used in address forms to specify the area code for mail sorting. Essential for autofill to ensure mail and services are accurately routed. */ +"Addresses.EditAddress.AutofillAddressPostalCode.v129" = "รหัสไปรษณีย์"; + +/* Label for the post town field, used primarily in the UK and some other regions for mail sorting. Essential for users in applicable areas to specify for correct mail delivery through autofill. */ +"Addresses.EditAddress.AutofillAddressPostTown.v129" = "เมือง"; + +/* Label for the prefecture field, essential for addresses in countries like Japan where prefectures are a major administrative division. Aids in precise location specification for autofill. */ +"Addresses.EditAddress.AutofillAddressPrefecture.v129" = "อำเภอ"; + +/* Label for the province field, required in countries where provinces are a primary administrative division. Helps in pinpointing the user's location more accurately for autofill purposes. */ +"Addresses.EditAddress.AutofillAddressProvince.v129" = "จังหวัด"; + +/* Label for the state field, a necessary component of addresses in many countries, especially the USA. It ensures that state-specific details are correctly filled in forms using autofill. */ +"Addresses.EditAddress.AutofillAddressState.v129" = "สถานะ"; + +/* Label for the suburb field, enabling users to add suburb details to their address. This is important for accurate delivery and services in suburban areas, enhancing autofill functionality. */ +"Addresses.EditAddress.AutofillAddressSuburb.v129" = "ชานเมือง"; + +/* Label for the telephone number field, allowing users to input their contact number. This is essential for communication and service provision, ensuring contact details are autofilled correctly. */ +"Addresses.EditAddress.AutofillAddressTel.v129" = "โทรศัพท์"; + +/* Label for the input field for the townland, a specific type of land division used in rural areas. Enhances address detail for users in regions where townlands are a common addressing component. */ +"Addresses.EditAddress.AutofillAddressTownland.v129" = "เขต"; + +/* Label for the field to input the name of a village or township. This is crucial for addresses in rural areas, ensuring the autofill feature accurately captures all necessary geographical details. */ +"Addresses.EditAddress.AutofillAddressVillageTownship.v129" = "หมู่บ้านหรือเขตการปกครอง"; + +/* Label for the ZIP code field, primarily used in the United States for mail sorting. Key for autofill to accurately complete addresses for shipping, billing, and service provision. */ +"Addresses.EditAddress.AutofillAddressZip.v129" = "รหัสไปรษณีย์"; + +/* Label for the button to cancel the current autofill operation or exit the form without saving changes. Provides users with an option to back out of a process without making any modifications. */ +"Addresses.EditAddress.AutofillCancelButton.v129" = "ยกเลิก"; + +/* Title for the option allowing users to edit an existing saved address. This is used within the settings for autofill, enabling users to update their address details for accurate form autofilling. */ +"Addresses.EditAddress.AutofillEditAddressTitle.v129" = "แก้ไขที่อยู่"; + +/* Title for the input field where users can enter their street address. This is used within the settings for autofill, allowing users to provide their street address for accurate form autofilling. */ +"Addresses.EditAddress.AutofillEditStreetAddressTitle.v129" = "ที่อยู่ถนน"; + +/* Label for the button to save the current address details entered or edited by the user. This action confirms the user's changes and updates their autofill settings accordingly. */ +"Addresses.EditAddress.AutofillSaveButton.v129" = "บันทึก"; + +/* Title for the option allowing users to view an existing saved address. This is used within the settings for autofill, enabling users to see their address details for accurate form autofilling. */ +"Addresses.EditAddress.AutofillViewAddressTitle.v129" = "ดูที่อยู่"; + +/* Button label for closing the view where user can view their address info. */ +"Addresses.EditAddress.CloseNavBarButtonLabel.v129" = "ปิด"; + +/* Button label for editing the address details shown in the form. */ +"Addresses.EditAddress.EditNavBarButtonLabel.v129" = "แก้ไข"; + +/* Title for button that offers the user the option to remove an address. */ +"Addresses.EditAddress.RemoveAddressButtonTitle.v129" = "เอาที่อยู่ออก"; + +/* Toast message confirming that an address has been successfully removed. */ +"Addresses.Toast.AddressRemovedConfirmation.v129" = "เอาที่อยู่ออกแล้ว"; + +/* Toast message confirming that an address has been successfully saved. */ +"Addresses.Toast.AddressSavedConfirmation.v129" = "บันทึกที่อยู่แล้ว"; + +/* Toast message indicating an error occurred while trying to save an address. */ +"Addresses.Toast.AddressSaveError.v129" = "ไม่สามารถบันทึกที่อยู่ได้"; + +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "ไม่สามารถเอาที่อยู่ออกได้"; + +/* Suggestion to try again after an error occurred while trying to save an address. */ +"Addresses.Toast.AddressSaveRetrySuggestion.v129" = "ลองอีกครั้ง"; + +/* Toast message confirming that an address has been successfully updated. */ +"Addresses.Toast.AddressUpdatedConfirmation.v129" = "ปรับปรุงข้อมูลที่อยู่แล้ว"; + diff --git a/firefox-ios/Shared/Supporting Files/th.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/th.lproj/EnhancedTrackingProtection.strings new file mode 100644 index 000000000000..c1a1c27b28cc --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/th.lproj/EnhancedTrackingProtection.strings @@ -0,0 +1,71 @@ +/* The text for the clear cookies and site data alert button inside the enhanced tracking protection screen. */ +"Menu.EnhancedTrackingProtection.ClearData.AlertCancelButton.v128" = "ยกเลิก"; + +/* The text for the clear cookies and site data alert button inside the enhanced tracking protection screen. */ +"Menu.EnhancedTrackingProtection.ClearData.AlertOkButton.v128" = "ล้าง"; + +/* The text for the clear cookies and site data alert inside the enhanced tracking protection screen. The placeholder will be replaced with the user's currently visited website */ +"Menu.EnhancedTrackingProtection.ClearData.AlertText.v128" = "การเอาคุกกี้และข้อมูลไซต์สำหรับ %@ ออกอาจทำให้คุณออกจากระบบเว็บไซต์และล้างตะกร้าสินค้า"; + +/* The title for the clear cookies and site data alert inside the enhanced tracking protection screen. */ +"Menu.EnhancedTrackingProtection.ClearData.AlertTitle.v128" = "ล้างคุกกี้และข้อมูลไซต์"; + +/* The title for the clear cookies and site data button inside the enhanced tracking protection screen. */ +"Menu.EnhancedTrackingProtection.ClearData.ButtonTitle.v128" = "ล้างคุกกี้และข้อมูลไซต์"; + +/* The text for the clear cookies and site data toast that appears when the user selects to clear the cookies */ +"Menu.EnhancedTrackingProtection.ClearData.ToastMessage.v128" = "เอาคุกกี้และข้อมูลไซต์ออกแล้ว"; + +/* Text to let users know that the current website is secure. */ +"Menu.EnhancedTrackingProtection.Details.ConnectionSecure.v128" = "การเชื่อมต่อปลอดภัย"; + +/* Text to let users know that the current website is not secure. */ +"Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "การเชื่อมต่อไม่ปลอดภัย"; + +/* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "คุกกี้ติดตามข้ามไซต์: %@"; + +/* Text to let users know how many fingerprinters were blocked on the current website. The placeholder will show the number of fingerprinters detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.Fingerprinter.v129" = "ลายนิ้วมือดิจิทัล: %@"; + +/* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "ตัวติดตามโซเชียลมีเดีย: %@"; + +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked + Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "ตัวติดตามที่ถูกปิดกั้น: %@"; + +/* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ +"Menu.EnhancedTrackingProtection.Details.Verifier.v128" = "ยืนยันโดย %@"; + +/* Header for the enhanced tracking protection screen when the user has opted out of the feature. Placeholder will be replaced by the app name */ +"Menu.EnhancedTrackingProtection.Off.Header.v128" = "%@ ไม่ได้ทำงานอยู่ เราขอแนะนำให้เปิดการป้องกันกลับมาใหม่อีกครั้ง"; + +/* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ +"Menu.EnhancedTrackingProtection.Off.Title.v128" = "คุณปิดการป้องกัน"; + +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. + Header for the enhanced tracking protection screen when the user has selected to be protected. */ +"Menu.EnhancedTrackingProtection.On.Header.v128" = "คุณได้รับการปกป้อง หากเราพบสิ่งใดเราจะแจ้งให้คุณทราบ"; + +/* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "โปรดระวังในไซต์นี้"; + +/* Title for the enhanced tracking protection screen when the user has selected to be protected. The placeholder will have the value of the app name */ +"Menu.EnhancedTrackingProtection.On.Title.v128" = "%@ ทำงานอยู่"; + +/* The title for the privacy settings button inside the enhanced tracking protection screen. */ +"Menu.EnhancedTrackingProtection.PrivacySettings.Title.v128" = "การตั้งค่าความเป็นส่วนตัว"; + +/* Title for the switch to enable/disable enhanced tracking protection inside the menu. */ +"Menu.EnhancedTrackingProtection.Switch.Title.v128" = "การป้องกันการติดตามแบบพิเศษ"; + +/* A switch to disable enhanced tracking protection inside the menu. */ +"Menu.EnhancedTrackingProtection.SwitchOff.Text.v128" = "การป้องกันปิดอยู่ เราขอแนะนำให้เปิดกลับมาใหม่อีกครั้ง"; + +/* A switch to disable enhanced tracking protection inside the menu. */ +"Menu.EnhancedTrackingProtection.SwitchOff.Text.v129" = "การป้องกันปิดอยู่ เราขอแนะนำให้เปิดกลับมาใหม่อีกครั้ง"; + +/* A switch to disable enhanced tracking protection inside the menu. */ +"Menu.EnhancedTrackingProtection.SwitchOn.Text.v128" = "หากมีบางอย่างดูเสียหายในไซต์นี้ ให้ลองปิดการป้องกัน"; + diff --git a/firefox-ios/Shared/Supporting Files/th.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/th.lproj/Microsurvey.strings index 1485c21fbd95..1ccb90735d0d 100644 --- a/firefox-ios/Shared/Supporting Files/th.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/th.lproj/Microsurvey.strings @@ -7,6 +7,9 @@ /* On top of the bottom toolbar, there can be a microsurvey prompt, this is the accessibility label for the close button that appears on the prompt that allows the user to dismiss the microsurvey prompt. */ "Microsurvey.Prompt.Close.Button.AccessibilityLabel.v127" = "ปิด"; +/* On top of the bottom toolbar, there can be a microsurvey prompt, this is the logo image that appears on the prompt to inform the prompt is coming from the app specifically. Placeholder is for the app name. */ +"Microsurvey.Prompt.LogoImage.AccessibilityLabel.v129" = "โลโก้ %@"; + /* On top of the bottom toolbar, there can be a microsurvey prompt, this is the title for the text that appears on the prompt to inform the user that this is a prompt to take a survey. Placeholder is for the app name. */ "Microsurvey.Prompt.TitleLabel.v127" = "ช่วยเราทำให้ %@ ดีขึ้น โดยสละเวลาเพียงนาทีเดียว"; @@ -28,6 +31,12 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the title for the header on the screen. */ "Microsurvey.Survey.HeaderLabel.v127" = "ทำแบบสำรวจนี้ให้เสร็จสมบูรณ์"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the title for the header on the screen. */ +"Microsurvey.Survey.HeaderLabel.v129" = "โปรดทำแบบสำรวจให้เสร็จสมบูรณ์"; + +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the logo image that appears on the bottom sheet that informs the user that it is coming from the app specifically. Placeholder is for the app name. */ +"Microsurvey.Survey.LogoImage.AccessibilityLabel.v129" = "โลโก้ %@"; + /* On the microsurvey, this is the title for one of the options that the user can select to answer the survey. */ "Microsurvey.Survey.Options.LikertScaleOption1.v127" = "พึงพอใจมาก"; @@ -43,6 +52,18 @@ /* On the microsurvey, this is the title for one of the options that the user can select to answer the survey. */ "Microsurvey.Survey.Options.LikertScaleOption5.v127" = "ไม่พอใจมาก"; +/* On the microsurvey, this is the title for one of the options that the user can select to answer the survey. It indicates that the user has not use the feature that the survey is inquiring about. */ +"Microsurvey.Survey.Options.LikertScaleOption6.v129" = "ฉันไม่ได้ใช้มัน"; + +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states the order the survey option in the list of options. First placeholder is the number the option is in the list and the second placeholder is the total number of options such as 1 out of 6. */ +"Microsurvey.Survey.OptionsOrder.AccessibilityLabel.v129" = "%1$@ จาก %2$@"; + /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this the title of a link on the survey and allows the user to navigate to our privacy policy details. */ "Microsurvey.Survey.PrivacyPolicyLink.v127" = "ประกาศความเป็นส่วนตัว"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was selected. */ +"Microsurvey.Survey.RadioButton.Selected.AccessibilityLabel.v129" = "เลือกแล้ว"; + +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ +"Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "ไม่ได้เลือก"; + diff --git a/firefox-ios/Shared/Supporting Files/th.lproj/PasswordAutofill.strings b/firefox-ios/Shared/Supporting Files/th.lproj/PasswordAutofill.strings index 915b135c3484..832f2d863c73 100644 --- a/firefox-ios/Shared/Supporting Files/th.lproj/PasswordAutofill.strings +++ b/firefox-ios/Shared/Supporting Files/th.lproj/PasswordAutofill.strings @@ -1,3 +1,6 @@ +/* This label is used in a cell found in the list of autofill login options in place of an actual username to denote that no username was saved for this login */ +"PasswordAutofill.LoginListCellNoUsername.v129" = "(ไม่มีชื่อผู้ใช้)"; + /* This label is used for a button in the password list screen allowing users to manage their saved passwords. It's meant to direct users to where they can add, remove, or edit their saved passwords. */ "PasswordAutofill.ManagePasswordsButton.v124" = "จัดการรหัสผ่าน"; diff --git a/firefox-ios/Shared/Supporting Files/th.lproj/QRCode.strings b/firefox-ios/Shared/Supporting Files/th.lproj/QRCode.strings new file mode 100644 index 000000000000..b3ea815b926a --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/th.lproj/QRCode.strings @@ -0,0 +1,3 @@ +/* Accessibility label of the QR code button in the toolbar */ +"QRCode.Toolbar.Button.A11y.Title.v128" = "สแกนคิวอาร์โค้ด"; + diff --git a/firefox-ios/Shared/Supporting Files/th.lproj/ScanQRCode.strings b/firefox-ios/Shared/Supporting Files/th.lproj/ScanQRCode.strings new file mode 100644 index 000000000000..e73e01c34135 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/th.lproj/ScanQRCode.strings @@ -0,0 +1,9 @@ +/* Allow button to open URL from scanned QR Code */ +"ScanQRCode.ConfirmOpenURL.AllowButton.v129" = "อนุญาต"; + +/* Deny button to cancel opening URL from scanned QR Code */ +"ScanQRCode.ConfirmOpenURL.DenyButton.v129" = "ปฏิเสธ"; + +/* Text of the prompt to ask user permission to open a URL from a scanned QR code. Placeholder is app name. */ +"ScanQRCode.ConfirmOpenURL.Message.v129" = "อนุญาตให้ %@ เปิดหรือไม่?"; + diff --git a/firefox-ios/Shared/Supporting Files/th.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/th.lproj/Toolbar.strings new file mode 100644 index 000000000000..2010ad34c1d2 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/th.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "แท็บใหม่"; + diff --git a/firefox-ios/Shared/Supporting Files/tr.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/tr.lproj/EditAddress.strings index bf8b862c8235..50f76b49f020 100644 --- a/firefox-ios/Shared/Supporting Files/tr.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/tr.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "Adres kaydedilemedi"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Adres kaldırılamadı"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Yeniden dene"; diff --git a/firefox-ios/Shared/Supporting Files/tr.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/tr.lproj/Toolbar.strings new file mode 100644 index 000000000000..18d25f2411dd --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/tr.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Yeni sekme"; + diff --git a/firefox-ios/Shared/Supporting Files/ug.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/ug.lproj/EditAddress.strings index d4a43d3346d2..886cdc5ad875 100644 --- a/firefox-ios/Shared/Supporting Files/ug.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/ug.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "ئادرېسنى ساقلىيالمايدۇ"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "ئادرېسنى چىقىرىۋېتەلمەيدۇ"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "قايتا سىنا"; diff --git a/firefox-ios/Shared/Supporting Files/ug.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/ug.lproj/Toolbar.strings new file mode 100644 index 000000000000..3c17178827ed --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/ug.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "يېڭى بەتكۈچ"; + diff --git a/firefox-ios/Shared/Supporting Files/vi.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/vi.lproj/EditAddress.strings index 137e42206ce3..34078b06334a 100644 --- a/firefox-ios/Shared/Supporting Files/vi.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/vi.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "Không thể lưu địa chỉ"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Không thể xóa địa chỉ"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Thử lại"; diff --git a/firefox-ios/Shared/Supporting Files/vi.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/vi.lproj/Toolbar.strings new file mode 100644 index 000000000000..e29c3c989adf --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/vi.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Thẻ mới"; + diff --git a/firefox-ios/Shared/Supporting Files/zh-CN.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/zh-CN.lproj/EditAddress.strings index 94b64b61ab6e..c9196a32edb5 100644 --- a/firefox-ios/Shared/Supporting Files/zh-CN.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/zh-CN.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "无法保存地址"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "无法移除地址"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "重试"; diff --git a/firefox-ios/Shared/Supporting Files/zh-CN.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/zh-CN.lproj/Toolbar.strings new file mode 100644 index 000000000000..a33d20a5f22f --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/zh-CN.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "新建标签页"; + diff --git a/firefox-ios/Shared/Supporting Files/zh-TW.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/zh-TW.lproj/EditAddress.strings index 0b86e0aeb501..8faaa8eb4a3c 100644 --- a/firefox-ios/Shared/Supporting Files/zh-TW.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/zh-TW.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "無法儲存地址"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "無法移除地址"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "重試"; diff --git a/firefox-ios/Shared/Supporting Files/zh-TW.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/zh-TW.lproj/Toolbar.strings new file mode 100644 index 000000000000..ba1ff910542a --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/zh-TW.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "開新分頁"; + diff --git a/firefox-ios/Shared/dsb.lproj/Localizable.strings b/firefox-ios/Shared/dsb.lproj/Localizable.strings index d861801b1f52..a8f575e784f6 100644 --- a/firefox-ios/Shared/dsb.lproj/Localizable.strings +++ b/firefox-ios/Shared/dsb.lproj/Localizable.strings @@ -5,10 +5,10 @@ "+" = "+"; /* Authentication prompt message with no realm. Parameter is the hostname of the site */ -"A username and password are being requested by %@." = "Wužywarske mě a gronidło pominatej se wót %@."; +"A username and password are being requested by %@." = "Wužywaŕske mě a gronidło pominatej se wót %@."; /* Authentication prompt message with a realm. First parameter is the hostname. Second is the realm string */ -"A username and password are being requested by %@. The site says: %@" = "Wužywarske mě a gronidło pominatej se wót %1$@. Sedło groni: %2$@"; +"A username and password are being requested by %@. The site says: %@" = "Wužywaŕske mě a gronidło pominatej se wót %1$@. Sedło groni: %2$@"; /* Button for reader mode font size. Keep this extremely short! This is shown in the reader mode toolbar. */ "Aa" = "Aa"; @@ -77,7 +77,7 @@ "Amazon" = "Amazon"; /* Authentication prompt title */ -"Authentication required" = "Awtentifikacija trěbna"; +"Authentication required" = "Awtentifikacija trjebna"; /* Accessibility label for the Back button in the tab toolbar. */ "Back" = "Slědk"; @@ -1754,7 +1754,7 @@ "Use stage servers" = "Testowe serwery wužywaś"; /* Username textbox in Authentication prompt */ -"Username" = "Wužywarske mě"; +"Username" = "Wužywaŕske mě"; /* The message of the error displayed to a user when they trying to change a wallpaper failed. */ "Wallpaper.Change.Error.Body.v106" = "Něco njejo se raźiło z toś tym slězynowym wobrazom."; diff --git a/firefox-ios/Shared/dsb.lproj/LoginManager.strings b/firefox-ios/Shared/dsb.lproj/LoginManager.strings index b68a67cc7fd4..7733e1e022d0 100644 --- a/firefox-ios/Shared/dsb.lproj/LoginManager.strings +++ b/firefox-ios/Shared/dsb.lproj/LoginManager.strings @@ -77,7 +77,7 @@ "Select All" = "Wšykne wubraś"; /* Label displayed above the username row in Login Detail View. */ -"Username" = "Wužywarske mě"; +"Username" = "Wužywaŕske mě"; /* Label displayed above the website row in Login Detail View. */ "Website" = "Websedło"; diff --git a/firefox-ios/Shared/es-MX.lproj/Localizable.strings b/firefox-ios/Shared/es-MX.lproj/Localizable.strings index 61fbc31d6381..7a1d9694ad4f 100644 --- a/firefox-ios/Shared/es-MX.lproj/Localizable.strings +++ b/firefox-ios/Shared/es-MX.lproj/Localizable.strings @@ -757,6 +757,9 @@ /* Label for the button, displayed in the menu, takes you to History screen when pressed. */ "Menu.History.Label" = "Historial"; +/* Label for the new private tab button in the menu page. Pressing this button opens a new private tab. */ +"Menu.NewPrivateTab.Label" = "Nueva pestaña privada"; + /* Label for the new tab button in the menu page. Pressing this button opens a new tab. */ "Menu.NewTab.v99" = "Nueva pestaña"; diff --git a/firefox-ios/Shared/es-MX.lproj/Menu.strings b/firefox-ios/Shared/es-MX.lproj/Menu.strings index fd43bf0cd701..9669ecea1a34 100644 --- a/firefox-ios/Shared/es-MX.lproj/Menu.strings +++ b/firefox-ios/Shared/es-MX.lproj/Menu.strings @@ -4,6 +4,9 @@ /* Label for the button, displayed in the menu, used to copy the current page link to the clipboard. */ "Menu.CopyLink.Title" = "Copiar enlace"; +/* Label for the button, displayed in the menu, downloads a pdf when pressed. */ +"Menu.DownloadPDF.Label.v129" = "Descargar PDF"; + /* Label for the button, displayed in the menu, used to open the toolbar to search for text within the current page. */ "Menu.FindInPageAction.Title" = "Encontrar en la página"; diff --git a/firefox-ios/Shared/nb.lproj/Localizable.strings b/firefox-ios/Shared/nb.lproj/Localizable.strings index 458c40cc4a61..728aae9c8536 100644 --- a/firefox-ios/Shared/nb.lproj/Localizable.strings +++ b/firefox-ios/Shared/nb.lproj/Localizable.strings @@ -757,6 +757,9 @@ /* Label for the button, displayed in the menu, takes you to History screen when pressed. */ "Menu.History.Label" = "Historikk"; +/* Label for the new private tab button in the menu page. Pressing this button opens a new private tab. */ +"Menu.NewPrivateTab.Label" = "Ny privat fane"; + /* Label for the new tab button in the menu page. Pressing this button opens a new tab. */ "Menu.NewTab.v99" = "Ny fane"; diff --git a/firefox-ios/Shared/nb.lproj/Menu.strings b/firefox-ios/Shared/nb.lproj/Menu.strings index 03521ff634f9..75a16cb73ffb 100644 --- a/firefox-ios/Shared/nb.lproj/Menu.strings +++ b/firefox-ios/Shared/nb.lproj/Menu.strings @@ -4,6 +4,12 @@ /* Label for the button, displayed in the menu, used to copy the current page link to the clipboard. */ "Menu.CopyLink.Title" = "Kopier lenke"; +/* Toast displayed to user after downlaod pdf was pressed. */ +"Menu.DownloadPDF.Confirm.v129" = "PDF er lastet ned"; + +/* Label for the button, displayed in the menu, downloads a pdf when pressed. */ +"Menu.DownloadPDF.Label.v129" = "Last ned PDF"; + /* Label for the button, displayed in the menu, used to open the toolbar to search for text within the current page. */ "Menu.FindInPageAction.Title" = "Søk på siden"; diff --git a/firefox-ios/Shared/si.lproj/Localizable.strings b/firefox-ios/Shared/si.lproj/Localizable.strings index 24dd3ec49781..ed2f75e52032 100644 --- a/firefox-ios/Shared/si.lproj/Localizable.strings +++ b/firefox-ios/Shared/si.lproj/Localizable.strings @@ -5,10 +5,10 @@ "+" = "+"; /* Authentication prompt message with no realm. Parameter is the hostname of the site */ -"A username and password are being requested by %@." = "%@ වෙතින් පරිශීලක නාමයක් හා මුරපදයක් ඉල්ලා සිටියි."; +"A username and password are being requested by %@." = "%@ වෙතින් පරිශ්‍රීලක නාමයක් හා මුරපදයක් ඉල්ලා සිටියි."; /* Authentication prompt message with a realm. First parameter is the hostname. Second is the realm string */ -"A username and password are being requested by %@. The site says: %@" = "%1$@ විසින් පරිශීලක නාමයක් සහ මුරපදයක් ඉල්ලා සිටියි. අඩවිය පවසන්නේ: %2$@"; +"A username and password are being requested by %@. The site says: %@" = "%1$@ විසින් පරිශ්‍රීලක නාමයක් සහ මුරපදයක් ඉල්ලා සිටියි. අඩවිය පවසන්නේ: %2$@"; /* Button for reader mode font size. Keep this extremely short! This is shown in the reader mode toolbar. */ "Aa" = "Aa"; @@ -1748,7 +1748,7 @@ "Use stage servers" = "අදියර සේවාදායක භාවිතය"; /* Username textbox in Authentication prompt */ -"Username" = "පරිශීලක නාමය"; +"Username" = "පරිශ්‍රීලක නාමය"; /* The message of the error displayed to a user when they trying to change a wallpaper failed. */ "Wallpaper.Change.Error.Body.v106" = "මෙම බිතුපතෙහි යම් දෙයක් වැරදී ඇත."; diff --git a/firefox-ios/Shared/si.lproj/LoginManager.strings b/firefox-ios/Shared/si.lproj/LoginManager.strings index 02eca742c103..9dd804cb1d58 100644 --- a/firefox-ios/Shared/si.lproj/LoginManager.strings +++ b/firefox-ios/Shared/si.lproj/LoginManager.strings @@ -77,7 +77,7 @@ "Select All" = "සියල්ල තෝරන්න"; /* Label displayed above the username row in Login Detail View. */ -"Username" = "පරිශීලක නාමය"; +"Username" = "පරිශ්‍රීලක නාමය"; /* Label displayed above the website row in Login Detail View. */ "Website" = "අඩවිය"; diff --git a/firefox-ios/Shared/th.lproj/Localizable.strings b/firefox-ios/Shared/th.lproj/Localizable.strings index 3d96ed696490..45b086f7e49a 100644 --- a/firefox-ios/Shared/th.lproj/Localizable.strings +++ b/firefox-ios/Shared/th.lproj/Localizable.strings @@ -757,6 +757,9 @@ /* Label for the button, displayed in the menu, takes you to History screen when pressed. */ "Menu.History.Label" = "ประวัติ"; +/* Label for the new private tab button in the menu page. Pressing this button opens a new private tab. */ +"Menu.NewPrivateTab.Label" = "แท็บส่วนตัวใหม่"; + /* Label for the new tab button in the menu page. Pressing this button opens a new tab. */ "Menu.NewTab.v99" = "แท็บใหม่"; @@ -1144,6 +1147,9 @@ /* The placeholder for URL Field when saving a custom search engine */ "Settings.AddCustomEngine.URLPlaceholder" = "URL (แทนที่คำสืบค้นด้วย %s)"; +/* Title of setting to block opening external apps when pressing links. */ +"Settings.BlockOpeningExternalApps.Title" = "ปิดกั้นการเปิดแอปภายนอก"; + /* Button in Data Management that clears all items. */ "Settings.ClearAllWebsiteData.Clear.Button" = "ล้างข้อมูลเว็บไซต์ทั้งหมด"; @@ -1399,6 +1405,9 @@ /* Description displayed under the ”Offer to Open Copied Link” option. See https://bug1223660.bmoattachments.org/attachment.cgi?id=8898349 */ "Settings.OfferClipboardBar.Status" = "เมื่อเปิด Firefox"; +/* Description displayed under the ”Offer to Open Copied Link” option. See https://bug1223660.bmoattachments.org/attachment.cgi?id=8898349. Placeholder is for the app name. */ +"Settings.OfferClipboardBar.Status.v128" = "เมื่อเปิด %@"; + /* Description displayed under the ”Offer to Open Copied Link” option. See https://bug1223660.bmoattachments.org/attachment.cgi?id=8898349 */ "Settings.OfferClipboardBar.StatusV2" = "เมื่อเปิด Firefox"; diff --git a/firefox-ios/Shared/th.lproj/Menu.strings b/firefox-ios/Shared/th.lproj/Menu.strings index 495bff422c86..36a9018048e7 100644 --- a/firefox-ios/Shared/th.lproj/Menu.strings +++ b/firefox-ios/Shared/th.lproj/Menu.strings @@ -4,6 +4,12 @@ /* Label for the button, displayed in the menu, used to copy the current page link to the clipboard. */ "Menu.CopyLink.Title" = "คัดลอกลิงก์"; +/* Toast displayed to user after downlaod pdf was pressed. */ +"Menu.DownloadPDF.Confirm.v129" = "ดาวน์โหลดไฟล์ PDF สำเร็จแล้ว"; + +/* Label for the button, displayed in the menu, downloads a pdf when pressed. */ +"Menu.DownloadPDF.Label.v129" = "ดาวน์โหลด PDF"; + /* Label for the button, displayed in the menu, used to open the toolbar to search for text within the current page. */ "Menu.FindInPageAction.Title" = "ค้นหาในหน้า"; From 340f236e0fa701c7c4942a40851ecba8e8ba7dff Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 16:20:03 +0200 Subject: [PATCH 003/128] Auto update SPM with latest rust-component release 130.0.20240726050301 (#21296) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- firefox-ios/Client.xcodeproj/project.pbxproj | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- focus-ios/Blockzilla.xcodeproj/project.pbxproj | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/firefox-ios/Client.xcodeproj/project.pbxproj b/firefox-ios/Client.xcodeproj/project.pbxproj index 36207b6eb4f0..d0f7500f2c00 100644 --- a/firefox-ios/Client.xcodeproj/project.pbxproj +++ b/firefox-ios/Client.xcodeproj/project.pbxproj @@ -23047,7 +23047,7 @@ repositoryURL = "https://github.com/mozilla/rust-components-swift.git"; requirement = { kind = exactVersion; - version = 130.0.20240724050232; + version = 130.0.20240726050301; }; }; 435C85EE2788F4D00072B526 /* XCRemoteSwiftPackageReference "glean-swift" */ = { diff --git a/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index cb48e650dce5..affeb50fdcdb 100644 --- a/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -95,8 +95,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/mozilla/rust-components-swift.git", "state" : { - "revision" : "21102e5081ce1b7446b110f474d2d2a7a2029527", - "version" : "130.0.20240724050232" + "revision" : "86000c4ce3dc797002c9b6ff91f4cba1ec0dbeba", + "version" : "130.0.20240726050301" } }, { diff --git a/focus-ios/Blockzilla.xcodeproj/project.pbxproj b/focus-ios/Blockzilla.xcodeproj/project.pbxproj index d0c18e55c776..e57f1467014d 100644 --- a/focus-ios/Blockzilla.xcodeproj/project.pbxproj +++ b/focus-ios/Blockzilla.xcodeproj/project.pbxproj @@ -7159,7 +7159,7 @@ repositoryURL = "https://github.com/mozilla/rust-components-swift"; requirement = { kind = exactVersion; - version = 130.0.20240724050232; + version = 130.0.20240726050301; }; }; 8A0E7F2C2BA0F0E0006BC6B6 /* XCRemoteSwiftPackageReference "Fuzi" */ = { diff --git a/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 6b20fdcbcf53..a252ee90b121 100644 --- a/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -51,8 +51,8 @@ "repositoryURL": "https://github.com/mozilla/rust-components-swift", "state": { "branch": null, - "revision": "21102e5081ce1b7446b110f474d2d2a7a2029527", - "version": "130.0.20240724050232" + "revision": "86000c4ce3dc797002c9b6ff91f4cba1ec0dbeba", + "version": "130.0.20240726050301" } }, { From 2d6dfcf26459d26d70c25c21fce65ff3141bd1fc Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 10:37:47 -0400 Subject: [PATCH 004/128] focus-string-import-07-29-2024 (#21317) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- .../Blockzilla/co.lproj/Localizable.strings | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/focus-ios/Blockzilla/co.lproj/Localizable.strings b/focus-ios/Blockzilla/co.lproj/Localizable.strings index 37552cb6f23d..2b0ba454524e 100644 --- a/focus-ios/Blockzilla/co.lproj/Localizable.strings +++ b/focus-ios/Blockzilla/co.lproj/Localizable.strings @@ -8,7 +8,7 @@ "About.privateBullet1" = "Fate ricerche è navigate in l’appiecazione"; /* Label on About screen */ -"About.privateBullet2" = "Bluccate i perseguitatori (o mudificate e preferenze per auturizalli)"; +"About.privateBullet2" = "Bluccate i perseguitatori (o mudificate i parametri per auturizalli)"; /* Label on About screen */ "About.privateBullet3" = "Squassate i canistrelli è ancu e cronolugie di navigazione è di ricerca"; @@ -74,7 +74,7 @@ "Autocomplete.addCustomUrlWithPlus" = "+ Aghjunghje un indirizzu persunalizatu"; /* Label for toast alerting a custom URL has been added */ -"Autocomplete.customUrlAdded" = "Novu indirizzu persunalizatu aghjuntu."; +"Autocomplete.customUrlAdded" = "L’indirizzu web persunalizatu novu hè aghjuntu."; /* Description for enabling or disabling the default list. The placeholder is replaced with the application name, which can be either Firefox Focus or Firefox Klar. */ "Autocomplete.defaultDescriptoin" = "Attivà per chì %@ compii autumaticamente più di 450 indirizzi populari in a barra d’indirizzu."; @@ -107,7 +107,7 @@ "BiometricAuthentication.UnlockButton.Title" = "Sbluccà"; /* Create a new session after failing a biometric check */ -"BiometricPrompt.newSession" = "Nova sessione"; +"BiometricPrompt.newSession" = "Sessione nova"; /* Accessibility label for the back button */ "Browser.backLabel" = "Ritornu"; @@ -125,7 +125,7 @@ "Browser.reloadLabel" = "Ricaricà"; /* Accessibility label for the settings button */ -"Browser.settingsLabel" = "Preferenze"; +"Browser.settingsLabel" = "Parametri"; /* Accessibility label for the stop button */ "Browser.stopLabel" = "Piantà"; @@ -215,7 +215,7 @@ "Onboarding.Incognito.Title" = "Più chè solu incognitu"; /* Text for a label that indicates the description of protection section from onboarding screen. */ -"Onboarding.Protection.Description" = "Cunfigureghja e preferenze per sceglie s’è vò scumpartite assai o pocu."; +"Onboarding.Protection.Description" = "Cunfigureghja i parametri per sceglie s’è vò scumpartite assai o pocu."; /* Text for a label that indicates the title of protection section from onboarding screen. */ "Onboarding.Protection.Title" = "Prutezzione discreziunale"; @@ -239,10 +239,10 @@ "Safari.instructionsNotEnabled" = "%@ ùn hè micca attivatu."; /* Label for instructions to enable Safari, shown when enabling Safari Integration in Settings */ -"Safari.instructionsOpen" = "Aprite e preferenze"; +"Safari.instructionsOpen" = "Aprite i parametri"; /* Label for instructions to enable extensions in Safari, shown when enabling Safari Integration in Settings */ -"Safari.openInstruction" = "Aprite e preferenze di l’apparechju"; +"Safari.openInstruction" = "Aprite i parametri di l’apparechju"; /* Save button label */ "Save" = "Arregistrà"; @@ -305,7 +305,7 @@ "Settings.safariTitle" = "INTEGRAZIONE SAFARI"; /* Title for settings screen */ -"Settings.screenTitle" = "Preferenze"; +"Settings.screenTitle" = "Parametri"; /* Text for button to add another search engine in settings */ "Settings.Search.AddSearchEngineButton" = "Aghjunghje un altru mutore di ricerca"; @@ -320,7 +320,7 @@ "Settings.Search.NameToDisplay" = "Nome à affissà"; /* Toast displayed after adding a search engine */ -"Settings.Search.NewSearchEngineAdded" = "Novu mutore di ricerca aghjuntu."; +"Settings.Search.NewSearchEngineAdded" = "U mutore di ricerca novu hè aghjuntu."; /* Label for button to bring deleted default engines back */ "Settings.Search.RestoreEngine" = "Risturà i mutori di ricerca predefiniti"; @@ -563,10 +563,10 @@ "TodayWidget.SearchInApp.Instruction" = "Circà in %@"; /* This is the body text that is displayed for the Context Menu icon tooltip */ -"TooltipBodyText.ContextMenu" = "Andà à e preferenze per urganizà l’ozzioni specifiche di cunfidenzialità è di sicurità."; +"TooltipBodyText.ContextMenu" = "Andà à i parametri per urganizà l’ozzioni specifiche di cunfidenzialità è di sicurità."; /* This is the body text that is displayed for the Privacy tooltip */ -"TooltipBodyText.Privacy" = "Ste preferenze predefinite furniscenu una prutezzione forte. Ma hè faciule di mudificalle per suddisfà i vostri bisogni specifichi."; +"TooltipBodyText.Privacy" = "Sti parametri predefiniti furniscenu una prutezzione forte. Ma hè faciule di mudificalli per suddisfà i vostri bisogni specifichi."; /* This is the body text that is displayed for the Search Bar tooltip */ "TooltipBodyText.SearchBar" = "Principiate a vostra sessione di navigazione privata è noi bluccheremu l’elementi di spiunagiu è l’altre minacce durante a navigazione."; @@ -581,7 +581,7 @@ "TooltipBodyText.TrashIcon" = "Picchichjate a curbella à ogni mumenti per caccià tutta traccia di a vostra sessione currente."; /* This is the body text that is displayed for the Trash icon tooltip */ -"TooltipBodyText.TrashIcon.V2" = "Picchicciate quì per squassà tuttu - cronolugia, canistrelli, ecc. - è principiate à zeru in un’unghjetta nova."; +"TooltipBodyText.TrashIcon.V2" = "Picchichjate quì per squassà tuttu - cronolugia, canistrelli, ecc. - è principiate à zeru in un’unghjetta nova."; /* This is the title text that is displayed for the Privacy tooltip */ "TooltipTitleText.Privacy" = "Site prutetti !"; From be3fe148af5164b5120f3dfc424295b3128e1ae0 Mon Sep 17 00:00:00 2001 From: Clare So <1740517+clarmso@users.noreply.github.com> Date: Mon, 29 Jul 2024 10:57:27 -0400 Subject: [PATCH 005/128] Bugfix FXIOS-9633 Sign in Mozilla Accounts button (#21309) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update button label * 🈳 Empty commit --- firefox-ios/Client/Application/AccessibilityIdentifiers.swift | 1 + .../firefox-ios-tests/Tests/XCUITests/FxScreenGraph.swift | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/firefox-ios/Client/Application/AccessibilityIdentifiers.swift b/firefox-ios/Client/Application/AccessibilityIdentifiers.swift index 9d2e20cd81e9..0ee388e13aad 100644 --- a/firefox-ios/Client/Application/AccessibilityIdentifiers.swift +++ b/firefox-ios/Client/Application/AccessibilityIdentifiers.swift @@ -510,6 +510,7 @@ public struct AccessibilityIdentifiers { static let fxaSignInButton = "EmailSignIn.button" static let qrButton = "QRCodeSignIn.button" static let qrScanFailedAlertOkButton = "qrCodeAlert.okButton" + static let signInButton = "Sign in" } struct Search { diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/FxScreenGraph.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/FxScreenGraph.swift index 2e9342558abc..832ae8d21095 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/FxScreenGraph.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/FxScreenGraph.swift @@ -688,7 +688,7 @@ func createScreenGraph(for test: XCTestCase, with app: XCUIApplication) -> MMScr app.webViews.buttons[AccessibilityIdentifiers.Settings.FirefoxAccount.continueButton].tap() } screenState.gesture(forAction: Action.FxATapOnSignInButton) { userState in - app.webViews.buttons.element(boundBy: 0).tap() + app.webViews.buttons[AccessibilityIdentifiers.Settings.FirefoxAccount.signInButton].tap() } screenState.tap(app.webViews.links["Create an account"].firstMatch, to: FxCreateAccount) } From 44992f131feede33fd08e53f8e2678f32597b026 Mon Sep 17 00:00:00 2001 From: Cyndi Chin Date: Mon, 29 Jul 2024 13:11:27 -0400 Subject: [PATCH 006/128] Bugfix FXIOS-8080 Favicon flicker on home (#21222) --- .../Data/JumpBackInDataAdaptor.swift | 23 +++---------------- .../Home/JumpBackIn/JumpBackInViewModel.swift | 19 ++++++++++----- .../JumpBackInDataAdaptorTests.swift | 8 ++----- .../JumpBackIn/JumpBackInViewModelTests.swift | 9 -------- 4 files changed, 18 insertions(+), 41 deletions(-) diff --git a/firefox-ios/Client/Frontend/Home/JumpBackIn/Data/JumpBackInDataAdaptor.swift b/firefox-ios/Client/Frontend/Home/JumpBackIn/Data/JumpBackInDataAdaptor.swift index cf9c7f281794..f03e824e2160 100644 --- a/firefox-ios/Client/Frontend/Home/JumpBackIn/Data/JumpBackInDataAdaptor.swift +++ b/firefox-ios/Client/Frontend/Home/JumpBackIn/Data/JumpBackInDataAdaptor.swift @@ -9,7 +9,6 @@ import Common protocol JumpBackInDataAdaptor: Actor { func hasSyncedTabFeatureEnabled() -> Bool func getRecentTabData() -> [Tab] - func getGroupsData() -> [ASGroup]? func getSyncedTabData() -> JumpBackInSyncedTab? } @@ -76,10 +75,6 @@ actor JumpBackInDataAdaptorImplementation: JumpBackInDataAdaptor, FeatureFlaggab return recentTabs } - func getGroupsData() -> [ASGroup]? { - return recentGroups - } - func getSyncedTabData() -> JumpBackInSyncedTab? { return mostRecentSyncedTab } @@ -98,30 +93,22 @@ actor JumpBackInDataAdaptorImplementation: JumpBackInDataAdaptor, FeatureFlaggab private func updateTabsData() async { await withTaskGroup(of: Void.self) { group in group.addTask { - await self.setRecentTabs(recentTabs: await self.updateRecentTabs()) - await self.delegate?.didLoadNewData() + let recentTabs = await self.updateRecentTabs() + await self.setRecentTabs(recentTabs: recentTabs) } group.addTask { if let remoteTabs = await self.updateRemoteTabs() { await self.createMostRecentSyncedTab(from: remoteTabs) - await self.delegate?.didLoadNewData() } } - group.addTask { - await self.setRecentGroups(recentGroups: await self.updateGroupsData()) - await self.delegate?.didLoadNewData() - } } + delegate?.didLoadNewData() } private func setRecentTabs(recentTabs: [Tab]) { self.recentTabs = recentTabs } - private func setRecentGroups(recentGroups: [ASGroup]?) { - self.recentGroups = recentGroups - } - private func updateRecentTabs() async -> [Tab] { // Recent tabs need to be accessed from .main otherwise value isn't proper return await withCheckedContinuation { continuation in @@ -131,10 +118,6 @@ actor JumpBackInDataAdaptorImplementation: JumpBackInDataAdaptor, FeatureFlaggab } } - private func updateGroupsData() async -> [ASGroup]? { - return nil - } - // MARK: Synced tab data private func getHasSyncAccount() async -> Bool { diff --git a/firefox-ios/Client/Frontend/Home/JumpBackIn/JumpBackInViewModel.swift b/firefox-ios/Client/Frontend/Home/JumpBackIn/JumpBackInViewModel.swift index aeb8a4074ede..20caa39ffec1 100644 --- a/firefox-ios/Client/Frontend/Home/JumpBackIn/JumpBackInViewModel.swift +++ b/firefox-ios/Client/Frontend/Home/JumpBackIn/JumpBackInViewModel.swift @@ -449,15 +449,22 @@ extension JumpBackInViewModel: HomepageSectionHandler { extension JumpBackInViewModel: JumpBackInDelegate { func didLoadNewData() { Task { @MainActor in - self.recentTabs = await self.jumpBackInDataAdaptor.getRecentTabData() - self.recentSyncedTab = await self.jumpBackInDataAdaptor.getSyncedTabData() - self.isSyncTabFeatureEnabled = await self.jumpBackInDataAdaptor.hasSyncedTabFeatureEnabled() + await self.updateJumpBackInData() logger.log("JumpBack didLoadNewData and section shouldShow \(self.shouldShow)", level: .debug, category: .homepage) - guard self.isEnabled else { return } - - self.delegate?.reloadView() + reloadView() } } + + private func updateJumpBackInData() async { + self.recentTabs = await self.jumpBackInDataAdaptor.getRecentTabData() + self.recentSyncedTab = await self.jumpBackInDataAdaptor.getSyncedTabData() + self.isSyncTabFeatureEnabled = await self.jumpBackInDataAdaptor.hasSyncedTabFeatureEnabled() + } + + private func reloadView() { + guard self.isEnabled else { return } + self.delegate?.reloadView() + } } diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Home/JumpBackIn/JumpBackInDataAdaptorTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Home/JumpBackIn/JumpBackInDataAdaptorTests.swift index e97ba4607df6..dcd9d5a4f855 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Home/JumpBackIn/JumpBackInDataAdaptorTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Home/JumpBackIn/JumpBackInDataAdaptorTests.swift @@ -8,11 +8,7 @@ import XCTest import WebKit import Common -// NOTE: -// Tab groups not tested at the moment since it depends on RustPlaces concrete object. -// Need protocol to be able to fix this - -class JumpBackInDataAdaptorTests: XCTestCase { +final class JumpBackInDataAdaptorTests: XCTestCase { var mockTabManager: MockTabManager! var mockProfile: MockProfile! let sleepTime: UInt64 = 100_000_000 @@ -33,7 +29,7 @@ class JumpBackInDataAdaptorTests: XCTestCase { mockTabManager = nil } - func testEmptyData_tabTrayGroupsDisabled() async { + func testEmptyData() async { let subject = createSubject() try? await Task.sleep(nanoseconds: sleepTime) diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Home/JumpBackIn/JumpBackInViewModelTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Home/JumpBackIn/JumpBackInViewModelTests.swift index 64d07c2920fe..baf8be59d403 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Home/JumpBackIn/JumpBackInViewModelTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Home/JumpBackIn/JumpBackInViewModelTests.swift @@ -628,15 +628,6 @@ actor JumpBackInDataAdaptorMock: JumpBackInDataAdaptor { return recentTabs } - var recentGroups: [ASGroup]? - func setRecentGroups(recentGroups: [ASGroup]?) { - self.recentGroups = recentGroups - } - - func getGroupsData() -> [ASGroup]? { - return recentGroups - } - var mockHasSyncedTabFeatureEnabled = true func setMockHasSyncedTabFeatureEnabled(enabled: Bool) { mockHasSyncedTabFeatureEnabled = enabled From 17ae64228b96621033ad60d7341950123d82faf4 Mon Sep 17 00:00:00 2001 From: Isabella Date: Mon, 29 Jul 2024 12:44:49 -0600 Subject: [PATCH 007/128] Clear system find in bar each time it is opened (unless the user is finding from a page selection). (#21325) --- .../Extensions/BrowserViewController+FindInPage.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+FindInPage.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+FindInPage.swift index 36f1b829f433..d47e14bd0a89 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+FindInPage.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+FindInPage.swift @@ -22,7 +22,7 @@ extension BrowserViewController { if isVisible { webView.isFindInteractionEnabled = true - webView.findInteraction?.searchText = searchText + webView.findInteraction?.searchText = searchText ?? "" webView.findInteraction?.presentFindNavigator(showingReplace: false) } else { webView.findInteraction?.dismissFindNavigator() From 1496411d79869def8f999a12c8b1ba73dfde7704 Mon Sep 17 00:00:00 2001 From: Matt Lichtenstein Date: Mon, 29 Jul 2024 17:28:33 -0400 Subject: [PATCH 008/128] v130 string for toolbar refactor (#21331) --- firefox-ios/Client/Frontend/Strings.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/firefox-ios/Client/Frontend/Strings.swift b/firefox-ios/Client/Frontend/Strings.swift index 304b79d0176e..d4231419d3d7 100644 --- a/firefox-ios/Client/Frontend/Strings.swift +++ b/firefox-ios/Client/Frontend/Strings.swift @@ -5766,6 +5766,14 @@ extension String { tableName: "Toolbar", value: "New Tab", comment: "Accessibility label for the new tab button that can be displayed in the navigation or address toolbar.") + public struct TabToolbarLongPressActionsMenu { + public static let CloseThisTabButton = MZLocalizedString( + key: "Toolbar.Tab.CloseThisTab.Button.v130", + tableName: "Toolbar", + value: "Close This Tab", + comment: "Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed" + ) + } } public struct AddressToolbar { From 94e05f2574c5257a8b8dff50cc6e71624520ba1a Mon Sep 17 00:00:00 2001 From: Ione Souza Junior Date: Mon, 29 Jul 2024 20:28:46 -0300 Subject: [PATCH 009/128] Refactor FXIOS-7301 - Help to remove 1 closure_body_length violation from Experiments.swift (2/3) (#21332) --- .../Client/Experiments/Experiments.swift | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/firefox-ios/Client/Experiments/Experiments.swift b/firefox-ios/Client/Experiments/Experiments.swift index 6f6dbaeaecbb..c0b7566142ec 100644 --- a/firefox-ios/Client/Experiments/Experiments.swift +++ b/firefox-ios/Client/Experiments/Experiments.swift @@ -141,24 +141,6 @@ enum Experiments { defaults.set(false, forKey: NIMBUS_IS_FIRST_RUN_KEY) } - let isPhone = UIDevice.current.userInterfaceIdiom == .phone - - let customTargetingAttributes: [String: Any] = [ - "isFirstRun": "\(isFirstRun)", - "is_first_run": isFirstRun, - "is_phone": isPhone, - "is_review_checker_enabled": isReviewCheckerEnabled() - ] - - // App settings, to allow experiments to target the app name and the - // channel. The values given here should match what `Experimenter` - // thinks it is. - let appSettings = NimbusAppSettings( - appName: nimbusAppName, - channel: AppConstants.buildChannel.nimbusString, - customTargetingAttributes: customTargetingAttributes - ) - let errorReporter: NimbusErrorReporter = { err in DefaultLogger.shared.log("Error in Nimbus SDK", level: .warning, @@ -190,9 +172,29 @@ enum Experiments { .with(bundles: bundles) .with(featureManifest: FxNimbus.shared) .with(commandLineArgs: CommandLine.arguments) - .build(appInfo: appSettings) + .build(appInfo: getAppSettings(isFirstRun: isFirstRun)) }() + private static func getAppSettings(isFirstRun: Bool) -> NimbusAppSettings { + let isPhone = UIDevice.current.userInterfaceIdiom == .phone + + let customTargetingAttributes: [String: Any] = [ + "isFirstRun": "\(isFirstRun)", + "is_first_run": isFirstRun, + "is_phone": isPhone, + "is_review_checker_enabled": isReviewCheckerEnabled() + ] + + // App settings, to allow experiments to target the app name and the + // channel. The values given here should match what `Experimenter` + // thinks it is. + return NimbusAppSettings( + appName: nimbusAppName, + channel: AppConstants.buildChannel.nimbusString, + customTargetingAttributes: customTargetingAttributes + ) + } + private static func isReviewCheckerEnabled() -> Bool { var isReviewCheckerEnabled = false if let prefs = UserDefaults(suiteName: AppInfo.sharedContainerIdentifier) { From 03c8f00dcb0711f72c91f8fce98fbea26d115dc9 Mon Sep 17 00:00:00 2001 From: dragosb01 <134391433+dragosb01@users.noreply.github.com> Date: Tue, 30 Jul 2024 10:35:55 +0300 Subject: [PATCH 010/128] Fixes MTE-3229 - for private and home page tests (#21342) --- .../Tests/XCUITests/BaseTestCase.swift | 2 +- .../Tests/XCUITests/FxScreenGraph.swift | 2 +- .../XCUITests/HomePageSettingsUITest.swift | 2 +- .../Tests/XCUITests/PrivateBrowsingTest.swift | 25 ++++--------------- 4 files changed, 8 insertions(+), 23 deletions(-) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/BaseTestCase.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/BaseTestCase.swift index b3cf6a3a2c0f..34cc121b115f 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/BaseTestCase.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/BaseTestCase.swift @@ -259,7 +259,7 @@ class BaseTestCase: XCTestCase { .otherElements .otherElements .count - let numberOfExpectedRecentlyVisitedBookmarks = 3 + let numberOfExpectedRecentlyVisitedBookmarks = 2 XCTAssertEqual(numberOfRecentlyVisitedBookmarks, numberOfExpectedRecentlyVisitedBookmarks) } diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/FxScreenGraph.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/FxScreenGraph.swift index 832ae8d21095..3c85e66c6256 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/FxScreenGraph.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/FxScreenGraph.swift @@ -770,7 +770,7 @@ func createScreenGraph(for test: XCTestCase, with app: XCUIApplication) -> MMScr } screenState.gesture(forAction: Action.ToggleRecentlySaved) { userState in - app.tables.cells.switches["Recently Saved"].tap() + app.tables.cells.switches["Bookmarks"].tap() } screenState.backAction = navigationControllerBackAction diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/HomePageSettingsUITest.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/HomePageSettingsUITest.swift index fb472a05caad..6773901636df 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/HomePageSettingsUITest.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/HomePageSettingsUITest.swift @@ -266,7 +266,7 @@ class HomePageSettingsUITests: BaseTestCase { bookmarkPages() addContentToReaderView() navigator.performAction(Action.GoToHomePage) - mozWaitForElementToExist(app.staticTexts["Recently Saved"]) + mozWaitForElementToExist(app.staticTexts["Bookmarks"]) navigator.performAction(Action.ToggleRecentlySaved) // On iPad we have the homepage button always present, // on iPhone we have the search button instead when we're on a new tab page diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/PrivateBrowsingTest.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/PrivateBrowsingTest.swift index 1cadd2d79369..f7cc99166a7c 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/PrivateBrowsingTest.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/PrivateBrowsingTest.swift @@ -108,14 +108,10 @@ class PrivateBrowsingTest: BaseTestCase { app.cells.staticTexts["Homepage"].tap() navigator.nowAt(NewTabScreen) - // Go back to private browsing and check that the tab has not been closed + // Go back to private browsing and check that the tab has been closed navigator.toggleOn(userState.isPrivate, withAction: Action.TogglePrivateMode) mozWaitForElementToExist(app.otherElements["Tabs Tray"]) - XCTAssertNotNil( - app.otherElements["Tabs Tray"].collectionViews.cells.staticTexts - .element(boundBy: 0).label - .range(of: url2Label) - ) + mozWaitForElementToExist(app.staticTexts["Private Browsing"]) checkOpenTabsBeforeClosingPrivateMode() } @@ -269,18 +265,8 @@ fileprivate extension BaseTestCase { let numPrivTabs = app.otherElements["Tabs Tray"].cells.count XCTAssertEqual( numPrivTabs, - 1, - "The number of tabs is not correct, the private tab should not have been closed" - ) - } - - func checkOpenTabsAfterClosingPrivateMode() { - // The private tab is not loger closed after "Close Private Tabs" has been removed - let numPrivTabsAfterClosing = app.otherElements["Tabs Tray"].cells.count - XCTAssertEqual( - numPrivTabsAfterClosing, - 1, - "The number of tabs is not correct" + 0, + "The private tab should have been closed" ) } @@ -337,12 +323,11 @@ class PrivateBrowsingTestIpad: IpadOnlyTestCase { navigator.openURL(url2) mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton], timeout: TIMEOUT) - // FXIOS-8672: "Close Private Tabs" has been removed from the settings. // Leave PM by tapping on PM shourt cut navigator.toggleOff(userState.isPrivate, withAction: Action.TogglePrivateModeFromTabBarHomePanel) waitForTabsButton() navigator.toggleOn(userState.isPrivate, withAction: Action.TogglePrivateMode) - checkOpenTabsAfterClosingPrivateMode() + checkOpenTabsBeforeClosingPrivateMode() } // https://testrail.stage.mozaws.net/index.php?/cases/view/2307009 From c24f6fa8dc79caf423b6d92d73772dec1ee3878b Mon Sep 17 00:00:00 2001 From: Ione Souza Junior Date: Tue, 30 Jul 2024 09:19:27 -0300 Subject: [PATCH 011/128] Refactor FXIOS-7301 - Remove 1 closure_body_length violation from SearchSuggestClient.swift (#21336) * Extract the error handling to a new function * Use the new function to handle error * Use the new function to handle error * Use the new function to handle error * Change access modifier --- .../Browser/SearchSuggestClient.swift | 30 ++++++++----------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/firefox-ios/Client/Frontend/Browser/SearchSuggestClient.swift b/firefox-ios/Client/Frontend/Browser/SearchSuggestClient.swift index 6b12ff35e4f5..5e70965fad28 100644 --- a/firefox-ios/Client/Frontend/Browser/SearchSuggestClient.swift +++ b/firefox-ios/Client/Frontend/Browser/SearchSuggestClient.swift @@ -54,12 +54,7 @@ class SearchSuggestClient { guard let data = data, validatedHTTPResponse(response, statusCode: 200..<300) != nil else { - let error = NSError( - domain: SearchSuggestClientErrorDomain, - code: SearchSuggestClientErrorInvalidResponse, - userInfo: nil - ) - callback(nil, error as NSError?) + self.handleInvalidResponseError(callback: callback) return } @@ -71,22 +66,12 @@ class SearchSuggestClient { // That is, an array of at least two elements: the search term and an array of suggestions. if array?.count ?? 0 < 2 { - let error = NSError( - domain: SearchSuggestClientErrorDomain, - code: SearchSuggestClientErrorInvalidResponse, - userInfo: nil - ) - callback(nil, error) + self.handleInvalidResponseError(callback: callback) return } guard let suggestions = array?[1] as? [String] else { - let error = NSError( - domain: SearchSuggestClientErrorDomain, - code: SearchSuggestClientErrorInvalidResponse, - userInfo: nil - ) - callback(nil, error) + self.handleInvalidResponseError(callback: callback) return } @@ -95,6 +80,15 @@ class SearchSuggestClient { task?.resume() } + private func handleInvalidResponseError(callback: @escaping (_ response: [String]?, _ error: NSError?) -> Void) { + let error = NSError( + domain: SearchSuggestClientErrorDomain, + code: SearchSuggestClientErrorInvalidResponse, + userInfo: nil + ) + callback(nil, error) + } + func cancelPendingRequest() { task?.cancel() } From cf0a7768a38131e7453f256e8cbbb2b015a1b5b9 Mon Sep 17 00:00:00 2001 From: "roux g. buciu" <11182210+adudenamedruby@users.noreply.github.com> Date: Tue, 30 Jul 2024 09:20:56 -0400 Subject: [PATCH 012/128] Add FXIOS-9689 [Onboarding] Customization cards (#21326) * Add onboarding cards * Fix the test --- .../Tests/XCUITests/OnboardingTests.swift | 22 +++++++++- .../onboardingFrameworkFeature.yaml | 43 +++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/OnboardingTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/OnboardingTests.swift index df984afee155..27eaf027658b 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/OnboardingTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/OnboardingTests.swift @@ -52,8 +52,28 @@ class OnboardingTests: BaseTestCase { XCTAssertTrue(app.buttons["\(rootA11yId)PrimaryButton"].exists) XCTAssertTrue(app.buttons["\(rootA11yId)SecondaryButton"].exists) - // Finish onboarding + // Swipe to the fourth screen app.buttons["\(rootA11yId)SecondaryButton"].tap() + currentScreen += 1 + mozWaitForElementToExist(app.images["\(rootA11yId)ImageView"], timeout: 15) + XCTAssertTrue(app.images["\(rootA11yId)ImageView"].exists) + XCTAssertTrue(app.staticTexts["\(rootA11yId)TitleLabel"].exists) + XCTAssertTrue(app.staticTexts["\(rootA11yId)DescriptionLabel"].exists) + XCTAssertTrue(app.buttons["\(rootA11yId)PrimaryButton"].exists) + XCTAssertTrue(app.buttons["\(rootA11yId)SecondaryButton"].exists) + + // Swipe to the fifth screen + app.buttons["\(rootA11yId)PrimaryButton"].tap() + currentScreen += 1 + mozWaitForElementToExist(app.images["\(rootA11yId)ImageView"], timeout: 15) + XCTAssertTrue(app.images["\(rootA11yId)ImageView"].exists) + XCTAssertTrue(app.staticTexts["\(rootA11yId)TitleLabel"].exists) + XCTAssertTrue(app.staticTexts["\(rootA11yId)DescriptionLabel"].exists) + XCTAssertTrue(app.buttons["\(rootA11yId)PrimaryButton"].exists) + XCTAssertTrue(app.buttons["\(rootA11yId)SecondaryButton"].exists) + + // Finish onboarding + app.buttons["\(rootA11yId)PrimaryButton"].tap() let topSites = app.collectionViews.cells[AccessibilityIdentifiers.FirefoxHomepage.TopSites.itemCell] mozWaitForElementToExist(topSites) } diff --git a/firefox-ios/nimbus-features/onboardingFrameworkFeature.yaml b/firefox-ios/nimbus-features/onboardingFrameworkFeature.yaml index 699564ae56f5..18db3588c405 100644 --- a/firefox-ios/nimbus-features/onboardingFrameworkFeature.yaml +++ b/firefox-ios/nimbus-features/onboardingFrameworkFeature.yaml @@ -146,6 +146,49 @@ features: onboarding-type: fresh-install prerequisites: - ALWAYS + customization-theme: + card-type: multiple-choice + order: 40 + title: Onboarding/Onboarding.Customization.Theme.Title.v123 + body: Onboarding/Onboarding.Customization.Theme.Description.v123 + image: themeing + buttons: + primary: + title: Onboarding/Onboarding.Customization.Theme.Continue.Action.v123 + action: forward-one-card + multiple-choice-buttons: + - title: Onboarding/Onboarding.Customization.Theme.System.Action.v123 + image: theme-system + action: theme-system-default + - title: Onboarding/Onboarding.Customization.Theme.Light.Action.v123 + image: theme-light + action: theme-light + - title: Onboarding/Onboarding.Customization.Theme.Dark.Action.v123 + image: theme-dark + action: theme-dark + onboarding-type: fresh-install + prerequisites: + - ALWAYS + customization-toolbar: + card-type: multiple-choice + order: 41 + title: Onboarding/Onboarding.Customization.Toolbar.Title.v123 + body: Onboarding/Onboarding.Customization.Toolbar.Description.v123 + image: toolbar + buttons: + primary: + title: Onboarding/Onboarding.Customization.Toolbar.Continue.Action.v123 + action: forward-one-card + multiple-choice-buttons: + - title: Onboarding/Onboarding.Customization.Toolbar.Top.Action.v123 + image: toolbar-top + action: toolbar-top + - title: Onboarding/Onboarding.Customization.Toolbar.Bottom.Action.v123 + image: toolbar-bottom + action: toolbar-bottom + onboarding-type: fresh-install + prerequisites: + - ALWAYS update-welcome: card-type: basic order: 10 From 4099df1d453d6ea56f9bb61fdbed7dcbeb42c0ac Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 30 Jul 2024 16:37:01 +0000 Subject: [PATCH 013/128] Refactor [v130] Auto update SPM with latest rust-component 130.0.20240730050414 (#21355) * Auto update SPM with latest rust-component release 130.0.20240730050414 * Update Glean to v60.4.0 --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Ryan VanderMeulen --- firefox-ios/Client.xcodeproj/project.pbxproj | 4 ++-- .../xcshareddata/swiftpm/Package.resolved | 8 ++++---- focus-ios/Blockzilla.xcodeproj/project.pbxproj | 4 ++-- .../xcshareddata/swiftpm/Package.resolved | 8 ++++---- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/firefox-ios/Client.xcodeproj/project.pbxproj b/firefox-ios/Client.xcodeproj/project.pbxproj index d0f7500f2c00..94c7b3167271 100644 --- a/firefox-ios/Client.xcodeproj/project.pbxproj +++ b/firefox-ios/Client.xcodeproj/project.pbxproj @@ -23047,7 +23047,7 @@ repositoryURL = "https://github.com/mozilla/rust-components-swift.git"; requirement = { kind = exactVersion; - version = 130.0.20240726050301; + version = 130.0.20240730050414; }; }; 435C85EE2788F4D00072B526 /* XCRemoteSwiftPackageReference "glean-swift" */ = { @@ -23055,7 +23055,7 @@ repositoryURL = "https://github.com/mozilla/glean-swift"; requirement = { kind = exactVersion; - version = 60.3.0; + version = 60.4.0; }; }; 4368F83B279669690013419B /* XCRemoteSwiftPackageReference "SnapKit" */ = { diff --git a/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index affeb50fdcdb..3708ec8aca51 100644 --- a/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -41,8 +41,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/mozilla/glean-swift", "state" : { - "revision" : "38c00984dcbc7aff85352b917a40f95395044eab", - "version" : "60.3.0" + "revision" : "4bea990fdaaeea98b7855ce682bfefa6a5acc04b", + "version" : "60.4.0" } }, { @@ -95,8 +95,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/mozilla/rust-components-swift.git", "state" : { - "revision" : "86000c4ce3dc797002c9b6ff91f4cba1ec0dbeba", - "version" : "130.0.20240726050301" + "revision" : "6981abbeee54a4bc1f5300e0023e5621fd53b8d1", + "version" : "130.0.20240730050414" } }, { diff --git a/focus-ios/Blockzilla.xcodeproj/project.pbxproj b/focus-ios/Blockzilla.xcodeproj/project.pbxproj index e57f1467014d..4c13e5c80984 100644 --- a/focus-ios/Blockzilla.xcodeproj/project.pbxproj +++ b/focus-ios/Blockzilla.xcodeproj/project.pbxproj @@ -7159,7 +7159,7 @@ repositoryURL = "https://github.com/mozilla/rust-components-swift"; requirement = { kind = exactVersion; - version = 130.0.20240726050301; + version = 130.0.20240730050414; }; }; 8A0E7F2C2BA0F0E0006BC6B6 /* XCRemoteSwiftPackageReference "Fuzi" */ = { @@ -7175,7 +7175,7 @@ repositoryURL = "https://github.com/mozilla/glean-swift"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 60.3.0; + minimumVersion = 60.4.0; }; }; F8324C2D264C807C007E4BFA /* XCRemoteSwiftPackageReference "SnapKit" */ = { diff --git a/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index a252ee90b121..a2d6aaac14d4 100644 --- a/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -33,8 +33,8 @@ "repositoryURL": "https://github.com/mozilla/glean-swift", "state": { "branch": null, - "revision": "38c00984dcbc7aff85352b917a40f95395044eab", - "version": "60.3.0" + "revision": "4bea990fdaaeea98b7855ce682bfefa6a5acc04b", + "version": "60.4.0" } }, { @@ -51,8 +51,8 @@ "repositoryURL": "https://github.com/mozilla/rust-components-swift", "state": { "branch": null, - "revision": "86000c4ce3dc797002c9b6ff91f4cba1ec0dbeba", - "version": "130.0.20240726050301" + "revision": "6981abbeee54a4bc1f5300e0023e5621fd53b8d1", + "version": "130.0.20240730050414" } }, { From 4a430670576d1520a755ab2abd2c372b1fbb2ffe Mon Sep 17 00:00:00 2001 From: Matt Lichtenstein Date: Tue, 30 Jul 2024 13:07:38 -0400 Subject: [PATCH 014/128] Add FXIOS-9523 Long press gestures for tab tray and new tab toolbar buttons (#21287) --- .../Actions/GeneralBrowserAction.swift | 1 + ...serViewController+TabToolbarDelegate.swift | 62 ++++++++++++++----- .../State/BrowserViewControllerState.swift | 11 ++++ .../Views/BrowserViewController.swift | 36 +++++++++-- .../Models/AddressToolbarContainerModel.swift | 2 +- .../NavigationToolbarContainerModel.swift | 2 +- .../Toolbars/Redux/ToolbarActionState.swift | 10 +-- .../Toolbars/Redux/ToolbarMiddleware.swift | 12 +++- .../Browser/TopTabsViewController.swift | 16 +++++ .../BrowserViewControllerStateTests.swift | 12 ++++ 10 files changed, 137 insertions(+), 27 deletions(-) diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Actions/GeneralBrowserAction.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Actions/GeneralBrowserAction.swift index 2b6d7b2d305d..9530fc61d543 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Actions/GeneralBrowserAction.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Actions/GeneralBrowserAction.swift @@ -49,6 +49,7 @@ enum GeneralBrowserActionType: ActionType { case reloadWebsite case showShare case addNewTab + case showNewTabLongPressActions } class GeneralBrowserMiddlewareAction: Action { diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+TabToolbarDelegate.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+TabToolbarDelegate.swift index fe650cca0e39..f787f544f10e 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+TabToolbarDelegate.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+TabToolbarDelegate.swift @@ -198,48 +198,80 @@ extension BrowserViewController: TabToolbarDelegate, PhotonActionSheetProtocol { if let tab = self.tabManager.selectedTab { return tab.isPrivate ? [normalBrowsingMode] : [privateBrowsingMode] } + return [privateBrowsingMode] } func getMoreTabToolbarLongPressActions() -> [PhotonRowActions] { - let newTab = SingleActionViewModel(title: .KeyboardShortcuts.NewTab, - iconString: StandardImageIdentifiers.Large.plus, - iconType: .Image) { _ in + let newTab = getNewTabAction() + let newPrivateTab = getNewPrivateTabAction() + let closeTab = getCloseTabAction() + + if let tab = self.tabManager.selectedTab { + return tab.isPrivate ? [newPrivateTab, closeTab] : [newTab, closeTab] + } + + return [newTab, closeTab] + } + + func getTabToolbarRefactorLongPressActions() -> [[PhotonRowActions]] { + let newTab = getNewTabAction() + let newPrivateTab = getNewPrivateTabAction() + let closeTab = getCloseTabAction() + + return [[newTab, newPrivateTab], [closeTab]] + } + + func getNewTabLongPressActions() -> [[PhotonRowActions]] { + let newTab = getNewTabAction() + let newPrivateTab = getNewPrivateTabAction() + + return [[newTab, newPrivateTab]] + } + + private func getNewTabAction() -> PhotonRowActions { + return SingleActionViewModel(title: .KeyboardShortcuts.NewTab, + iconString: StandardImageIdentifiers.Large.plus, + iconType: .Image) { _ in let shouldFocusLocationField = self.newTabSettings == .blankPage self.overlayManager.openNewTab(url: nil, newTabSettings: self.newTabSettings) self.openBlankNewTab(focusLocationField: shouldFocusLocationField, isPrivate: false) }.items + } - let newPrivateTab = SingleActionViewModel(title: .KeyboardShortcuts.NewPrivateTab, - iconString: StandardImageIdentifiers.Large.plus, - iconType: .Image) { _ in + private func getNewPrivateTabAction() -> PhotonRowActions { + let isRefactorEnabled = isToolbarRefactorEnabled && isOneTapNewTabEnabled + let iconString = isRefactorEnabled ? StandardImageIdentifiers.Large.privateMode : StandardImageIdentifiers.Large.plus + return SingleActionViewModel(title: .KeyboardShortcuts.NewPrivateTab, + iconString: iconString, + iconType: .Image) { _ in let shouldFocusLocationField = self.newTabSettings == .blankPage self.overlayManager.openNewTab(url: nil, newTabSettings: self.newTabSettings) self.openBlankNewTab(focusLocationField: shouldFocusLocationField, isPrivate: true) TelemetryWrapper.recordEvent(category: .action, method: .tap, object: .newPrivateTab, value: .tabTray) }.items + } - let closeTab = SingleActionViewModel(title: .KeyboardShortcuts.CloseCurrentTab, - iconString: StandardImageIdentifiers.Large.cross, - iconType: .Image) { _ in + private func getCloseTabAction() -> PhotonRowActions { + let isRefactorEnabled = isToolbarRefactorEnabled && isOneTapNewTabEnabled + let title = isRefactorEnabled ? String.Toolbars.TabToolbarLongPressActionsMenu.CloseThisTabButton : + String.KeyboardShortcuts.CloseCurrentTab + return SingleActionViewModel(title: title, + iconString: StandardImageIdentifiers.Large.cross, + iconType: .Image) { _ in if let tab = self.tabManager.selectedTab { self.tabManager.removeTab(tab) self.updateTabCountUsingTabManager(self.tabManager) self.showToast(message: .TabsTray.CloseTabsToast.SingleTabTitle, toastAction: .closeTab) } }.items - - if let tab = self.tabManager.selectedTab { - return tab.isPrivate ? [newPrivateTab, closeTab] : [newTab, closeTab] - } - return [newTab, closeTab] } func tabToolbarDidLongPressTabs(_ tabToolbar: TabToolbarProtocol, button: UIButton) { let generator = UIImpactFeedbackGenerator(style: .heavy) generator.impactOccurred() - presentActionSheet(from: button) + presentTabsLongPressAction(from: button) } func tabToolbarDidPressSearch(_ tabToolbar: TabToolbarProtocol, button: UIButton) { diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/State/BrowserViewControllerState.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/State/BrowserViewControllerState.swift index fd9127a98da0..cab6d5d7c81f 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/State/BrowserViewControllerState.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/State/BrowserViewControllerState.swift @@ -27,6 +27,7 @@ struct BrowserViewControllerState: ScreenState, Equatable { case reloadLongPressAction case tabTray case share + case newTabLongPressActions } let windowUUID: WindowUUID @@ -363,6 +364,16 @@ struct BrowserViewControllerState: ScreenState, Equatable { displayView: .share, buttonTapped: action.buttonTapped, microsurveyState: MicrosurveyPromptState.reducer(state.microsurveyState, action)) + case GeneralBrowserActionType.showNewTabLongPressActions: + return BrowserViewControllerState( + searchScreenState: state.searchScreenState, + showDataClearanceFlow: state.showDataClearanceFlow, + fakespotState: state.fakespotState, + toast: state.toast, + windowUUID: state.windowUUID, + browserViewType: state.browserViewType, + displayView: .newTabLongPressActions, + microsurveyState: MicrosurveyPromptState.reducer(state.microsurveyState, action)) default: return state } diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift index eeff6e0b685c..53627a79463f 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift @@ -122,6 +122,9 @@ class BrowserViewController: UIViewController, var isToolbarRefactorEnabled: Bool { return featureFlags.isFeatureEnabled(.toolbarRefactor, checking: .buildOnly) } + var isOneTapNewTabEnabled: Bool { + return featureFlags.isFeatureEnabled(.toolbarOneTapNewTab, checking: .buildOnly) + } private var browserViewControllerState: BrowserViewControllerState? // Header stack view can contain the top url bar, top reader mode, top ZoomPageBar @@ -1899,7 +1902,7 @@ class BrowserViewController: UIViewController, case .backForwardList: navigationHandler?.showBackForwardList() case .tabsLongPressActions: - presentActionSheet(from: view) + presentTabsLongPressAction(from: view) case .locationViewLongPressAction: presentLocationViewActionSheet(from: addressToolbarContainer) case .trackingProtectionDetails: @@ -1921,6 +1924,8 @@ class BrowserViewController: UIViewController, case .share: guard let button = state.buttonTapped else { return } didTapOnShare(from: button) + case .newTabLongPressActions: + presentNewTabLongPressActionSheet(from: view) } } @@ -1986,6 +1991,19 @@ class BrowserViewController: UIViewController, presentSheetWith(viewModel: viewModel, on: self, from: button) } + func presentNewTabLongPressActionSheet(from view: UIView) { + let actions = getNewTabLongPressActions() + + let shouldPresentAsPopover = ToolbarHelper().shouldShowTopTabs(for: traitCollection) + let style: UIModalPresentationStyle = shouldPresentAsPopover ? .popover : .overCurrentContext + let viewModel = PhotonActionSheetViewModel( + actions: actions, + closeButtonTitle: .CloseButtonTitle, + modalStyle: style + ) + presentSheetWith(viewModel: viewModel, on: self, from: view) + } + func didTapOnHome() { let shouldUpdateWithRedux = isToolbarRefactorEnabled && browserViewControllerState?.navigateTo == .home guard shouldUpdateWithRedux || !isToolbarRefactorEnabled else { return } @@ -2078,12 +2096,18 @@ class BrowserViewController: UIViewController, } } - func presentActionSheet(from view: UIView) { + func presentTabsLongPressAction(from view: UIView) { guard presentedViewController == nil else { return } var actions: [[PhotonRowActions]] = [] - actions.append(getTabToolbarLongPressActionsForModeSwitching()) - actions.append(getMoreTabToolbarLongPressActions()) + let useToolbarRefactorLongPressActions = featureFlags.isFeatureEnabled(.toolbarRefactor, checking: .buildOnly) && + featureFlags.isFeatureEnabled(.toolbarOneTapNewTab, checking: .buildOnly) + if useToolbarRefactorLongPressActions { + actions = getTabToolbarRefactorLongPressActions() + } else { + actions.append(getTabToolbarLongPressActionsForModeSwitching()) + actions.append(getMoreTabToolbarLongPressActions()) + } let viewModel = PhotonActionSheetViewModel( actions: actions, @@ -3742,6 +3766,10 @@ extension BrowserViewController: TopTabsDelegate { newTabSettings: newTabSettings) } + func topTabsDidLongPressNewTab(button: UIButton) { + presentNewTabLongPressActionSheet(from: button) + } + func topTabsDidChangeTab() { // Only for iPad leave overlay mode on tab change overlayManager.switchTab(shouldCancelLoading: true) diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift index 018cc1b05f07..68e9713a90a1 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift @@ -97,7 +97,7 @@ class AddressToolbarContainerModel: Equatable { windowUUID: windowUUID, actionType: ToolbarMiddlewareActionType.didTapButton) store.dispatch(action) - }, onLongPress: action.canPerformLongPressAction ? { button in + }, onLongPress: action.canPerformLongPressAction(isShowingTopTabs: true) ? { button in let action = ToolbarMiddlewareAction(buttonType: action.actionType, buttonTapped: button, gestureType: .longPress, diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/NavigationToolbarContainerModel.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/NavigationToolbarContainerModel.swift index 8e3454b0be1c..2121f12ec62a 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/NavigationToolbarContainerModel.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/NavigationToolbarContainerModel.swift @@ -32,7 +32,7 @@ struct NavigationToolbarContainerModel: Equatable { windowUUID: windowUUID, actionType: ToolbarMiddlewareActionType.didTapButton) store.dispatch(action) - }, onLongPress: action.canPerformLongPressAction ? { button in + }, onLongPress: action.canPerformLongPressAction(isShowingTopTabs: action.isShowingTopTabs) ? { button in let action = ToolbarMiddlewareAction(buttonType: action.actionType, buttonTapped: button, gestureType: .longPress, diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarActionState.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarActionState.swift index 4d081b5e0c2a..a167a9f8e7de 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarActionState.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarActionState.swift @@ -4,7 +4,7 @@ import Foundation -struct ToolbarActionState: Equatable { +struct ToolbarActionState: Equatable, FeatureFlaggable { enum ActionType { case back case forward @@ -28,15 +28,17 @@ struct ToolbarActionState: Equatable { var iconName: String var badgeImageName: String? var numberOfTabs: Int? + var isShowingTopTabs: Bool? var isEnabled: Bool var a11yLabel: String var a11yHint: String? var a11yId: String - var canPerformLongPressAction: Bool { + func canPerformLongPressAction(isShowingTopTabs: Bool?) -> Bool { return actionType == .back || actionType == .forward || - actionType == .tabs || - actionType == .reload + actionType == .reload || + actionType == .newTab || + (actionType == .tabs && isShowingTopTabs == false) } } diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift index faa3feb1dcd1..5604d16384df 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift @@ -270,6 +270,11 @@ class ToolbarMiddleware: FeatureFlaggable { windowUUID: action.windowUUID, actionType: GeneralBrowserActionType.showReloadLongPressAction) store.dispatch(action) + case .newTab: + let action = GeneralBrowserAction(windowUUID: action.windowUUID, + actionType: GeneralBrowserActionType.showNewTabLongPressActions + ) + store.dispatch(action) default: break } @@ -573,6 +578,8 @@ class ToolbarMiddleware: FeatureFlaggable { let middleActionHome = searchAction let middleAction = url == nil ? middleActionHome : middleActionDefault + let isShowingTopTabs = action.isShowingTopTabs ?? false + let canGoBack = action.canGoBack ?? toolbarState.canGoBack let canGoForward = action.canGoForward ?? toolbarState.canGoForward let numberOfTabs = action.numberOfTabs ?? toolbarState.numberOfTabs @@ -584,7 +591,7 @@ class ToolbarMiddleware: FeatureFlaggable { backAction(enabled: canGoBack), forwardAction(enabled: canGoForward), middleAction, - tabsAction(numberOfTabs: numberOfTabs), + tabsAction(numberOfTabs: numberOfTabs, isShowingTopTabs: isShowingTopTabs), menuAction(badgeImageName: menuBadgeImageName) ] @@ -616,11 +623,12 @@ class ToolbarMiddleware: FeatureFlaggable { a11yId: AccessibilityIdentifiers.Toolbar.forwardButton) } - private func tabsAction(numberOfTabs: Int = 1) -> ToolbarActionState { + private func tabsAction(numberOfTabs: Int = 1, isShowingTopTabs: Bool = false) -> ToolbarActionState { return ToolbarActionState( actionType: .tabs, iconName: StandardImageIdentifiers.Large.tab, numberOfTabs: numberOfTabs, + isShowingTopTabs: isShowingTopTabs, isEnabled: true, a11yLabel: .TabsButtonShowTabsAccessibilityLabel, a11yId: AccessibilityIdentifiers.Toolbar.tabsButton) diff --git a/firefox-ios/Client/Frontend/Browser/TopTabsViewController.swift b/firefox-ios/Client/Frontend/Browser/TopTabsViewController.swift index de33d57d18a6..1c515424d9ae 100644 --- a/firefox-ios/Client/Frontend/Browser/TopTabsViewController.swift +++ b/firefox-ios/Client/Frontend/Browser/TopTabsViewController.swift @@ -24,6 +24,7 @@ struct TopTabsUX { protocol TopTabsDelegate: AnyObject { func topTabsDidPressTabs() func topTabsDidPressNewTab(_ isPrivate: Bool) + func topTabsDidLongPressNewTab(button: UIButton) func topTabsDidChangeTab() func topTabsDidPressPrivateMode() } @@ -70,6 +71,14 @@ class TopTabsViewController: UIViewController, Themeable, Notifiable, FeatureFla button.setImage(UIImage.templateImageNamed(StandardImageIdentifiers.Large.plus), for: .normal) button.semanticContentAttribute = .forceLeftToRight button.addTarget(self, action: #selector(TopTabsViewController.newTabTapped), for: .touchUpInside) + if self.featureFlags.isFeatureEnabled(.toolbarOneTapNewTab, checking: .buildOnly) && + self.featureFlags.isFeatureEnabled(.toolbarRefactor, checking: .buildOnly) { + let longPressRecognizer = UILongPressGestureRecognizer( + target: self, + action: #selector(TopTabsViewController.newTabLongPressed) + ) + button.addGestureRecognizer(longPressRecognizer) + } button.accessibilityIdentifier = AccessibilityIdentifiers.Toolbar.addNewTabButton button.accessibilityLabel = .AddTabAccessibilityLabel button.showsLargeContentViewer = true @@ -215,6 +224,13 @@ class TopTabsViewController: UIViewController, Themeable, Notifiable, FeatureFla delegate?.topTabsDidPressNewTab(self.topTabDisplayManager.isPrivate) } + @objc + func newTabLongPressed(_ gestureRecognizer: UILongPressGestureRecognizer) { + if gestureRecognizer.state == .began { + delegate?.topTabsDidLongPressNewTab(button: newTab) + } + } + @objc func togglePrivateModeTapped() { delegate?.topTabsDidPressPrivateMode() diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/BrowserViewControllerStateTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/BrowserViewControllerStateTests.swift index b3d6d032bc85..7c769273288c 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/BrowserViewControllerStateTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/BrowserViewControllerStateTests.swift @@ -30,6 +30,18 @@ final class BrowserViewControllerStateTests: XCTestCase { XCTAssertEqual(newState.navigateTo, .newTab) } + func testShowNewTabLongpPressActions() { + let initialState = createSubject() + let reducer = browserViewControllerReducer() + + XCTAssertNil(initialState.displayView) + + let action = getAction(for: .showNewTabLongPressActions) + let newState = reducer(initialState, action) + + XCTAssertEqual(newState.displayView, .newTabLongPressActions) + } + // MARK: - Private private func createSubject() -> BrowserViewControllerState { return BrowserViewControllerState(windowUUID: .XCTestDefaultUUID) From ea96ad94c7d14b5decc899de31a93aa8184ebea3 Mon Sep 17 00:00:00 2001 From: Litianu Razvan Date: Tue, 30 Jul 2024 20:57:00 +0300 Subject: [PATCH 015/128] Refactor FXIOS-9661 Change nimbus feature flag for address autofill phase 2 [ca, us] (#21232) --------- Co-authored-by: Nishant Bhasin --- firefox-ios/Client.xcodeproj/project.pbxproj | 18 +++++++- .../FeatureFlags/NimbusFlaggableFeature.swift | 2 - .../AddressLocaleFeatureValidator.swift | 16 +++++++ .../AddressProvider.swift | 0 .../Views/BrowserViewController.swift | 6 +-- .../Main/AppSettingsTableViewController.swift | 2 +- .../SyncContentSettingsViewController.swift | 4 +- .../Nimbus/NimbusFeatureFlagLayer.swift | 13 +----- firefox-ios/RustFxA/FxAWebViewModel.swift | 2 +- .../AddressLocaleFeatureValidatorTests.swift | 43 +++++++++++++++++++ .../addressAutofillFeature.yaml | 10 +---- 11 files changed, 84 insertions(+), 32 deletions(-) create mode 100644 firefox-ios/Client/Frontend/Autofill/Address/AddressUtility/AddressLocaleFeatureValidator.swift rename firefox-ios/Client/Frontend/Autofill/Address/{ => AddressUtility}/AddressProvider.swift (100%) create mode 100644 firefox-ios/firefox-ios-tests/Tests/ClientTests/Autofill/AddressLocaleFeatureValidatorTests.swift diff --git a/firefox-ios/Client.xcodeproj/project.pbxproj b/firefox-ios/Client.xcodeproj/project.pbxproj index 94c7b3167271..7e98218741a9 100644 --- a/firefox-ios/Client.xcodeproj/project.pbxproj +++ b/firefox-ios/Client.xcodeproj/project.pbxproj @@ -802,6 +802,8 @@ 8A95FF642B1E969E00AC303D /* TelemetryContextualIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A95FF632B1E969E00AC303D /* TelemetryContextualIdentifier.swift */; }; 8A95FF672B1E97A800AC303D /* TelemetryContextualIdentifierTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A95FF652B1E977E00AC303D /* TelemetryContextualIdentifierTests.swift */; }; 8A96C4BB28F9E7B300B75884 /* XCTestCaseRootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A96C4BA28F9E7B300B75884 /* XCTestCaseRootViewController.swift */; }; + 8A97E6EA2C58487900F94793 /* AddressLocaleFeatureValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A97E6E92C58487900F94793 /* AddressLocaleFeatureValidator.swift */; }; + 8A97E6EF2C584C4900F94793 /* AddressLocaleFeatureValidatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A97E6ED2C584AC300F94793 /* AddressLocaleFeatureValidatorTests.swift */; }; 8A9AC465276CEC4E0047F5B0 /* JumpBackInCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A9AC464276CEC4E0047F5B0 /* JumpBackInCell.swift */; }; 8A9AC46B276D11280047F5B0 /* PocketViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A9AC46A276D11280047F5B0 /* PocketViewModel.swift */; }; 8A9B87AD2C1B39100042B894 /* SearchViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A9B87AC2C1B39100042B894 /* SearchViewModel.swift */; }; @@ -6530,6 +6532,8 @@ 8A95FF652B1E977E00AC303D /* TelemetryContextualIdentifierTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TelemetryContextualIdentifierTests.swift; sourceTree = ""; }; 8A96C4B828F9DD8700B75884 /* ThemableTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemableTests.swift; sourceTree = ""; }; 8A96C4BA28F9E7B300B75884 /* XCTestCaseRootViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCTestCaseRootViewController.swift; sourceTree = ""; }; + 8A97E6E92C58487900F94793 /* AddressLocaleFeatureValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressLocaleFeatureValidator.swift; sourceTree = ""; }; + 8A97E6ED2C584AC300F94793 /* AddressLocaleFeatureValidatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressLocaleFeatureValidatorTests.swift; sourceTree = ""; }; 8A99DB9727C6DD3E007EA6BD /* is */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = is; path = "is.lproj/Default Browser.strings"; sourceTree = ""; }; 8A99DB9827C6DD3E007EA6BD /* is */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = is; path = is.lproj/Today.strings; sourceTree = ""; }; 8A99DB9927C6DD3E007EA6BD /* is */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = is; path = is.lproj/BookmarkPanel.strings; sourceTree = ""; }; @@ -10403,6 +10407,15 @@ path = Extensions; sourceTree = ""; }; + 8A97E6EC2C58489C00F94793 /* AddressUtility */ = { + isa = PBXGroup; + children = ( + 8CEDF07F2BFE138B00D2617B /* AddressProvider.swift */, + 8A97E6E92C58487900F94793 /* AddressLocaleFeatureValidator.swift */, + ); + path = AddressUtility; + sourceTree = ""; + }; 8A9B87A92C1B30340042B894 /* Search */ = { isa = PBXGroup; children = ( @@ -10953,6 +10966,7 @@ 439B78172A09721600CAAE37 /* FormAutofillHelperTests.swift */, 8CCD74722B90A945008F919B /* LoginListViewModelTests.swift */, 8CEDF07D2BFE04B100D2617B /* AddressListViewModelTests.swift */, + 8A97E6ED2C584AC300F94793 /* AddressLocaleFeatureValidatorTests.swift */, ); path = Autofill; sourceTree = ""; @@ -10974,11 +10988,11 @@ B2FEA6892B460CEC0058E616 /* Address */ = { isa = PBXGroup; children = ( + 8A97E6EC2C58489C00F94793 /* AddressUtility */, 8C2937732BF79F0C00146613 /* Edit */, B2FEA68C2B460D390058E616 /* AddressAutofillSettingsViewController.swift */, B2FEA68E2B460D9E0058E616 /* AddressAutofillSettingsViewModel.swift */, B2DFB7DE2B619DB80004CEA5 /* AddressListViewModel.swift */, - 8CEDF07F2BFE138B00D2617B /* AddressProvider.swift */, B2FEA68A2B460D1D0058E616 /* AddressAutofillSettingsView.swift */, B2FEA6902B4661BE0058E616 /* AddressAutofillToggle.swift */, B2DFB7E02B619DF60004CEA5 /* AddressListView.swift */, @@ -15070,6 +15084,7 @@ 8A83B7462A264FA0002FF9AC /* SettingsCoordinator.swift in Sources */, A9072B801D07B34100459960 /* NoImageModeHelper.swift in Sources */, 433396C827ACE92500491049 /* LegacyInactiveTabButton.swift in Sources */, + 8A97E6EA2C58487900F94793 /* AddressLocaleFeatureValidator.swift in Sources */, AB3DB0C92B596739001D32CB /* AppStartupTelemetry.swift in Sources */, D8AA923421A602DC002605C0 /* HomePageSettingViewController.swift in Sources */, 8A161411282C035D00DDBB02 /* CustomizeHomepageSectionViewModel.swift in Sources */, @@ -15670,6 +15685,7 @@ 4A59B58AD11B5EE1F80BBDEB /* TestHistory.swift in Sources */, A83E5B1D1C1DA8D80026D912 /* UIPasteboardExtensionsTests.swift in Sources */, 8A635ECD289437A8006378BA /* SyncedTabCellTests.swift in Sources */, + 8A97E6EF2C584C4900F94793 /* AddressLocaleFeatureValidatorTests.swift in Sources */, E1E425322B5A2E9700899550 /* DownloadTests.swift in Sources */, 5AB4237C28A1947A003BC40C /* MockNotificationCenter.swift in Sources */, 8A37C79F28DA4BA600B1FAD4 /* ContextualHintViewProviderTests.swift in Sources */, diff --git a/firefox-ios/Client/FeatureFlags/NimbusFlaggableFeature.swift b/firefox-ios/Client/FeatureFlags/NimbusFlaggableFeature.swift index 4fce434cb1eb..e8d6c80efb4e 100644 --- a/firefox-ios/Client/FeatureFlags/NimbusFlaggableFeature.swift +++ b/firefox-ios/Client/FeatureFlags/NimbusFlaggableFeature.swift @@ -10,7 +10,6 @@ import UIKit /// Please add new features alphabetically. enum NimbusFeatureFlagID: String, CaseIterable { case accountSettingsRedux - case addressAutofill case addressAutofillEdit case bottomSearchBar case contextualHintForToolbar @@ -78,7 +77,6 @@ struct NimbusFlaggableFeature: HasNimbusSearchBar { // Cases where users do not have the option to manipulate a setting. case .contextualHintForToolbar, .accountSettingsRedux, - .addressAutofill, .addressAutofillEdit, .creditCardAutofillStatus, .fakespotBackInStock, diff --git a/firefox-ios/Client/Frontend/Autofill/Address/AddressUtility/AddressLocaleFeatureValidator.swift b/firefox-ios/Client/Frontend/Autofill/Address/AddressUtility/AddressLocaleFeatureValidator.swift new file mode 100644 index 000000000000..851aca5ad913 --- /dev/null +++ b/firefox-ios/Client/Frontend/Autofill/Address/AddressUtility/AddressLocaleFeatureValidator.swift @@ -0,0 +1,16 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/ + +import Foundation + +struct AddressLocaleFeatureValidator { + static let supportedRegions = ["CA", "US"] + + static func isValidRegion(locale: Locale = Locale.current) -> Bool { + guard let regionCode = locale.regionCode else { + return false + } + return supportedRegions.contains(regionCode) + } +} diff --git a/firefox-ios/Client/Frontend/Autofill/Address/AddressProvider.swift b/firefox-ios/Client/Frontend/Autofill/Address/AddressUtility/AddressProvider.swift similarity index 100% rename from firefox-ios/Client/Frontend/Autofill/Address/AddressProvider.swift rename to firefox-ios/Client/Frontend/Autofill/Address/AddressUtility/AddressProvider.swift diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift index 53627a79463f..0409aa6feddb 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift @@ -2540,10 +2540,6 @@ class BrowserViewController: UIViewController, return (userDefaults.object(forKey: keyCreditCardAutofill) as? Bool ?? true) } - private func addressAutofillNimbusFeatureFlag() -> Bool { - return featureFlags.isFeatureEnabled(.addressAutofill, checking: .buildOnly) - } - private func addressAutofillSettingsUserDefaultsIsEnabled() -> Bool { let userDefaults = UserDefaults.standard let keyAddressAutofill = PrefsKeys.KeyAutofillAddressStatus @@ -2563,7 +2559,7 @@ class BrowserViewController: UIViewController, switch fieldValues.fieldValue { case .address: guard addressAutofillSettingsUserDefaultsIsEnabled(), - addressAutofillNimbusFeatureFlag(), + AddressLocaleFeatureValidator.isValidRegion(), // FXMO-376: Phase 2 let addressPayload = fieldValues.fieldData as? UnencryptedAddressFields, let type = type else { return } diff --git a/firefox-ios/Client/Frontend/Settings/Main/AppSettingsTableViewController.swift b/firefox-ios/Client/Frontend/Settings/Main/AppSettingsTableViewController.swift index 5af35a7cbe1b..d24f9833e8ba 100644 --- a/firefox-ios/Client/Frontend/Settings/Main/AppSettingsTableViewController.swift +++ b/firefox-ios/Client/Frontend/Settings/Main/AppSettingsTableViewController.swift @@ -284,7 +284,7 @@ class AppSettingsTableViewController: SettingsTableViewController, privacySettings.append(AutofillCreditCardSettings(settings: self, settingsDelegate: parentCoordinator)) } - let autofillAddressStatus = featureFlags.isFeatureEnabled(.addressAutofill, checking: .buildOnly) + let autofillAddressStatus = AddressLocaleFeatureValidator.isValidRegion() if autofillAddressStatus { privacySettings.append(AddressAutofillSetting(theme: themeManager.getCurrentTheme(for: windowUUID), profile: profile, diff --git a/firefox-ios/Client/Frontend/Settings/SyncContentSettingsViewController.swift b/firefox-ios/Client/Frontend/Settings/SyncContentSettingsViewController.swift index 7ea9ed316950..953ea8eb0af3 100644 --- a/firefox-ios/Client/Frontend/Settings/SyncContentSettingsViewController.swift +++ b/firefox-ios/Client/Frontend/Settings/SyncContentSettingsViewController.swift @@ -265,9 +265,7 @@ class SyncContentSettingsViewController: SettingsTableViewController, FeatureFla engineSectionChildren.append(creditCards) } - if featureFlags.isFeatureEnabled( - .addressAutofill, - checking: .buildOnly) { + if AddressLocaleFeatureValidator.isValidRegion() { engineSectionChildren.append(addresses) } diff --git a/firefox-ios/Client/Nimbus/NimbusFeatureFlagLayer.swift b/firefox-ios/Client/Nimbus/NimbusFeatureFlagLayer.swift index fa71c86b758e..6d2c3419e432 100644 --- a/firefox-ios/Client/Nimbus/NimbusFeatureFlagLayer.swift +++ b/firefox-ios/Client/Nimbus/NimbusFeatureFlagLayer.swift @@ -13,9 +13,6 @@ final class NimbusFeatureFlagLayer { case .accountSettingsRedux: return checkAccountSettingsRedux(from: nimbus) - case .addressAutofill: - return checkAddressAutofill(from: nimbus) - case .addressAutofillEdit: return checkAddressAutofillEditing(from: nimbus) @@ -254,16 +251,10 @@ final class NimbusFeatureFlagLayer { return nimbus.features.homescreenFeature.value().preferSwitchToOpenTab } - private func checkAddressAutofill(from nimbus: FxNimbus) -> Bool { - let config = nimbus.features.addressAutofillFeature.value() - - return config.status - } - private func checkAddressAutofillEditing(from nimbus: FxNimbus) -> Bool { - let config = nimbus.features.addressAutofillFeature.value() + let config = nimbus.features.addressAutofillEdit.value() - return config.addressAutofillEdit + return config.status } private func checkZoomFeature(from nimbus: FxNimbus) -> Bool { diff --git a/firefox-ios/RustFxA/FxAWebViewModel.swift b/firefox-ios/RustFxA/FxAWebViewModel.swift index 1b3d3bec8a88..d250944859d0 100644 --- a/firefox-ios/RustFxA/FxAWebViewModel.swift +++ b/firefox-ios/RustFxA/FxAWebViewModel.swift @@ -309,7 +309,7 @@ extension FxAWebViewModel { /// signing up for an account). This latter case is also used for the sign-in state. private func onSessionStatus(id: Int, webView: WKWebView) { let autofillCreditCardStatus = featureFlags.isFeatureEnabled(.creditCardAutofillStatus, checking: .buildOnly) - let addressAutofillStatus = featureFlags.isFeatureEnabled(.addressAutofill, checking: .buildOnly) + let addressAutofillStatus = AddressLocaleFeatureValidator.isValidRegion() let creditCardCapability = autofillCreditCardStatus ? ", \"creditcards\"" : "" let addressAutofillCapability = addressAutofillStatus ? ", \"addresses\"" : "" diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Autofill/AddressLocaleFeatureValidatorTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Autofill/AddressLocaleFeatureValidatorTests.swift new file mode 100644 index 000000000000..48f06a0a37d3 --- /dev/null +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Autofill/AddressLocaleFeatureValidatorTests.swift @@ -0,0 +1,43 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/ + +import Foundation +import XCTest +import Common + +@testable import Client + +class AddressLocaleFeatureValidatorTests: XCTestCase { + func testValidRegionCA() { + let locale = Locale(identifier: "en_CA") + XCTAssertTrue( + AddressLocaleFeatureValidator.isValidRegion(locale: locale), + "Region valid for CA" + ) + } + + func testValidRegionUS() { + let locale = Locale(identifier: "en_US") + XCTAssertTrue( + AddressLocaleFeatureValidator.isValidRegion(locale: locale), + "Region valid for US" + ) + } + + func testInvalidRegionFR() { + let locale = Locale(identifier: "fr_FR") + XCTAssertFalse( + AddressLocaleFeatureValidator.isValidRegion(locale: locale), + "Invalid region for FR" + ) + } + + func testInvalidRegionWithoutRegionCode() { + let locale = Locale(identifier: "") + XCTAssertFalse( + AddressLocaleFeatureValidator.isValidRegion(locale: locale), + "Invalid region for locale without region code" + ) + } +} diff --git a/firefox-ios/nimbus-features/addressAutofillFeature.yaml b/firefox-ios/nimbus-features/addressAutofillFeature.yaml index f56692ffd8fa..301032c3ebbc 100644 --- a/firefox-ios/nimbus-features/addressAutofillFeature.yaml +++ b/firefox-ios/nimbus-features/addressAutofillFeature.yaml @@ -1,13 +1,9 @@ # The configuration for the addressAutofillFeature feature features: - address-autofill-feature: - description: This property defines the address card autofill feature + address-autofill-edit: + description: This property defines if the address editing is enabled in Settings variables: status: - description: If true, we will allow user to use the address autofill feature - type: Boolean - default: false - address-autofill-edit: description: If true, we will allow user to edit the address type: Boolean default: false @@ -15,8 +11,6 @@ features: - channel: beta value: status: false - address-autofill-edit: false - channel: developer value: status: true - address-autofill-edit: true From 4846c84a65be72257758f113f8a214a4e6938dbc Mon Sep 17 00:00:00 2001 From: dragosb01 <134391433+dragosb01@users.noreply.github.com> Date: Wed, 31 Jul 2024 12:18:03 +0300 Subject: [PATCH 016/128] Fix MTE-3232 - testTypeOnGivenFields test (#21343) * Fix MTE-3232 - testTypeOnGivenFields test * Use a better navigator.performAction() * Should be "sign in" --------- Co-authored-by: Clare So --- .../firefox-ios-tests/Tests/XCUITests/SyncFAUITests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/SyncFAUITests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/SyncFAUITests.swift index e846d81efa6f..e897c1a37e07 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/SyncFAUITests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/SyncFAUITests.swift @@ -73,7 +73,7 @@ class SyncUITests: BaseTestCase { // Enter only email, wrong and correct and tap sign in userState.fxaUsername = "foo1bar2baz3@gmail.com" navigator.performAction(Action.FxATypeEmail) - navigator.performAction(Action.FxATapOnSignInButton) + navigator.performAction(Action.FxATapOnContinueButton) // Enter invalid (too short, it should be at least 8 chars) and incorrect password userState.fxaPassword = "foo" From 58fc1b81099c41e9aa7e6ca3ff6d7dba3cee2220 Mon Sep 17 00:00:00 2001 From: PARAIPAN SORIN <51127880+PARAIPAN9@users.noreply.github.com> Date: Wed, 31 Jul 2024 12:22:40 +0300 Subject: [PATCH 017/128] Add FXIOS-9434 - Add config for toolbar action images to be flipped for RTL if necessary (#21344) * Add imageFlippedForRightToLeftLayoutDirection config * Add config method for rtl layout * Add documentation comment for isFlippedForRTL var --- BrowserKit/Sources/ToolbarKit/ToolbarButton.swift | 7 ++++++- BrowserKit/Sources/ToolbarKit/ToolbarElement.swift | 6 ++++++ .../Toolbars/Models/AddressToolbarContainerModel.swift | 1 + .../Toolbars/Models/NavigationToolbarContainerModel.swift | 1 + .../Browser/Toolbars/Redux/ToolbarActionState.swift | 1 + .../Browser/Toolbars/Redux/ToolbarMiddleware.swift | 3 +++ 6 files changed, 18 insertions(+), 1 deletion(-) diff --git a/BrowserKit/Sources/ToolbarKit/ToolbarButton.swift b/BrowserKit/Sources/ToolbarKit/ToolbarButton.swift index e225723d04af..9296b0dbff3e 100644 --- a/BrowserKit/Sources/ToolbarKit/ToolbarButton.swift +++ b/BrowserKit/Sources/ToolbarKit/ToolbarButton.swift @@ -47,7 +47,7 @@ class ToolbarButton: UIButton, ThemeApplicable { configureLongPressGestureRecognizerIfNeeded(for: element) shouldDisplayAsHighlighted = element.shouldDisplayAsHighlighted - let image = UIImage(named: element.iconName)?.withRenderingMode(.alwaysTemplate) + let image = imageConfiguredForRTL(for: element) let action = UIAction(title: element.a11yLabel, image: image, handler: { _ in @@ -124,6 +124,11 @@ class ToolbarButton: UIButton, ThemeApplicable { addGestureRecognizer(longPressRecognizer) } + private func imageConfiguredForRTL(for element: ToolbarElement) -> UIImage? { + let image = UIImage(named: element.iconName)?.withRenderingMode(.alwaysTemplate) + return element.isFlippedForRTL ? image?.imageFlippedForRightToLeftLayoutDirection() : image + } + private func removeAllGestureRecognizers() { guard let gestureRecognizers else { return } for recognizer in gestureRecognizers { diff --git a/BrowserKit/Sources/ToolbarKit/ToolbarElement.swift b/BrowserKit/Sources/ToolbarKit/ToolbarElement.swift index e2b7558ebf7e..4eb942705249 100644 --- a/BrowserKit/Sources/ToolbarKit/ToolbarElement.swift +++ b/BrowserKit/Sources/ToolbarKit/ToolbarElement.swift @@ -17,6 +17,9 @@ public struct ToolbarElement: Equatable { /// Whether the toolbar element can be interacted with let isEnabled: Bool + /// Indicates whether the toolbar element's image should be flipped for right-to-left layout direction + let isFlippedForRTL: Bool + /// Indicates if the element should be displayed as highlighted let shouldDisplayAsHighlighted: Bool @@ -41,6 +44,7 @@ public struct ToolbarElement: Equatable { badgeImageName: String? = nil, numberOfTabs: Int? = nil, isEnabled: Bool, + isFlippedForRTL: Bool = false, shouldDisplayAsHighlighted: Bool = false, a11yLabel: String, a11yHint: String?, @@ -51,6 +55,7 @@ public struct ToolbarElement: Equatable { self.badgeImageName = badgeImageName self.numberOfTabs = numberOfTabs self.isEnabled = isEnabled + self.isFlippedForRTL = isFlippedForRTL self.shouldDisplayAsHighlighted = shouldDisplayAsHighlighted self.onSelected = onSelected self.onLongPress = onLongPress @@ -64,6 +69,7 @@ public struct ToolbarElement: Equatable { lhs.badgeImageName == rhs.badgeImageName && lhs.numberOfTabs == rhs.numberOfTabs && lhs.isEnabled == rhs.isEnabled && + lhs.isFlippedForRTL == rhs.isFlippedForRTL && lhs.shouldDisplayAsHighlighted == rhs.shouldDisplayAsHighlighted && lhs.a11yLabel == rhs.a11yLabel && lhs.a11yHint == rhs.a11yHint && diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift index 68e9713a90a1..173e54ae2913 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift @@ -87,6 +87,7 @@ class AddressToolbarContainerModel: Equatable { badgeImageName: action.badgeImageName, numberOfTabs: action.numberOfTabs, isEnabled: action.isEnabled, + isFlippedForRTL: action.isFlippedForRTL, a11yLabel: action.a11yLabel, a11yHint: action.a11yHint, a11yId: action.a11yId, diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/NavigationToolbarContainerModel.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/NavigationToolbarContainerModel.swift index 2121f12ec62a..3553f323cc25 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/NavigationToolbarContainerModel.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/NavigationToolbarContainerModel.swift @@ -22,6 +22,7 @@ struct NavigationToolbarContainerModel: Equatable { badgeImageName: action.badgeImageName, numberOfTabs: action.numberOfTabs, isEnabled: action.isEnabled, + isFlippedForRTL: action.isFlippedForRTL, a11yLabel: action.a11yLabel, a11yHint: action.a11yHint, a11yId: action.a11yId, diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarActionState.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarActionState.swift index a167a9f8e7de..31cbdef318aa 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarActionState.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarActionState.swift @@ -28,6 +28,7 @@ struct ToolbarActionState: Equatable, FeatureFlaggable { var iconName: String var badgeImageName: String? var numberOfTabs: Int? + var isFlippedForRTL = false var isShowingTopTabs: Bool? var isEnabled: Bool var a11yLabel: String diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift index 5604d16384df..d5397c6731e2 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift @@ -52,6 +52,7 @@ class ToolbarMiddleware: FeatureFlaggable { lazy var cancelEditAction = ToolbarActionState( actionType: .cancelEdit, iconName: StandardImageIdentifiers.Large.chevronLeft, + isFlippedForRTL: true, isEnabled: true, a11yLabel: AccessibilityIdentifiers.GeneralizedIdentifiers.back, a11yId: AccessibilityIdentifiers.Browser.UrlBar.cancelButton) @@ -609,6 +610,7 @@ class ToolbarMiddleware: FeatureFlaggable { return ToolbarActionState( actionType: .back, iconName: StandardImageIdentifiers.Large.back, + isFlippedForRTL: true, isEnabled: enabled, a11yLabel: .TabToolbarBackAccessibilityLabel, a11yId: AccessibilityIdentifiers.Toolbar.backButton) @@ -618,6 +620,7 @@ class ToolbarMiddleware: FeatureFlaggable { return ToolbarActionState( actionType: .forward, iconName: StandardImageIdentifiers.Large.forward, + isFlippedForRTL: true, isEnabled: enabled, a11yLabel: .TabToolbarForwardAccessibilityLabel, a11yId: AccessibilityIdentifiers.Toolbar.forwardButton) From 29753d7e41d110c65149971af2b09092bcc0ec04 Mon Sep 17 00:00:00 2001 From: Sammy Khamis Date: Wed, 31 Jul 2024 03:15:03 -1000 Subject: [PATCH 018/128] Add FXIOS-9398 [Remote Tab Management] Close tabs upon receiving close tab commands (#20810) --- .../AppDelegate+SyncSentTabs.swift | 19 +++++++--- .../Client/Application/AppDelegate.swift | 2 +- .../Client/Application/AppLaunchUtil.swift | 8 +++- .../Application/UITestAppDelegate.swift | 4 +- firefox-ios/Client/ApplicationHelper.swift | 14 +++++++ .../FeatureFlags/NimbusFlaggableFeature.swift | 4 +- .../Main/AppSettingsTableViewController.swift | 2 +- .../FeatureFlagsDebugViewController.swift | 17 ++++++++- .../Nimbus/NimbusFeatureFlagLayer.swift | 8 ++++ .../Legacy/LegacyTabManager.swift | 14 +++++++ .../Client/TabManagement/TabManager.swift | 3 ++ firefox-ios/Providers/Profile.swift | 31 +++++++++++----- firefox-ios/RustFxA/RustFirefoxAccounts.swift | 25 +++++++++++-- .../Application/AppSendTabDelegateTests.swift | 37 ++++++++++++++++--- .../Mocks/MockApplicationHelper.swift | 5 +++ .../ClientTests/Mocks/MockTabManager.swift | 6 +++ .../nimbus-features/remoteTabManagement.yaml | 22 +++++++++++ firefox-ios/nimbus.fml.yaml | 1 + 18 files changed, 191 insertions(+), 31 deletions(-) create mode 100644 firefox-ios/nimbus-features/remoteTabManagement.yaml diff --git a/firefox-ios/Client/Application/AppDelegate+SyncSentTabs.swift b/firefox-ios/Client/Application/AppDelegate+SyncSentTabs.swift index a0956a4e3698..ad555e43fecf 100644 --- a/firefox-ios/Client/Application/AppDelegate+SyncSentTabs.swift +++ b/firefox-ios/Client/Application/AppDelegate+SyncSentTabs.swift @@ -10,16 +10,17 @@ import Account import Common extension UIApplication { - var sendTabDelegate: SendTabDelegate { - return AppSendTabDelegate(app: self) + var fxaCommandsDelegate: FxACommandsDelegate { + return AppFxACommandsDelegate(app: self) } } -/// Sent tabs can be displayed not only by receiving push notifications, but by sync. +/// Close and Sent tabs can be displayed not only by receiving push notifications, +/// but by sync. /// Sync will get the list of sent tabs, and try to display any in that list. -/// Thus, push notifications are not needed to receive sent tabs, they can be handled -/// when the app performs a sync. -class AppSendTabDelegate: SendTabDelegate { +/// Thus, push notifications are not needed to receive sent or closed tabs; +/// they can be handled when the app performs a sync. +class AppFxACommandsDelegate: FxACommandsDelegate { private let app: ApplicationStateProvider private let logger: Logger private var applicationHelper: ApplicationHelper @@ -46,4 +47,10 @@ class AppSendTabDelegate: SendTabDelegate { } } } + + func closeTabs(for urls: [URL]) { + Task { + await self.applicationHelper.closeTabs(urls) + } + } } diff --git a/firefox-ios/Client/Application/AppDelegate.swift b/firefox-ios/Client/Application/AppDelegate.swift index c75da4485cb6..f0645d45d105 100644 --- a/firefox-ios/Client/Application/AppDelegate.swift +++ b/firefox-ios/Client/Application/AppDelegate.swift @@ -25,7 +25,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { lazy var profile: Profile = BrowserProfile( localName: "profile", - sendTabDelegate: UIApplication.shared.sendTabDelegate, + fxaCommandsDelegate: UIApplication.shared.fxaCommandsDelegate, creditCardAutofillEnabled: creditCardAutofillStatus ) diff --git a/firefox-ios/Client/Application/AppLaunchUtil.swift b/firefox-ios/Client/Application/AppLaunchUtil.swift index 47b2667e2426..50a8d2bf2171 100644 --- a/firefox-ios/Client/Application/AppLaunchUtil.swift +++ b/firefox-ios/Client/Application/AppLaunchUtil.swift @@ -78,7 +78,13 @@ class AppLaunchUtil { } } - RustFirefoxAccounts.startup(prefs: profile.prefs) { _ in + // RustFirefoxAccounts doesn't have access to the feature flags + // So we check the nimbus flag here before sending it to the startup + var fxaFeatures: RustFxAFeatures = [] + if LegacyFeatureFlagsManager.shared.isFeatureEnabled(.closeRemoteTabs, checking: .buildAndUser) { + fxaFeatures.insert(.closeRemoteTabs) + } + RustFirefoxAccounts.startup(prefs: profile.prefs, features: fxaFeatures) { _ in self.logger.log("RustFirefoxAccounts started", level: .info, category: .sync) AppEventQueue.signal(event: .accountManagerInitialized) } diff --git a/firefox-ios/Client/Application/UITestAppDelegate.swift b/firefox-ios/Client/Application/UITestAppDelegate.swift index 7f347a7daed4..9a5d8d2206ac 100644 --- a/firefox-ios/Client/Application/UITestAppDelegate.swift +++ b/firefox-ios/Client/Application/UITestAppDelegate.swift @@ -134,13 +134,13 @@ class UITestAppDelegate: AppDelegate, FeatureFlaggable { // Use a clean profile for each test session. profile = BrowserProfile( localName: "testProfile", - sendTabDelegate: application.sendTabDelegate, + fxaCommandsDelegate: application.fxaCommandsDelegate, clear: true ) } else { profile = BrowserProfile( localName: "testProfile", - sendTabDelegate: application.sendTabDelegate + fxaCommandsDelegate: application.fxaCommandsDelegate ) } diff --git a/firefox-ios/Client/ApplicationHelper.swift b/firefox-ios/Client/ApplicationHelper.swift index 55925612388f..1079f5b3bce5 100644 --- a/firefox-ios/Client/ApplicationHelper.swift +++ b/firefox-ios/Client/ApplicationHelper.swift @@ -9,6 +9,7 @@ protocol ApplicationHelper { func openSettings() func open(_ url: URL) func open(_ url: URL, inWindow: WindowUUID) + func closeTabs(_ urls: [URL]) async } /// UIApplication.shared wrapper @@ -46,4 +47,17 @@ struct DefaultApplicationHelper: ApplicationHelper { open(url) } } + + /// Closes all tabs that match the url passed in + /// This is most likely from other clients connected to the same + /// account requesting to close the tab on this device + /// + /// - Parameters: + /// - urls: an array of URLs requested to be closed + func closeTabs(_ urls: [URL]) async { + let windowManager = AppContainer.shared.resolve() as WindowManager + for tabManager in windowManager.allWindowTabManagers() { + await tabManager.removeTabs(by: urls) + } + } } diff --git a/firefox-ios/Client/FeatureFlags/NimbusFlaggableFeature.swift b/firefox-ios/Client/FeatureFlags/NimbusFlaggableFeature.swift index e8d6c80efb4e..752d4e2a9b08 100644 --- a/firefox-ios/Client/FeatureFlags/NimbusFlaggableFeature.swift +++ b/firefox-ios/Client/FeatureFlags/NimbusFlaggableFeature.swift @@ -30,6 +30,7 @@ enum NimbusFeatureFlagID: String, CaseIterable { case nightMode case preferSwitchToOpenTabOverDuplicate case reduxSearchSettings + case closeRemoteTabs case reportSiteIssue case searchHighlights case splashScreen @@ -41,7 +42,7 @@ enum NimbusFeatureFlagID: String, CaseIterable { var debugKey: String? { switch self { - case .microsurvey: + case .microsurvey, .closeRemoteTabs: return rawValue + PrefsKeys.FeatureFlags.DebugSuffixKey default: return nil @@ -79,6 +80,7 @@ struct NimbusFlaggableFeature: HasNimbusSearchBar { .accountSettingsRedux, .addressAutofillEdit, .creditCardAutofillStatus, + .closeRemoteTabs, .fakespotBackInStock, .fakespotFeature, .fakespotProductAds, diff --git a/firefox-ios/Client/Frontend/Settings/Main/AppSettingsTableViewController.swift b/firefox-ios/Client/Frontend/Settings/Main/AppSettingsTableViewController.swift index d24f9833e8ba..c8fe567791c8 100644 --- a/firefox-ios/Client/Frontend/Settings/Main/AppSettingsTableViewController.swift +++ b/firefox-ios/Client/Frontend/Settings/Main/AppSettingsTableViewController.swift @@ -367,7 +367,7 @@ class AppSettingsTableViewController: SettingsTableViewController, SentryIDSetting(settings: self, settingsDelegate: self), FasterInactiveTabs(settings: self, settingsDelegate: self), OpenFiftyTabsDebugOption(settings: self, settingsDelegate: self), - FirefoxSuggestSettings(settings: self, settingsDelegate: self) + FirefoxSuggestSettings(settings: self, settingsDelegate: self), ] #if MOZ_CHANNEL_BETA || MOZ_CHANNEL_FENNEC diff --git a/firefox-ios/Client/Frontend/Settings/Main/Debug/FeatureFlags/FeatureFlagsDebugViewController.swift b/firefox-ios/Client/Frontend/Settings/Main/Debug/FeatureFlags/FeatureFlagsDebugViewController.swift index b075398d0db8..28fdedd3a78d 100644 --- a/firefox-ios/Client/Frontend/Settings/Main/Debug/FeatureFlags/FeatureFlagsDebugViewController.swift +++ b/firefox-ios/Client/Frontend/Settings/Main/Debug/FeatureFlags/FeatureFlagsDebugViewController.swift @@ -34,7 +34,8 @@ final class FeatureFlagsDebugViewController: SettingsTableViewController, Featur UserDefaults.standard.set(nil, forKey: "\(GleanPlumbMessageStore.rootKey)\("homepage-microsurvey-message")") self?.reloadView() } - return SettingSection(title: nil, children: [microsurveySetting]) + let closeRemoteTabsSetting = getCloseRemoteTabSetting(theme) + return SettingSection(title: nil, children: [microsurveySetting, closeRemoteTabsSetting]) } private func generateFeatureFlagList() -> SettingSection { @@ -52,6 +53,20 @@ final class FeatureFlagsDebugViewController: SettingsTableViewController, Featur ) } + private func getCloseRemoteTabSetting(_ theme: Theme) -> FeatureFlagsBoolSetting { + FeatureFlagsBoolSetting( + with: .closeRemoteTabs, + titleText: NSAttributedString( + string: "Enable Close Remote Tabs", + attributes: [NSAttributedString.Key.foregroundColor: theme.colors.textPrimary]), + statusText: NSAttributedString( + string: "Toggle to enable closing tabs remotely feature", + attributes: [NSAttributedString.Key.foregroundColor: theme.colors.textPrimary]) + ) { [weak self] _ in + self?.reloadView() + } + } + private func reloadView() { self.settings = self.generateSettings() self.tableView.reloadData() diff --git a/firefox-ios/Client/Nimbus/NimbusFeatureFlagLayer.swift b/firefox-ios/Client/Nimbus/NimbusFeatureFlagLayer.swift index 6d2c3419e432..47c35edab601 100644 --- a/firefox-ios/Client/Nimbus/NimbusFeatureFlagLayer.swift +++ b/firefox-ios/Client/Nimbus/NimbusFeatureFlagLayer.swift @@ -67,6 +67,9 @@ final class NimbusFeatureFlagLayer { case .reduxSearchSettings: return checkReduxSearchSettingsFeature(from: nimbus) + case .closeRemoteTabs: + return checkCloseRemoteTabsFeature(from: nimbus) + case .reportSiteIssue: return checkGeneralFeature(for: featureID, from: nimbus) @@ -289,4 +292,9 @@ final class NimbusFeatureFlagLayer { return config.enabled } + + private func checkCloseRemoteTabsFeature(from nimbus: FxNimbus) -> Bool { + let config = nimbus.features.remoteTabManagement.value() + return config.closeTabsEnabled + } } diff --git a/firefox-ios/Client/TabManagement/Legacy/LegacyTabManager.swift b/firefox-ios/Client/TabManagement/Legacy/LegacyTabManager.swift index 0b177e689447..442af4dde7a8 100644 --- a/firefox-ios/Client/TabManagement/Legacy/LegacyTabManager.swift +++ b/firefox-ios/Client/TabManagement/Legacy/LegacyTabManager.swift @@ -639,6 +639,20 @@ class LegacyTabManager: NSObject, FeatureFlaggable, TabManager, TabEventHandler storeChanges() } + @MainActor + func removeTabs(by urls: [URL]) async { + let urls = Set(urls) + let tabsToRemove = normalTabs.filter { tab in + guard let url = tab.url else { return false } + return urls.contains(url) + } + for tab in tabsToRemove { + await withCheckedContinuation { continuation in + removeTab(tab) { continuation.resume() } + } + } + } + @MainActor func removeAllTabs(isPrivateMode: Bool) async { let currentModeTabs = tabs.filter { $0.isPrivate == isPrivateMode } diff --git a/firefox-ios/Client/TabManagement/TabManager.swift b/firefox-ios/Client/TabManagement/TabManager.swift index 66b9cddce91a..2db98c9be2ec 100644 --- a/firefox-ios/Client/TabManagement/TabManager.swift +++ b/firefox-ios/Client/TabManagement/TabManager.swift @@ -83,6 +83,9 @@ protocol TabManager: AnyObject { /// Undo close all tabs, it will restore the tabs that were backed up when the close action was called. func undoCloseAllTabs() + /// Removes all tabs matching the urls, used when other clients request to close tabs on this device. + func removeTabs(by urls: [URL]) async + /// Get inactive tabs from the list of tabs based on the time condition to be considered inactive. /// Replaces LegacyInactiveTabModel and related classes /// diff --git a/firefox-ios/Providers/Profile.swift b/firefox-ios/Providers/Profile.swift index e23f1d2d876b..d52dac7abd4d 100644 --- a/firefox-ios/Providers/Profile.swift +++ b/firefox-ios/Providers/Profile.swift @@ -51,8 +51,9 @@ public protocol SyncManager { /// This exists to pass in external context: e.g., the UIApplication can /// expose notification functionality in this way. -public protocol SendTabDelegate: AnyObject { +public protocol FxACommandsDelegate: AnyObject { func openSendTabs(for urls: [URL]) + func closeTabs(for urls: [URL]) } class ProfileFileAccessor: FileAccessor { @@ -234,7 +235,7 @@ open class BrowserProfile: Profile { let readingListDB: BrowserDB var syncManager: SyncManager! - var sendTabDelegate: SendTabDelegate? + var fxaCommandsDelegate: FxACommandsDelegate? /** * N.B., BrowserProfile is used from our extensions, often via a pattern like @@ -249,7 +250,7 @@ open class BrowserProfile: Profile { * However, if we provide it here, it's assumed that we're initializing it from the application. */ init(localName: String, - sendTabDelegate: SendTabDelegate? = nil, + fxaCommandsDelegate: FxACommandsDelegate? = nil, creditCardAutofillEnabled: Bool = false, clear: Bool = false, logger: Logger = DefaultLogger.shared) { @@ -260,7 +261,7 @@ open class BrowserProfile: Profile { self.files = ProfileFileAccessor(localName: localName) self.keychain = MZKeychainWrapper.sharedClientAppContainerKeychain self.logger = logger - self.sendTabDelegate = sendTabDelegate + self.fxaCommandsDelegate = fxaCommandsDelegate if clear { do { @@ -603,16 +604,26 @@ open class BrowserProfile: Profile { if let accountManager = self.rustFxA.accountManager { accountManager.deviceConstellation()?.pollForCommands { commands in guard let commands = try? commands.get() else { return } - let urls = commands.compactMap { command in + + var receivedTabURLs: [URL] = [] + var closedTabURLs: [URL] = [] + for command in commands { switch command { case .tabReceived(_, let tabData): - let url = tabData.entries.last?.url ?? "" - return URL(string: url, invalidCharacters: false) - default: - return nil + if let urlString = tabData.entries.last?.url, let url = URL(string: urlString) { + receivedTabURLs.append(url) + } + case .tabsClosed(sender: _, let closeTabPayload): + closedTabURLs.append(contentsOf: closeTabPayload.urls.compactMap { URL(string: $0) }) } } - self.sendTabDelegate?.openSendTabs(for: urls) + if !receivedTabURLs.isEmpty { + self.fxaCommandsDelegate?.openSendTabs(for: receivedTabURLs) + } + + if !closedTabURLs.isEmpty { + self.fxaCommandsDelegate?.closeTabs(for: closedTabURLs) + } } } } diff --git a/firefox-ios/RustFxA/RustFirefoxAccounts.swift b/firefox-ios/RustFxA/RustFirefoxAccounts.swift index 0dd5f77cb624..15e81426fe70 100644 --- a/firefox-ios/RustFxA/RustFirefoxAccounts.swift +++ b/firefox-ios/RustFxA/RustFirefoxAccounts.swift @@ -8,6 +8,7 @@ import Shared import class MozillaAppServices.FxAccountManager import class MozillaAppServices.FxAConfig +import enum MozillaAppServices.DeviceCapability import enum MozillaAppServices.DeviceType import enum MozillaAppServices.OAuthScope import struct MozillaAppServices.DeviceConfig @@ -23,6 +24,18 @@ final class Unknown: NSObject, NSCoding { } } +// A convenience to allow other callers to pass in Nimbus/Flaggable features +// to RustFirefoxAccounts +public struct RustFxAFeatures: OptionSet { + public let rawValue: Int + + public static let closeRemoteTabs = RustFxAFeatures(rawValue: 1 << 0) + + public init(rawValue: Int) { + self.rawValue = rawValue + } +} + // TODO: renamed FirefoxAccounts.swift once the old code is removed fully. /** A singleton that wraps the Rust FxA library. @@ -71,6 +84,7 @@ open class RustFirefoxAccounts { */ public static func startup( prefs: Prefs, + features: RustFxAFeatures = RustFxAFeatures(), logger: Logger = DefaultLogger.shared, completion: @escaping (FxAccountManager) -> Void ) { @@ -84,7 +98,7 @@ open class RustFirefoxAccounts { if let accManager = RustFirefoxAccounts.shared.accountManager { completion(accManager) } - let manager = RustFirefoxAccounts.shared.createAccountManager() + let manager = RustFirefoxAccounts.shared.createAccountManager(features: features) manager.initialize { result in assert(Thread.isMainThread) if !Thread.isMainThread { @@ -117,7 +131,7 @@ open class RustFirefoxAccounts { return RustFirefoxAccounts.prefs?.boolForKey(PrefsKeys.KeyEnableChinaSyncService) ?? AppInfo.isChinaEdition } - private func createAccountManager() -> FxAccountManager { + private func createAccountManager(features: RustFxAFeatures) -> FxAccountManager { let prefs = RustFirefoxAccounts.prefs if prefs == nil { logger.log("prefs is unexpectedly nil", level: .warning, category: .sync) @@ -162,10 +176,15 @@ open class RustFirefoxAccounts { } let type = UIDevice.current.userInterfaceIdiom == .pad ? DeviceType.tablet : DeviceType.mobile + + var capabilities: [DeviceCapability] = [.sendTab] + if features.contains(.closeRemoteTabs) { + capabilities.append(.closeTabs) + } let deviceConfig = DeviceConfig( name: DeviceInfo.defaultClientName(), deviceType: type, - capabilities: [.sendTab] + capabilities: capabilities ) let accessGroupPrefix = Bundle.main.object(forInfoDictionaryKey: "MozDevelopmentTeam") as! String let accessGroupIdentifier = AppInfo.keychainAccessGroupWithPrefix(accessGroupPrefix) diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Application/AppSendTabDelegateTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Application/AppSendTabDelegateTests.swift index 5e70bbd32745..653ac2a74801 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Application/AppSendTabDelegateTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Application/AppSendTabDelegateTests.swift @@ -5,7 +5,7 @@ import XCTest @testable import Client -final class AppSendTabDelegateTests: XCTestCase { +final class AppFxACommandsTests: XCTestCase { private var applicationStateProvider: MockApplicationStateProvider! private var applicationHelper: MockApplicationHelper! @@ -57,12 +57,39 @@ final class AppSendTabDelegateTests: XCTestCase { XCTAssertEqual(applicationHelper.openURLCalled, 3) } + // MARK: - Close Remote Tabs Tests + func testCloseSendTabs_activeWithOneURL_callsDeeplink() async { + let url = URL(string: "https://mozilla.com", invalidCharacters: false)! + let subject = createSubject() + let expectation = XCTestExpectation(description: "Close tabs called") + subject.closeTabs(for: [url]) + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { + expectation.fulfill() + XCTAssertEqual(self.applicationHelper.closeTabsCalled, 1) + } + await fulfillment(of: [expectation]) + } + + func testCloseSendTabs_activeWithMultipleURLs_callsDeeplink() async { + let url1 = URL(string: "https://example.com", invalidCharacters: false)! + let url2 = URL(string: "https://example.com/1", invalidCharacters: false)! + let url3 = URL(string: "https://example.com/2", invalidCharacters: false)! + let subject = createSubject() + let expectation = XCTestExpectation(description: "Close tabs called multiple times") + subject.closeTabs(for: [url1, url2, url3]) + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { + expectation.fulfill() + XCTAssertEqual(self.applicationHelper.closeTabsCalled, 1) + } + await fulfillment(of: [expectation]) + } + // MARK: - Helper methods - func createSubject() -> AppSendTabDelegate { - let subject = AppSendTabDelegate(app: applicationStateProvider, - applicationHelper: applicationHelper, - mainQueue: MockDispatchQueue()) + func createSubject() -> AppFxACommandsDelegate { + let subject = AppFxACommandsDelegate(app: applicationStateProvider, + applicationHelper: applicationHelper, + mainQueue: MockDispatchQueue()) trackForMemoryLeaks(subject) return subject } diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockApplicationHelper.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockApplicationHelper.swift index 1b96b55ed81a..7eff386cae59 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockApplicationHelper.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockApplicationHelper.swift @@ -11,6 +11,7 @@ class MockApplicationHelper: ApplicationHelper { var openURLCalled = 0 var openURLInWindowCalled = 0 var lastOpenURL: URL? + var closeTabsCalled = 0 func openSettings() { openSettingsCalled += 1 @@ -25,4 +26,8 @@ class MockApplicationHelper: ApplicationHelper { openURLInWindowCalled += 1 lastOpenURL = url } + + func closeTabs(_ urls: [URL]) { + closeTabsCalled += 1 + } } diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockTabManager.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockTabManager.swift index 1039cc45b45e..532224541b82 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockTabManager.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockTabManager.swift @@ -37,6 +37,8 @@ class MockTabManager: TabManager { var addTabsForURLsCalled = 0 var addTabsURLs: [URL] = [] + var removeTabsByURLCalled = 0 + init(windowUUID: WindowUUID = WindowUUID.XCTestDefaultUUID) { self.windowUUID = windowUUID } @@ -92,6 +94,10 @@ class MockTabManager: TabManager { func removeAllTabs(isPrivateMode: Bool) async {} + func removeTabs(by urls: [URL]) async { + removeTabsByURLCalled += 1 + } + func undoCloseAllTabs() {} func undoCloseTab() {} diff --git a/firefox-ios/nimbus-features/remoteTabManagement.yaml b/firefox-ios/nimbus-features/remoteTabManagement.yaml new file mode 100644 index 000000000000..b4017b30302d --- /dev/null +++ b/firefox-ios/nimbus-features/remoteTabManagement.yaml @@ -0,0 +1,22 @@ +# The configuration for the remoteTabManagement feature +features: + remote-tab-management: + description: > + Features that let users manage tabs on other devices that are + connected to the same Mozilla account. + variables: + close-tabs-enabled: + description: > + Whether the feature to close synced tabs is enabled. When enabled, + this device will allow other devices to close tabs that are open on this device, and + show a "close" button for tabs that are currently open on other supported devices + in the synced tabs tray. + type: Boolean + default: false + defaults: + - channel: beta + value: + close-tabs-enabled: false + - channel: developer + value: + close-tabs-enabled: true diff --git a/firefox-ios/nimbus.fml.yaml b/firefox-ios/nimbus.fml.yaml index f6eaee2a676a..23d6bf97be79 100644 --- a/firefox-ios/nimbus.fml.yaml +++ b/firefox-ios/nimbus.fml.yaml @@ -29,6 +29,7 @@ include: - nimbus-features/nightModeFeature.yaml - nimbus-features/onboardingFrameworkFeature.yaml - nimbus-features/reduxSearchSettingsFeature.yaml + - nimbus-features/remoteTabManagement.yaml - nimbus-features/searchFeature.yaml - nimbus-features/splashScreenFeature.yaml - nimbus-features/spotlightSearchFeature.yaml From dad1fd27db8a3872809d0740680f33de99e09804 Mon Sep 17 00:00:00 2001 From: "roux g. buciu" <11182210+adudenamedruby@users.noreply.github.com> Date: Wed, 31 Jul 2024 10:35:51 -0400 Subject: [PATCH 019/128] Bugfix FXIOS-9708 - Fix mask behaviour for private mode (#21371) --- .../Views/BrowserViewController.swift | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift index 0409aa6feddb..65dd3c90261d 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift @@ -3383,26 +3383,26 @@ extension BrowserViewController: TabManagerDelegate { webView.removeFromSuperview() } + if let tab = selected, previous == nil || tab.isPrivate != previous?.isPrivate { + applyTheme() + + if !isToolbarRefactorEnabled { + let ui: [PrivateModeUI?] = [toolbar, topTabsViewController, urlBar] + ui.forEach { $0?.applyUIMode(isPrivate: tab.isPrivate, theme: currentTheme()) } + } + } else { + // Theme is applied to the tab and webView in the else case + // because in the if block is applied already to all the tabs and web views + selected?.applyTheme(theme: currentTheme()) + selected?.webView?.applyTheme(theme: currentTheme()) + } + if let tab = selected, let webView = tab.webView { updateURLBarDisplayURL(tab) if !isToolbarRefactorEnabled, urlBar.inOverlayMode, tab.url?.displayURL != nil { urlBar.leaveOverlayMode(reason: .finished, shouldCancelLoading: false) } - if previous == nil || tab.isPrivate != previous?.isPrivate { - applyTheme() - - if !isToolbarRefactorEnabled { - let ui: [PrivateModeUI?] = [toolbar, topTabsViewController, urlBar] - ui.forEach { $0?.applyUIMode(isPrivate: tab.isPrivate, theme: currentTheme()) } - } - } else { - // Theme is applied to the tab and webView in the else case - // because in the if block is applied already to all the tabs and web views - tab.applyTheme(theme: currentTheme()) - webView.applyTheme(theme: currentTheme()) - } - readerModeCache = tab.isPrivate ? MemoryReaderModeCache.sharedInstance : DiskReaderModeCache.sharedInstance if let privateModeButton = topTabsViewController?.privateModeButton, previous != nil && previous?.isPrivate != tab.isPrivate { From 40c06d9f671df6d0d70555811efeeeaa50ac943f Mon Sep 17 00:00:00 2001 From: Clare So <1740517+clarmso@users.noreply.github.com> Date: Wed, 31 Jul 2024 11:03:31 -0400 Subject: [PATCH 020/128] Bugfix FXIOS-9633 Login page for sync integration tests (#21360) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Ensure the password page is loaded * 🈳 Empty commit --- .../firefox-ios-tests/Tests/XCUITests/IntegrationTests.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/IntegrationTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/IntegrationTests.swift index 79d2ef4fab06..5ed7daf407ae 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/IntegrationTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/IntegrationTests.swift @@ -63,9 +63,10 @@ class IntegrationTests: BaseTestCase { userState.fxaPassword = ProcessInfo.processInfo.environment["FXA_PASSWORD"]! navigator.performAction(Action.FxATypeEmail) navigator.performAction(Action.FxATapOnContinueButton) + mozWaitForElementToExist(app.staticTexts["Enter your password"], timeout: TIMEOUT_LONG) navigator.performAction(Action.FxATypePasswordExistingAccount) navigator.performAction(Action.FxATapOnSignInButton) - sleep(3) + mozWaitForElementToNotExist(app.staticTexts["Enter your password"], timeout: TIMEOUT_LONG) waitForTabsButton() allowNotifications() } From 3292de3e78b90d15b0bb7d082d29a47756c5c6e1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 31 Jul 2024 18:41:34 +0300 Subject: [PATCH 021/128] Auto update SPM with latest rust-component release 130.0.20240731050243 (#21374) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- firefox-ios/Client.xcodeproj/project.pbxproj | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- focus-ios/Blockzilla.xcodeproj/project.pbxproj | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/firefox-ios/Client.xcodeproj/project.pbxproj b/firefox-ios/Client.xcodeproj/project.pbxproj index 7e98218741a9..b66e0206d3af 100644 --- a/firefox-ios/Client.xcodeproj/project.pbxproj +++ b/firefox-ios/Client.xcodeproj/project.pbxproj @@ -23063,7 +23063,7 @@ repositoryURL = "https://github.com/mozilla/rust-components-swift.git"; requirement = { kind = exactVersion; - version = 130.0.20240730050414; + version = 130.0.20240731050243; }; }; 435C85EE2788F4D00072B526 /* XCRemoteSwiftPackageReference "glean-swift" */ = { diff --git a/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 3708ec8aca51..927a6d85cc32 100644 --- a/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -95,8 +95,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/mozilla/rust-components-swift.git", "state" : { - "revision" : "6981abbeee54a4bc1f5300e0023e5621fd53b8d1", - "version" : "130.0.20240730050414" + "revision" : "f1cdc3f52f87f69ffd408eacd79543ee3b50a83d", + "version" : "130.0.20240731050243" } }, { diff --git a/focus-ios/Blockzilla.xcodeproj/project.pbxproj b/focus-ios/Blockzilla.xcodeproj/project.pbxproj index 4c13e5c80984..7ca0abc7068f 100644 --- a/focus-ios/Blockzilla.xcodeproj/project.pbxproj +++ b/focus-ios/Blockzilla.xcodeproj/project.pbxproj @@ -7159,7 +7159,7 @@ repositoryURL = "https://github.com/mozilla/rust-components-swift"; requirement = { kind = exactVersion; - version = 130.0.20240730050414; + version = 130.0.20240731050243; }; }; 8A0E7F2C2BA0F0E0006BC6B6 /* XCRemoteSwiftPackageReference "Fuzi" */ = { diff --git a/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index a2d6aaac14d4..354cb5b8866e 100644 --- a/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -51,8 +51,8 @@ "repositoryURL": "https://github.com/mozilla/rust-components-swift", "state": { "branch": null, - "revision": "6981abbeee54a4bc1f5300e0023e5621fd53b8d1", - "version": "130.0.20240730050414" + "revision": "f1cdc3f52f87f69ffd408eacd79543ee3b50a83d", + "version": "130.0.20240731050243" } }, { From ca0696e8a1a3a598468cdb80f94443481110c828 Mon Sep 17 00:00:00 2001 From: Clare So <1740517+clarmso@users.noreply.github.com> Date: Wed, 31 Jul 2024 17:48:03 -0400 Subject: [PATCH 022/128] Refactor MTE-3146 (#21339) * cherry pick changes * Cherry pick changes * Accommodate other launchArguments * Try to resolve "cannot go from to " errors * Ensure parts of the app is visible :-/ * Remove the new setUp() * Put back changes in package.resolved * Put back old version of rush * Fix FormattingTest errors * Fix syntax errors * Swiftlint --- .github/workflows/firefox-ios-ui-tests.yml | 180 +++++++++--------- .../Tests/XCUITests/ActivityStreamTest.swift | 68 +++---- .../Tests/XCUITests/AuthenticationTest.swift | 10 +- .../Tests/XCUITests/BaseTestCase.swift | 30 ++- .../Tests/XCUITests/BookmarksTests.swift | 47 ++--- .../Tests/XCUITests/BrowsingPDFTests.swift | 8 +- .../Tests/XCUITests/ClipBoardTests.swift | 2 +- .../Tests/XCUITests/CreditCardsTests.swift | 64 ++++--- .../Tests/XCUITests/DataManagementTests.swift | 12 +- .../Tests/XCUITests/DesktopModeTests.swift | 4 +- .../XCUITests/DisplaySettingsTests.swift | 23 ++- .../Tests/XCUITests/DownloadsTests.swift | 40 ++-- .../Tests/XCUITests/DragAndDropTests.swift | 4 +- .../Tests/XCUITests/FindInPageTests.swift | 44 ++--- .../Tests/XCUITests/FxScreenGraph.swift | 2 +- .../Tests/XCUITests/HistoryTests.swift | 104 +++++----- .../Tests/XCUITests/HomeButtonTests.swift | 10 +- .../XCUITests/HomePageSettingsUITest.swift | 65 +++---- .../Tests/XCUITests/IntegrationTests.swift | 42 ++-- .../Tests/XCUITests/JumpBackInTests.swift | 7 +- .../Tests/XCUITests/LoginsTests.swift | 76 ++++---- .../Tests/XCUITests/MicrosurveyTests.swift | 26 +-- .../Tests/XCUITests/NavigationTest.swift | 80 ++++---- .../Tests/XCUITests/NewTabSettings.swift | 29 +-- .../Tests/XCUITests/OnboardingTests.swift | 40 ++-- .../Tests/XCUITests/OpeningScreenTests.swift | 6 + .../Tests/XCUITests/PerformanceTests.swift | 58 +++--- .../XCUITests/PhotonActionSheetTests.swift | 22 +-- .../Tests/XCUITests/PrivateBrowsingTest.swift | 41 ++-- .../Tests/XCUITests/ReadingListTests.swift | 27 ++- .../Tests/XCUITests/ReportSiteTests.swift | 4 +- .../Tests/XCUITests/SearchTest.swift | 37 ++-- .../Tests/XCUITests/SettingsTests.swift | 7 +- .../Tests/XCUITests/SyncFAUITests.swift | 27 +-- .../Tests/XCUITests/TabCounterTests.swift | 8 +- .../XCUITests/ThirdPartySearchTest.swift | 18 +- .../Tests/XCUITests/ToolbarMenuTests.swift | 23 ++- .../Tests/XCUITests/TopTabsTest.swift | 61 +++--- .../XCUITests/TrackingProtectionTests.swift | 41 ++-- 39 files changed, 708 insertions(+), 689 deletions(-) diff --git a/.github/workflows/firefox-ios-ui-tests.yml b/.github/workflows/firefox-ios-ui-tests.yml index 3b71fc9270ca..b3fe346fa308 100644 --- a/.github/workflows/firefox-ios-ui-tests.yml +++ b/.github/workflows/firefox-ios-ui-tests.yml @@ -40,7 +40,8 @@ jobs: -scheme ${{ env.xcodebuild_scheme }} \ -target ${{ env.xcodebuild_target }} \ -derivedDataPath ~/DerivedData \ - -destination 'platform=iOS Simulator,name=${{ env.ios_simulator_default }},OS=${{ env.ios_version }}' + -destination 'platform=iOS Simulator,name=${{ env.ios_simulator_default }},OS=${{ env.ios_version }}' \ + COMPILER_INDEX_STORE_ENABLE=NO CODE_SIGN_IDENTITY= CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO ARCHS="arm64" working-directory: ${{ env.browser }} - name: Compress Derived Data id: compress-dd @@ -61,7 +62,7 @@ jobs: strategy: fail-fast: false matrix: - ios_simulator: ['iPhone 15 Plus'] + ios_simulator: ['iPhone 15 Plus', 'iPad Pro 13-inch (M4)'] steps: - name: Check out source code uses: actions/checkout@v4.1.7 @@ -70,7 +71,7 @@ jobs: run: | gem install xcpretty -v 0.3.0 pip install blockkit==1.9.1 - npm install -g junit-report-merger@7.0.0 + npm install -g junit-report-merger@7.0.0 - name: Setup Xcode id: xcode run: | @@ -99,7 +100,7 @@ jobs: -destination 'platform=iOS Simulator,name=${{ matrix.ios_simulator }},OS=${{ env.ios_version }}' \ -testPlan Smoketest1 \ -resultBundlePath ${{ env.test_results_directory }}/results-smoketest1 \ - | tee xcodebuild.log | xcpretty -r junit --output ./junit-smoketest1.xml && exit ${PIPESTATUS[0]} + | tee xcodebuild-smoketest1.log | xcpretty -r junit --output ./junit-smoketest1.xml && exit ${PIPESTATUS[0]} working-directory: ${{ env.browser }} continue-on-error: true - name: Run Smoketest2 @@ -113,7 +114,7 @@ jobs: -destination 'platform=iOS Simulator,name=${{ matrix.ios_simulator }},OS=${{ env.ios_version }}' \ -testPlan Smoketest2 \ -resultBundlePath ${{ env.test_results_directory }}/results-smoketest2 \ - | tee xcodebuild.log | xcpretty -r junit --output ./junit-smoketest2.xml && exit ${PIPESTATUS[0]} + | tee xcodebuild-smoketest2.log | xcpretty -r junit --output ./junit-smoketest2.xml && exit ${PIPESTATUS[0]} working-directory: ${{ env.browser }} continue-on-error: true - name: Run Smoketest3 @@ -127,7 +128,7 @@ jobs: -destination 'platform=iOS Simulator,name=${{ matrix.ios_simulator }},OS=${{ env.ios_version }}' \ -testPlan Smoketest3 \ -resultBundlePath ${{ env.test_results_directory }}/results-smoketest3 \ - | tee xcodebuild.log | xcpretty -r junit --output ./junit-smoketest3.xml && exit ${PIPESTATUS[0]} + | tee xcodebuild-smoketest3.log | xcpretty -r junit --output ./junit-smoketest3.xml && exit ${PIPESTATUS[0]} working-directory: ${{ env.browser }} continue-on-error: true - name: Run Smoketest4 @@ -141,7 +142,7 @@ jobs: -destination 'platform=iOS Simulator,name=${{ matrix.ios_simulator }},OS=${{ env.ios_version }}' \ -testPlan Smoketest4 \ -resultBundlePath ${{ env.test_results_directory }}/results-smoketest4 \ - | tee xcodebuild.log | xcpretty -r junit --output ./junit-smoketest4.xml && exit ${PIPESTATUS[0]} + | tee xcodebuild-smoketest4.log | xcpretty -r junit --output ./junit-smoketest4.xml && exit ${PIPESTATUS[0]} working-directory: ${{ env.browser }} continue-on-error: true - name: Determine pass/fail status @@ -167,20 +168,21 @@ jobs: python ../test-fixtures/ci/convert_junit_to_markdown.py --smoke --github --${{ env.browser }} ./combined.xml ./github.md cat github.md >> $GITHUB_STEP_SUMMARY python ../test-fixtures/ci/convert_junit_to_markdown.py --smoke --slack --${{ env.browser }} ./combined.xml ./slack.json + mv ./combined junit-smoketests-${{ matrix.ios_simulator }}-`date +"%Y-%m-%d"`.xml working-directory: ${{ env.browser }} - name: Upload junit files id: upload-junit uses: actions/upload-artifact@v4.3.3 with: name: ${{ env.browser }}-smoketests-${{ matrix.ios_simulator }}-junit-${{ github.run_number }} - path: ${{ env.browser }}/junit-*.xml + path: ${{ env.browser }}/junit-smoketests-*.xml retention-days: 90 - name: Upload log file id: upload-log uses: actions/upload-artifact@v4.3.3 with: name: ${{ env.browser }}-smoketests-${{ matrix.ios_simulator }}-xcodebuildlog-${{ github.run_number }} - path: ${{ env.browser }}/xcodebuild.log + path: ${{ env.browser }}/xcodebuild-smoketest*.log retention-days: 90 - name: Report to Slack id: slack @@ -203,81 +205,85 @@ jobs: exit ${{ steps.passfail.outcome == 'success' && '0' || '1' }} run-fullfunctionaltests: - name: Run full functional tests - runs-on: macos-14 - needs: compile - strategy: - fail-fast: false - matrix: - ios_simulator: ['iPhone 15 Plus'] - steps: - - name: Check out source code - uses: actions/checkout@v4.1.7 - - name: Install packages - id: packages - run: | - gem install xcpretty -v 0.3.0 - pip install blockkit==1.9.1 - - name: Get derived data - id: download-derived-data - uses: actions/download-artifact@v4 - with: - name: xcode-cache-deriveddata-${{ github.workflow }}-${{ github.sha }} - - name: Decompress derived data - id: decompress-dd - run: | - tar xzf derived-data.tar.gz -C / - - name: Run tests - id: run-tests - run: | - xcodebuild \ - test-without-building \ - -scheme ${{ env.xcodebuild_scheme }} \ - -target ${{ env.xcodebuild_target }} \ - -derivedDataPath ~/DerivedData \ - -destination 'platform=iOS Simulator,name=${{ matrix.ios_simulator }},OS=${{ env.ios_version }}' \ - -testPlan FullFunctionalTestPlan \ - -resultBundlePath ${{ env.test_results_directory }}/results \ - | tee xcodebuild.log | xcpretty -r junit && exit ${PIPESTATUS[0]} - working-directory: ${{ env.browser }} - continue-on-error: true - - name: Print test report - id: test-report - run: | - python ../test-fixtures/ci/convert_junit_to_markdown.py --github --${{ env.browser }} ./build/reports/junit.xml ./github.md - cat github.md >> $GITHUB_STEP_SUMMARY - python ../test-fixtures/ci/convert_junit_to_markdown.py --slack --${{ env.browser }} ./build/reports/junit.xml ./slack.json - working-directory: ${{ env.browser }} - - name: Upload junit files - id: upload-junit - uses: actions/upload-artifact@v4.3.3 - with: - name: ${{ env.browser }}-fullfunctional-${{ matrix.ios_simulator }}-junit-${{ github.run_number }} - path: ${{ env.browser }}/junit-*.xml - retention-days: 90 - - name: Upload log file - id: upload-log - uses: actions/upload-artifact@v4.3.3 - with: - name: ${{ env.browser }}-fullfunctional-${{ matrix.ios_simulator }}-xcodebuildlog-${{ github.run_number }} - path: ${{ env.browser }}/xcodebuild.log - retention-days: 90 - - name: Report to Slack - id: slack - uses: slackapi/slack-github-action@v1.26.0 - with: - payload-file-path: ${{ env.browser }}/slack.json - env: - SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} - SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK - ios_simulator: ${{ matrix.ios_simulator }} - pass_fail: ${{ steps.run-tests.outcome == 'success' && ':white_check_mark:' || ':x:' }} - xcodebuild_test_plan: FullFunctionalTestPlan - ref_name: ${{ github.ref_name }} - repository: ${{ github.repository }} - run_id: ${{ github.run_id }} - server_url: ${{ github.server_url }} - sha: ${{ github.sha }} - - name: Return fail status if a test fails - run: | - exit ${{ steps.run-tests.outcome == 'success' && '0' || '1' }} \ No newline at end of file + name: Run full functional tests + runs-on: macos-14 + needs: compile + strategy: + fail-fast: false + matrix: + ios_simulator: ['iPhone 15 Pro Max'] + steps: + - name: Check out source code + uses: actions/checkout@v4.1.7 + - name: Install packages + id: packages + run: | + gem install xcpretty -v 0.3.0 + pip install blockkit==1.9.1 + - name: Get derived data + id: download-derived-data + uses: actions/download-artifact@v4 + with: + name: xcode-cache-deriveddata-${{ github.workflow }}-${{ github.sha }} + - name: Decompress derived data + id: decompress-dd + run: | + tar xzf derived-data.tar.gz -C / + - name: Run tests + id: run-tests + run: | + xcrun simctl shutdown all + xcrun simctl erase all + xcrun simctl boot '${{ matrix.ios_simulator }}' + xcodebuild \ + test-without-building \ + -scheme ${{ env.xcodebuild_scheme }} \ + -target ${{ env.xcodebuild_target }} \ + -derivedDataPath ~/DerivedData \ + -destination 'platform=iOS Simulator,name=${{ matrix.ios_simulator }},OS=${{ env.ios_version }}' \ + -testPlan FullFunctionalTestPlan \ + -resultBundlePath ${{ env.test_results_directory }}/results \ + | tee xcodebuild.log | xcpretty -r junit && exit ${PIPESTATUS[0]} + working-directory: ${{ env.browser }} + continue-on-error: true + - name: Print test report + id: test-report + run: | + python ../test-fixtures/ci/convert_junit_to_markdown.py --github --${{ env.browser }} ./build/reports/junit.xml ./github.md + cat github.md >> $GITHUB_STEP_SUMMARY + python ../test-fixtures/ci/convert_junit_to_markdown.py --slack --${{ env.browser }} ./build/reports/junit.xml ./slack.json + mv ./build/reports/junit.xml junit-fullfunctional-${{ matrix.ios_simulator }}-`date +"%Y-%m-%d"`.xml + working-directory: ${{ env.browser }} + - name: Upload junit files + id: upload-junit + uses: actions/upload-artifact@v4.3.3 + with: + name: ${{ env.browser }}-fullfunctional-${{ matrix.ios_simulator }}-junit-${{ github.run_number }} + path: ${{ env.browser }}/junit-*.xml + retention-days: 90 + - name: Upload log file + id: upload-log + uses: actions/upload-artifact@v4.3.3 + with: + name: ${{ env.browser }}-fullfunctional-${{ matrix.ios_simulator }}-xcodebuildlog-${{ github.run_number }} + path: ${{ env.browser }}/xcodebuild.log + retention-days: 90 + - name: Report to Slack + id: slack + uses: slackapi/slack-github-action@v1.26.0 + with: + payload-file-path: ${{ env.browser }}/slack.json + env: + SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} + SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK + ios_simulator: ${{ matrix.ios_simulator }} + pass_fail: ${{ steps.run-tests.outcome == 'success' && ':white_check_mark:' || ':x:' }} + xcodebuild_test_plan: FullFunctionalTestPlan + ref_name: ${{ github.ref_name }} + repository: ${{ github.repository }} + run_id: ${{ github.run_id }} + server_url: ${{ github.server_url }} + sha: ${{ github.sha }} + - name: Return fail status if a test fails + run: | + exit ${{ steps.run-tests.outcome == 'success' && '0' || '1' }} \ No newline at end of file diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/ActivityStreamTest.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/ActivityStreamTest.swift index 0f715fe260b1..b9a23c9242ce 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/ActivityStreamTest.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/ActivityStreamTest.swift @@ -47,17 +47,17 @@ class ActivityStreamTest: BaseTestCase { // Smoketest func testDefaultSites() throws { XCTExpectFailure("The app was not launched", strict: false) { - waitForExistence(TopSiteCellgroup, timeout: 60) + waitForExistence(TopSiteCellgroup, timeout: TIMEOUT_LONG) } - XCTAssertTrue(app.collectionViews[AccessibilityIdentifiers.FirefoxHomepage.collectionView].exists) + mozWaitForElementToExist(app.collectionViews[AccessibilityIdentifiers.FirefoxHomepage.collectionView]) // There should be 5 top sites by default checkNumberOfExpectedTopSites(numberOfExpectedTopSites: 5) // Check their names so that test is added to Smoketest - XCTAssertTrue(app.collectionViews.cells.staticTexts["Twitter"].exists) - XCTAssertTrue(app.collectionViews.cells.staticTexts["Amazon"].exists) - XCTAssertTrue(app.collectionViews.cells.staticTexts["Wikipedia"].exists) - XCTAssertTrue(app.collectionViews.cells.staticTexts["YouTube"].exists) - XCTAssertTrue(app.collectionViews.cells.staticTexts["Facebook"].exists) + mozWaitForElementToExist(app.collectionViews.cells.staticTexts["Twitter"]) + mozWaitForElementToExist(app.collectionViews.cells.staticTexts["Amazon"]) + mozWaitForElementToExist(app.collectionViews.cells.staticTexts["Wikipedia"]) + mozWaitForElementToExist(app.collectionViews.cells.staticTexts["YouTube"]) + mozWaitForElementToExist(app.collectionViews.cells.staticTexts["Facebook"]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2272218 @@ -71,8 +71,7 @@ class ActivityStreamTest: BaseTestCase { // https://testrail.stage.mozaws.net/index.php?/cases/view/2272219 func testTopSitesRemoveAllExceptDefaultClearPrivateData() { - waitForExistence(app.cells.staticTexts[newTopSite["bookmarkLabel"]!], timeout: 15) - XCTAssertTrue(app.cells.staticTexts[newTopSite["bookmarkLabel"]!].exists) + waitForExistence(app.cells.staticTexts[newTopSite["bookmarkLabel"]!], timeout: TIMEOUT_LONG) // A new site has been added to the top sites if iPad() { checkNumberOfExpectedTopSites(numberOfExpectedTopSites: 12) @@ -89,12 +88,12 @@ class ActivityStreamTest: BaseTestCase { navigator.goto(HomePanelsScreen) } checkNumberOfExpectedTopSites(numberOfExpectedTopSites: 5) - XCTAssertFalse(app.cells.staticTexts[newTopSite["bookmarkLabel"]!].exists) + mozWaitForElementToNotExist(app.cells.staticTexts[newTopSite["bookmarkLabel"]!]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2272220 func testTopSitesRemoveAllExceptPinnedClearPrivateData() { - waitForExistence(TopSiteCellgroup, timeout: TIMEOUT) + waitForExistence(TopSiteCellgroup) if iPad() { app.textFields.element(boundBy: 0).tap() app.typeText("mozilla.org\n") @@ -112,16 +111,14 @@ class ActivityStreamTest: BaseTestCase { navigator.performAction(Action.OpenNewTabFromTabTray) let topSitesCells = app.collectionViews.cells["TopSitesCell"] - waitForExistence(topSitesCells.staticTexts[newTopSite["bookmarkLabel"]!], timeout: TIMEOUT) - XCTAssertTrue(topSitesCells.staticTexts[newTopSite["bookmarkLabel"]!].exists) + waitForExistence(topSitesCells.staticTexts[newTopSite["bookmarkLabel"]!], timeout: TIMEOUT_LONG) checkNumberOfExpectedTopSites(numberOfExpectedTopSites: 6) topSitesCells.staticTexts[newTopSite["bookmarkLabel"]!].press(forDuration: 1) selectOptionFromContextMenu(option: "Pin") - waitForExistence(topSitesCells.staticTexts[newTopSite["bookmarkLabel"]!], timeout: TIMEOUT) - XCTAssertTrue(topSitesCells.staticTexts[newTopSite["bookmarkLabel"]!].exists) + waitForExistence(topSitesCells.staticTexts[newTopSite["bookmarkLabel"]!], timeout: TIMEOUT_LONG) - waitForExistence(app.buttons["urlBar-cancel"], timeout: TIMEOUT) + waitForExistence(app.buttons["urlBar-cancel"]) navigator.performAction(Action.CloseURLBarOpen) navigator.nowAt(NewTabScreen) navigator.goto(SettingsScreen) @@ -129,7 +126,6 @@ class ActivityStreamTest: BaseTestCase { navigator.performAction(Action.AcceptClearPrivateData) navigator.goto(HomePanelsScreen) waitForExistence(topSitesCells.staticTexts[newTopSite["bookmarkLabel"]!]) - XCTAssertTrue(topSitesCells.staticTexts[newTopSite["bookmarkLabel"]!].exists) checkNumberOfExpectedTopSites(numberOfExpectedTopSites: 6) } @@ -140,11 +136,12 @@ class ActivityStreamTest: BaseTestCase { let topSiteFirstCell = allTopSites.element(boundBy: 0).label let topSiteSecondCell = allTopSites.element(boundBy: 1).label + mozWaitForElementToExist(allTopSites.firstMatch) XCTAssertTrue(topSiteFirstCell == allDefaultTopSites[0]) XCTAssertTrue(topSiteSecondCell == allDefaultTopSites[1]) // Remove facebook top sites, first cell - waitForExistence(allTopSites.element(boundBy: 0), timeout: TIMEOUT) + waitForExistence(allTopSites.element(boundBy: 0)) allTopSites.element(boundBy: 0).press(forDuration: 1) selectOptionFromContextMenu(option: "Remove") @@ -155,6 +152,7 @@ class ActivityStreamTest: BaseTestCase { waitForExistence(updatedAllTopSites.element(boundBy: 0)) let topSiteCells = updatedAllTopSites.staticTexts let topSiteFirstCellAfter = updatedAllTopSites.element(boundBy: 0).label + mozWaitForElementToExist(updatedAllTopSites.element(boundBy: 0)) XCTAssertTrue( topSiteFirstCellAfter == topSiteCells[allDefaultTopSites[1]].label, "First top site does not match" @@ -165,41 +163,41 @@ class ActivityStreamTest: BaseTestCase { // Smoketest func testTopSitesOpenInNewPrivateTab() throws { XCTExpectFailure("The app was not launched", strict: false) { - waitForExistence(TopSiteCellgroup, timeout: 60) + waitForExistence(TopSiteCellgroup, timeout: TIMEOUT_LONG) } - waitForExistence(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton], timeout: 5) + waitForExistence(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton]) // Long tap on Wikipedia top site - waitForExistence(app.collectionViews.cells.staticTexts["Wikipedia"], timeout: 3) + waitForExistence(app.collectionViews.cells.staticTexts["Wikipedia"]) app.collectionViews.cells.staticTexts["Wikipedia"].press(forDuration: 1) + mozWaitForElementToExist(app.tables["Context Menu"].cells.otherElements["Open in a Private Tab"]) app.tables["Context Menu"].cells.otherElements["Open in a Private Tab"].tap() - XCTAssert(TopSiteCellgroup.exists) + mozWaitForElementToExist(TopSiteCellgroup) navigator.toggleOn(userState.isPrivate, withAction: Action.TogglePrivateMode) navigator.goto(TabTray) - waitForExistence(app.cells.staticTexts.element(boundBy: 0), timeout: 10) + waitForExistence(app.cells.staticTexts.element(boundBy: 0)) navigator.nowAt(TabTray) - waitForExistence(app.otherElements["Tabs Tray"].collectionViews.cells["Wikipedia"], timeout: TIMEOUT) + waitForExistence(app.otherElements["Tabs Tray"].collectionViews.cells["Wikipedia"]) app.otherElements["Tabs Tray"].collectionViews.cells["Wikipedia"].tap() // The website is open - XCTAssertFalse(TopSiteCellgroup.exists) - XCTAssertTrue(app.textFields["url"].exists) + mozWaitForElementToNotExist(TopSiteCellgroup) waitForValueContains(app.textFields["url"], value: "wikipedia.org") } // Smoketest func testTopSitesOpenInNewPrivateTabDefaultTopSite() { XCTExpectFailure("The app was not launched", strict: false) { - waitForExistence(TopSiteCellgroup, timeout: 60) + waitForExistence(TopSiteCellgroup, timeout: TIMEOUT_LONG) } - waitForExistence(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton], timeout: 5) + waitForExistence(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton]) navigator.nowAt(NewTabScreen) // Open one of the sites from Topsites and wait until page is loaded // Long tap on apple top site, second cell waitForExistence(app.collectionViews["FxCollectionView"].cells - .staticTexts[defaultTopSite["bookmarkLabel"]!], timeout: 3) + .staticTexts[defaultTopSite["bookmarkLabel"]!]) app.collectionViews["FxCollectionView"].cells.staticTexts[defaultTopSite["bookmarkLabel"]!].press(forDuration: 1) selectOptionFromContextMenu(option: "Open in a Private Tab") @@ -216,14 +214,18 @@ class ActivityStreamTest: BaseTestCase { if iPad() { navigator.goto(TabTray) numTabsOpen = app.otherElements["Tabs Tray"].collectionViews.cells.count + waitForExistence(app.otherElements["Tabs Tray"].collectionViews.cells.firstMatch) + } else { + waitForExistence(app.collectionViews.element(boundBy: 1).cells.firstMatch) } XCTAssertEqual(numTabsOpen, 1, "New tab not open") } private func checkNumberOfExpectedTopSites(numberOfExpectedTopSites: Int) { - waitForExistence(app.cells[TopSites.itemCell]) - XCTAssertTrue(app.cells[TopSites.itemCell].exists) + mozWaitForElementToExist(app.cells[TopSites.itemCell]) + mozWaitForElementToExist(app.cells[TopSites.itemCell]) let numberOfTopSites = app.collectionViews.cells.matching(identifier: TopSites.itemCell).count + mozWaitForElementToExist(app.collectionViews.cells.matching(identifier: TopSites.itemCell).firstMatch) XCTAssertEqual(numberOfTopSites, numberOfExpectedTopSites, "The number of Top Sites is not correct") } @@ -233,8 +235,10 @@ class ActivityStreamTest: BaseTestCase { // can't scroll only to that area. Needs investigation if iPad() { XCUIDevice.shared.orientation = .landscapeLeft - waitForExistence(TopSiteCellgroup, timeout: TIMEOUT) + waitForExistence(TopSiteCellgroup) app.collectionViews.cells.staticTexts["Wikipedia"].press(forDuration: 1) + mozWaitForElementToExist(app.tables["Context Menu"]) + mozWaitForElementToExist(app.otherElements["Action Sheet"]) let contextMenuHeight = app.tables["Context Menu"].frame.size.height let parentViewHeight = app.otherElements["Action Sheet"].frame.size.height diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/AuthenticationTest.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/AuthenticationTest.swift index b7782dcf8b42..83754eb1ad07 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/AuthenticationTest.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/AuthenticationTest.swift @@ -9,7 +9,7 @@ let testBasicHTTPAuthURL = "https://jigsaw.w3.org/HTTP/Basic/" class AuthenticationTest: BaseTestCase { // https://testrail.stage.mozaws.net/index.php?/cases/view/2360560 func testBasicHTTPAuthenticationPromptVisible() { - mozWaitForElementToExist(app.textFields["url"], timeout: 5) + mozWaitForElementToExist(app.textFields["url"]) navigator.nowAt(NewTabScreen) navigator.openURL(testBasicHTTPAuthURL) mozWaitForElementToExist(app.staticTexts["Authentication required"], timeout: 100) @@ -17,11 +17,11 @@ class AuthenticationTest: BaseTestCase { "A username and password are being requested by jigsaw.w3.org. The site says: test" ]) - let placeholderValueUsername = app.alerts.textFields.element(boundBy: 0).value as! String - let placeholderValuePassword = app.alerts.secureTextFields.element(boundBy: 0).value as! String + let placeholderValueUsername = app.alerts.textFields.element(boundBy: 0) + let placeholderValuePassword = app.alerts.secureTextFields.element(boundBy: 0) - XCTAssertEqual(placeholderValueUsername, "Username") - XCTAssertEqual(placeholderValuePassword, "Password") + mozWaitForValueContains(placeholderValueUsername, value: "Username") + mozWaitForValueContains(placeholderValuePassword, value: "Password") mozWaitForElementToExist(app.alerts.buttons["Cancel"]) mozWaitForElementToExist(app.alerts.buttons["Log in"]) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/BaseTestCase.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/BaseTestCase.swift index 34cc121b115f..13d36abd3120 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/BaseTestCase.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/BaseTestCase.swift @@ -15,7 +15,7 @@ func path(forTestPage page: String) -> String { } // Extended timeout values for mozWaitForElementToExist and mozWaitForElementToNotExist -let TIMEOUT: TimeInterval = 15 +let TIMEOUT: TimeInterval = 20 let TIMEOUT_LONG: TimeInterval = 45 class BaseTestCase: XCTestCase { @@ -47,7 +47,7 @@ class BaseTestCase: XCTestCase { // Let's be sure the app is backgrounded _ = app.wait(for: XCUIApplication.State.runningBackgroundSuspended, timeout: TIMEOUT) let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard") - mozWaitForElementToExist(springboard.icons["XCUITests-Runner"], timeout: 10) + mozWaitForElementToExist(springboard.icons["XCUITests-Runner"]) app.activate() } @@ -57,7 +57,7 @@ class BaseTestCase: XCTestCase { sleep(2) swipeStart.press(forDuration: 0.1, thenDragTo: swipeEnd) let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard") - mozWaitForElementToExist(springboard.icons["XCUITests-Runner"], timeout: 10) + mozWaitForElementToExist(springboard.icons["XCUITests-Runner"]) app.activate() } @@ -101,6 +101,8 @@ class BaseTestCase: XCTestCase { continueAfterFailure = false setUpApp() setUpScreenGraph() + + mozWaitForElementToExist(app.windows.otherElements.firstMatch) } override func tearDown() { @@ -140,7 +142,7 @@ class BaseTestCase: XCTestCase { func waitForExistence( _ element: XCUIElement, - timeout: TimeInterval = 5.0, + timeout: TimeInterval = TIMEOUT, file: String = #file, line: UInt = #line ) { @@ -162,7 +164,7 @@ class BaseTestCase: XCTestCase { func waitForNoExistence( _ element: XCUIElement, - timeoutValue: TimeInterval = 5.0, + timeoutValue: TimeInterval = TIMEOUT, file: String = #file, line: UInt = #line ) { @@ -204,7 +206,7 @@ class BaseTestCase: XCTestCase { _ element: XCUIElement, with predicateString: String, description: String? = nil, - timeout: TimeInterval = 5.0, + timeout: TimeInterval = TIMEOUT, file: String, line: UInt ) { @@ -260,6 +262,8 @@ class BaseTestCase: XCTestCase { .otherElements .count let numberOfExpectedRecentlyVisitedBookmarks = 2 + mozWaitForElementToExist(app.scrollViews + .cells[AccessibilityIdentifiers.FirefoxHomepage.Bookmarks.itemCell].firstMatch) XCTAssertEqual(numberOfRecentlyVisitedBookmarks, numberOfExpectedRecentlyVisitedBookmarks) } @@ -273,6 +277,8 @@ class BaseTestCase: XCTestCase { .otherElements .count let numberOfExpectedRecentlyVisitedBookmarks = 1 + mozWaitForElementToExist(app.scrollViews + .cells[AccessibilityIdentifiers.FirefoxHomepage.Bookmarks.itemCell].firstMatch) XCTAssertEqual(numberOfRecentlyVisitedBookmarks, numberOfExpectedRecentlyVisitedBookmarks) } @@ -287,7 +293,7 @@ class BaseTestCase: XCTestCase { userState.url = path(forTestPage: "test-mozilla-book.html") navigator.openURL(path(forTestPage: "test-mozilla-book.html")) waitUntilPageLoad() - mozWaitForElementToExist(app.buttons["Reader View"], timeout: TIMEOUT) + mozWaitForElementToExist(app.buttons["Reader View"]) app.buttons["Reader View"].tap() waitUntilPageLoad() mozWaitForElementToExist(app.buttons["Add to Reading List"]) @@ -307,7 +313,7 @@ class BaseTestCase: XCTestCase { } func selectOptionFromContextMenu(option: String) { - XCTAssertTrue(app.tables["Context Menu"].cells.otherElements[option].exists) + mozWaitForElementToExist(app.tables["Context Menu"].cells.otherElements[option]) app.tables["Context Menu"].cells.otherElements[option].tap() mozWaitForElementToNotExist(app.tables["Context Menu"]) } @@ -345,7 +351,7 @@ class BaseTestCase: XCTestCase { } func waitForTabsButton() { - mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton], timeout: TIMEOUT) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton]) } func unlockLoginsView() { @@ -355,7 +361,7 @@ class BaseTestCase: XCTestCase { } let passcodeInput = springboard.otherElements.secureTextFields.firstMatch - mozWaitForElementToExist(passcodeInput, timeout: 20) + mozWaitForElementToExist(passcodeInput) passcodeInput.tap() passcodeInput.typeText("foo\n") mozWaitForElementToNotExist(passcodeInput) @@ -402,6 +408,8 @@ class IpadOnlyTestCase: BaseTestCase { specificForPlatform = .pad if iPad() { super.setUp() + waitForTabsButton() + mozWaitForElementToExist(app.textFields["url"]) } } } @@ -411,6 +419,8 @@ class IphoneOnlyTestCase: BaseTestCase { specificForPlatform = .phone if !iPad() { super.setUp() + waitForTabsButton() + mozWaitForElementToExist(app.textFields["url"]) } } } diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/BookmarksTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/BookmarksTests.swift index 795bba38f189..5521b5e94974 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/BookmarksTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/BookmarksTests.swift @@ -27,7 +27,7 @@ class BookmarksTests: BaseTestCase { mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.bookmarkSlash]) app.otherElements[StandardImageIdentifiers.Large.bookmarkSlash].tap() navigator.nowAt(BrowserTab) - mozWaitForElementToExist(app.buttons["Undo"], timeout: 3) + mozWaitForElementToExist(app.buttons["Undo"]) app.buttons["Undo"].tap() } @@ -85,23 +85,23 @@ class BookmarksTests: BaseTestCase { } private func checkEmptyBookmarkList() { - mozWaitForElementToExist(app.tables["Bookmarks List"], timeout: 5) + mozWaitForElementToExist(app.tables["Bookmarks List"]) let list = app.tables["Bookmarks List"].cells.count XCTAssertEqual(list, 0, "There should not be any entry in the bookmarks list") } private func checkItemInBookmarkList(oneItemBookmarked: Bool) { - mozWaitForElementToExist(app.tables["Bookmarks List"], timeout: 5) + mozWaitForElementToExist(app.tables["Bookmarks List"]) let bookmarksList = app.tables["Bookmarks List"] let list = bookmarksList.cells.count if oneItemBookmarked == true { XCTAssertEqual(list, 2, "There should be an entry in the bookmarks list") - XCTAssertTrue(bookmarksList.cells.element(boundBy: 0).staticTexts["Desktop Bookmarks"].exists) - XCTAssertTrue(bookmarksList.cells.element(boundBy: 1).staticTexts[url_2["bookmarkLabel"]!].exists) + mozWaitForElementToExist(bookmarksList.cells.element(boundBy: 0).staticTexts["Desktop Bookmarks"]) + mozWaitForElementToExist(bookmarksList.cells.element(boundBy: 1).staticTexts[url_2["bookmarkLabel"]!]) } else { XCTAssertEqual(list, 3, "There should be an entry in the bookmarks list") - XCTAssertTrue(bookmarksList.cells.element(boundBy: 1).staticTexts[urlLabelExample_3].exists) - XCTAssertTrue(bookmarksList.cells.element(boundBy: 2).staticTexts[url_2["bookmarkLabel"]!].exists) + mozWaitForElementToExist(bookmarksList.cells.element(boundBy: 1).staticTexts[urlLabelExample_3]) + mozWaitForElementToExist(bookmarksList.cells.element(boundBy: 2).staticTexts[url_2["bookmarkLabel"]!]) } } @@ -112,7 +112,7 @@ class BookmarksTests: BaseTestCase { navigator.openURL(path(forTestPage: url_2["url"]!)) waitUntilPageLoad() navigator.nowAt(BrowserTab) - mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton], timeout: 10) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton]) bookmark() // There should be a bookmark @@ -124,12 +124,11 @@ class BookmarksTests: BaseTestCase { // Smoketest func testBookmarksAwesomeBar() { XCTExpectFailure("The app was not launched", strict: false) { - mozWaitForElementToExist(app.textFields["url"], timeout: 60) + mozWaitForElementToExist(app.textFields["url"], timeout: TIMEOUT_LONG) } typeOnSearchBar(text: "www.google") mozWaitForElementToExist(app.tables["SiteTable"]) - mozWaitForElementToExist(app.tables["SiteTable"].cells.staticTexts["www.google"], timeout: 5) - XCTAssertTrue(app.tables["SiteTable"].cells.staticTexts["www.google"].exists) + mozWaitForElementToExist(app.tables["SiteTable"].cells.staticTexts["www.google"]) app.textFields["address"].typeText(".com") app.textFields["address"].typeText("\r") navigator.nowAt(BrowserTab) @@ -152,7 +151,7 @@ class BookmarksTests: BaseTestCase { bookmark() // Now the site should be suggested - mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton], timeout: 10) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton]) navigator.performAction(Action.AcceptClearPrivateData) navigator.goto(BrowserTab) typeOnSearchBar(text: "mozilla.org") @@ -166,7 +165,7 @@ class BookmarksTests: BaseTestCase { addNewBookmark() // Verify that clicking on bookmark opens the website app.tables["Bookmarks List"].cells.element(boundBy: 1).tap() - mozWaitForElementToExist(app.textFields["url"], timeout: 5) + mozWaitForElementToExist(app.textFields["url"]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2306914 @@ -251,7 +250,7 @@ class BookmarksTests: BaseTestCase { navigator.goto(LibraryPanel_Bookmarks) navigator.nowAt(MobileBookmarks) navigator.performAction(Action.AddNewBookmark) - mozWaitForElementToExist(app.navigationBars["Bookmarks"], timeout: 3) + mozWaitForElementToExist(app.navigationBars["Bookmarks"]) // Enter the bookmarks details app.tables.cells.textFields.element(boundBy: 0).tap() app.tables.cells.textFields.element(boundBy: 0).typeText("BBC") @@ -265,12 +264,12 @@ class BookmarksTests: BaseTestCase { } private func checkItemsInBookmarksList(items: Int) { - mozWaitForElementToExist(app.tables["Bookmarks List"], timeout: 3) + mozWaitForElementToExist(app.tables["Bookmarks List"]) XCTAssertEqual(app.tables["Bookmarks List"].cells.count, items) } private func typeOnSearchBar(text: String) { - mozWaitForElementToExist(app.textFields["url"], timeout: 5) + mozWaitForElementToExist(app.textFields["url"]) app.textFields["url"].tap() app.textFields["address"].typeText(text) } @@ -280,13 +279,13 @@ class BookmarksTests: BaseTestCase { func testBookmarkLibraryAddDeleteBookmark() { // Verify that there are only 1 cell (desktop bookmark folder) XCTExpectFailure("The app was not launched", strict: false) { - mozWaitForElementToExist(app.textFields["url"], timeout: 60) + mozWaitForElementToExist(app.textFields["url"], timeout: TIMEOUT_LONG) } navigator.nowAt(NewTabScreen) waitForTabsButton() navigator.goto(LibraryPanel_Bookmarks) // There is only one row in the bookmarks panel, which is the desktop folder - mozWaitForElementToExist(app.tables["Bookmarks List"], timeout: 5) + mozWaitForElementToExist(app.tables["Bookmarks List"]) XCTAssertEqual(app.tables["Bookmarks List"].cells.count, 1) // Add a bookmark @@ -299,16 +298,12 @@ class BookmarksTests: BaseTestCase { // Check that it appears in Bookmarks panel navigator.goto(LibraryPanel_Bookmarks) - mozWaitForElementToExist(app.tables["Bookmarks List"], timeout: 5) + mozWaitForElementToExist(app.tables["Bookmarks List"]) // Delete the Bookmark added, check it is removed app.tables["Bookmarks List"].cells.staticTexts["Example Domain"].swipeLeft() app.buttons["Delete"].tap() - mozWaitForElementToNotExist(app.tables["Bookmarks List"].cells.staticTexts["Example Domain"], timeout: 10) - XCTAssertFalse( - app.tables["Bookmarks List"].cells.staticTexts["Example Domain"].exists, - "Bookmark not removed successfully" - ) + mozWaitForElementToNotExist(app.tables["Bookmarks List"].cells.staticTexts["Example Domain"]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2306910 @@ -319,12 +314,12 @@ class BookmarksTests: BaseTestCase { waitForTabsButton() navigator.goto(LibraryPanel_Bookmarks) // There is only one folder at the root of the bookmarks - mozWaitForElementToExist(app.tables["Bookmarks List"], timeout: 5) + mozWaitForElementToExist(app.tables["Bookmarks List"]) XCTAssertEqual(app.tables["Bookmarks List"].cells.count, 1) // There is only three folders inside the desktop bookmarks app.tables["Bookmarks List"].cells.firstMatch.tap() - mozWaitForElementToExist(app.tables["Bookmarks List"], timeout: 5) + mozWaitForElementToExist(app.tables["Bookmarks List"]) XCTAssertEqual(app.tables["Bookmarks List"].cells.count, 3) } diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/BrowsingPDFTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/BrowsingPDFTests.swift index a3e95c7ddf28..b7c0891f3736 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/BrowsingPDFTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/BrowsingPDFTests.swift @@ -75,7 +75,6 @@ class BrowsingPDFTests: BaseTestCase { navigator.goto(LibraryPanel_ReadingList) let savedToReadingList = app.tables["ReadingTable"].cells.staticTexts[PDF_website["longUrlValue"]!] mozWaitForElementToExist(savedToReadingList) - XCTAssertTrue(savedToReadingList.exists) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2307120 @@ -85,9 +84,8 @@ class BrowsingPDFTests: BaseTestCase { waitUntilPageLoad() navigator.performAction(Action.PinToTopSitesPAM) navigator.performAction(Action.OpenNewTabFromTabTray) - mozWaitForElementToExist(app.cells[AccessibilityIdentifiers.FirefoxHomepage.TopSites.itemCell], timeout: 10) + mozWaitForElementToExist(app.cells[AccessibilityIdentifiers.FirefoxHomepage.TopSites.itemCell]) mozWaitForElementToExist(app.collectionViews.cells.staticTexts[PDF_website["bookmarkLabel"]!]) - XCTAssertTrue(app.collectionViews.cells.staticTexts[PDF_website["bookmarkLabel"]!].exists) // Open pdf from pinned site let pdfTopSite = app @@ -108,7 +106,7 @@ class BrowsingPDFTests: BaseTestCase { mozWaitForElementToExist(app.tables.cells.otherElements[StandardImageIdentifiers.Large.pinSlash]) app.tables.cells.otherElements[StandardImageIdentifiers.Large.pinSlash].tap() mozWaitForElementToExist(app.cells[AccessibilityIdentifiers.FirefoxHomepage.TopSites.itemCell]) - XCTAssertTrue(app.collectionViews.cells.staticTexts[PDF_website["bookmarkLabel"]!].exists) + mozWaitForElementToExist(app.collectionViews.cells.staticTexts[PDF_website["bookmarkLabel"]!]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2307121 @@ -121,6 +119,6 @@ class BrowsingPDFTests: BaseTestCase { navigator.goto(BrowserTabMenu) navigator.goto(LibraryPanel_Bookmarks) mozWaitForElementToExist(app.tables["Bookmarks List"]) - XCTAssertTrue(app.tables["Bookmarks List"].staticTexts[PDF_website["bookmarkLabel"]!].exists) + mozWaitForElementToExist(app.tables["Bookmarks List"].staticTexts[PDF_website["bookmarkLabel"]!]) } } diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/ClipBoardTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/ClipBoardTests.swift index a6e3fa2ffba7..fed26e5368b8 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/ClipBoardTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/ClipBoardTests.swift @@ -34,7 +34,7 @@ class ClipBoardTests: BaseTestCase { if let myString = UIPasteboard.general.string { let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard") let allowBtn = springboard.buttons["Allow Paste"] - if allowBtn.waitForExistence(timeout: 10) { + if allowBtn.waitForExistence(timeout: TIMEOUT) { allowBtn.tap() } diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/CreditCardsTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/CreditCardsTests.swift index 68889a091c29..1d50e0b21555 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/CreditCardsTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/CreditCardsTests.swift @@ -28,29 +28,30 @@ class CreditCardsTests: BaseTestCase { // SmokeTest func testAccessingTheCreditCardsSection() { navigator.nowAt(NewTabScreen) + waitForTabsButton() navigator.goto(CreditCardsSettings) unlockLoginsView() // Autofill Credit cards section displays let addCardButton = app.buttons[creditCardsStaticTexts.AutoFillCreditCard.addCard] mozWaitForElementToExist(app.staticTexts[creditCardsStaticTexts.AutoFillCreditCard.autoFillCreditCards]) - XCTAssertTrue(addCardButton.exists) - XCTAssertTrue(app.switches[creditCardsStaticTexts.AutoFillCreditCard.saveAutofillCards].exists) + mozWaitForElementToExist(addCardButton) + mozWaitForElementToExist(app.switches[creditCardsStaticTexts.AutoFillCreditCard.saveAutofillCards]) addCardButton.tap() // Add Credit Card page is displayed mozWaitForElementToExist(app.staticTexts[creditCardsStaticTexts.AddCreditCard.addCreditCard]) - XCTAssertTrue(app.staticTexts[creditCardsStaticTexts.AddCreditCard.nameOnCard].exists) - XCTAssertTrue(app.staticTexts[creditCardsStaticTexts.AddCreditCard.cardNumber].exists) - XCTAssertTrue(app.staticTexts[creditCardsStaticTexts.AddCreditCard.expiration].exists) - XCTAssertTrue(app.buttons[creditCardsStaticTexts.AddCreditCard.close].exists) - XCTAssertTrue(app.buttons[creditCardsStaticTexts.AddCreditCard.save].exists) + mozWaitForElementToExist(app.staticTexts[creditCardsStaticTexts.AddCreditCard.nameOnCard]) + mozWaitForElementToExist(app.staticTexts[creditCardsStaticTexts.AddCreditCard.cardNumber]) + mozWaitForElementToExist(app.staticTexts[creditCardsStaticTexts.AddCreditCard.expiration]) + mozWaitForElementToExist(app.buttons[creditCardsStaticTexts.AddCreditCard.close]) + mozWaitForElementToExist(app.buttons[creditCardsStaticTexts.AddCreditCard.save]) // Add, and save a valid credit card addCreditCard(name: "Test", cardNumber: cards[0], expirationDate: "0540") mozWaitForElementToExist(app.staticTexts[creditCardsStaticTexts.AutoFillCreditCard.savedCards]) - XCTAssertTrue(app.staticTexts.containingText("New").element.exists) - XCTAssertTrue(app.tables.cells.element(boundBy: 1).staticTexts.elementContainingText("1252").exists) + mozWaitForElementToExist(app.staticTexts.containingText("New").element) + mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).staticTexts.elementContainingText("1252")) let cardDetails = ["Test", "Expires", "5/40"] for i in cardDetails { - XCTAssertTrue(app.tables.cells.element(boundBy: 1).staticTexts[i].exists, "\(i) does not exists") + mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).staticTexts[i]) } } @@ -71,8 +72,8 @@ class CreditCardsTests: BaseTestCase { creditCardsStaticTexts.EditCreditCard.remove ] mozWaitForElementToExist(removeThisCardAlert) - XCTAssertTrue(cancelButton.exists) - XCTAssertTrue(removeButton.exists) + mozWaitForElementToExist(cancelButton) + mozWaitForElementToExist(removeButton) // Tap on "CANCEL" cancelButton.tap() // The prompt is dismissed, the "Edit card" page is displayed @@ -87,7 +88,7 @@ class CreditCardsTests: BaseTestCase { // The credit card is deleted. The user is redirected to the "Saved cards" page mozWaitForElementToExist(app.staticTexts[creditCardsStaticTexts.AutoFillCreditCard.autoFillCreditCards]) mozWaitForElementToNotExist(app.staticTexts[creditCardsStaticTexts.AutoFillCreditCard.savedCards]) - XCTAssertFalse(app.tables.cells.element(boundBy: 1).exists) + mozWaitForElementToNotExist(app.tables.cells.element(boundBy: 1)) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2306975 @@ -127,6 +128,7 @@ class CreditCardsTests: BaseTestCase { // Smoketest func testAutofillCreditCardsToggleOnOoff() { navigator.nowAt(NewTabScreen) + waitForTabsButton() navigator.goto(CreditCardsSettings) unlockLoginsView() mozWaitForElementToExist(app.staticTexts[creditCardsStaticTexts.AutoFillCreditCard.autoFillCreditCards]) @@ -190,6 +192,7 @@ class CreditCardsTests: BaseTestCase { dismissSavedCardsPrompt() // The credit card's number and name are imported correctly on the designated fields let contentView = app.webViews["contentView"].webViews.textFields + mozWaitForElementToExist(contentView["Card number"]) XCTAssertEqual(contentView["Card number"].value! as! String, "2720 9943 2658 1252") XCTAssertEqual(contentView["Expiration"].value! as! String, "05 / 40") XCTAssertEqual(contentView["Full name on card"].value! as! String, "Test") @@ -208,7 +211,7 @@ class CreditCardsTests: BaseTestCase { typeCardName(name: updatedName) app.buttons["Save"].tap() // The name of the card is saved without issues - XCTAssertTrue(app.tables.cells.element(boundBy: 1).staticTexts[updatedName].exists, "\(updatedName) does not exists") + mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).staticTexts[updatedName]) // Go to an saved credit card and change the credit card number app.tables.cells.element(boundBy: 1).tap() app.buttons[creditCardsStaticTexts.ViewCreditCard.edit].tap() @@ -217,7 +220,7 @@ class CreditCardsTests: BaseTestCase { typeCardNr(cardNo: cards[1]) app.buttons["Save"].tap() // The credit card number is saved without issues - XCTAssertTrue(app.tables.cells.element(boundBy: 1).staticTexts.elementContainingText("1111").exists) + mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).staticTexts.elementContainingText("1111")) // Reach autofill website // reachAutofillWebsite() does not work on iOS 15 if #available(iOS 16, *) { @@ -233,6 +236,7 @@ class CreditCardsTests: BaseTestCase { // Add multiple credit cards let expectedCards = 3 navigator.nowAt(NewTabScreen) + waitForTabsButton() navigator.goto(CreditCardsSettings) unlockLoginsView() mozWaitForElementToExist(app.staticTexts[creditCardsStaticTexts.AutoFillCreditCard.autoFillCreditCards]) @@ -250,6 +254,7 @@ class CreditCardsTests: BaseTestCase { ["1111", "Test2", "6/40"], ["9631", "Test3", "7/40"]] for i in 1...3 { + mozWaitForElementToExist(app.tables.cells.element(boundBy: i).staticTexts.firstMatch) XCTAssertTrue(app.tables.cells.element(boundBy: i).staticTexts.elementContainingText(cardsInfo[i-1][0]).exists, "\(cardsInfo[i-1][0]) info is not displayed") XCTAssertTrue(app.tables.cells.element(boundBy: i).staticTexts[cardsInfo[i-1][1]].exists, @@ -300,43 +305,47 @@ class CreditCardsTests: BaseTestCase { tapCardNr() // Error message is displayed mozWaitForElementToExist(app.otherElements.staticTexts["Add a name"]) + mozWaitForElementToExist(saveButton) XCTAssertFalse(saveButton.isEnabled) // Fill in the name on card, and delete the credit card number tapCardName() typeCardName(name: "Test") tapCardNr() mozWaitForElementToNotExist(app.otherElements.staticTexts["Add a name"]) + mozWaitForElementToExist(saveButton) XCTAssertTrue(saveButton.isEnabled) pressDelete() tapCardName() // Error message is displayed mozWaitForElementToExist(app.otherElements.staticTexts["Enter a valid card number"]) + mozWaitForElementToExist(saveButton) XCTAssertFalse(saveButton.isEnabled) // Fill in the name on the card and the credit card number, delete the Expiration date tapCardNr() typeCardNr(cardNo: cards[0]) tapExpiration() mozWaitForElementToNotExist(app.otherElements.staticTexts["Enter a valid card number"]) + mozWaitForElementToExist(saveButton) XCTAssertTrue(saveButton.isEnabled) pressDelete() tapCardNr() // Error message is displayed mozWaitForElementToExist(app.otherElements.staticTexts["Enter a valid expiration date"]) + mozWaitForElementToExist(saveButton) XCTAssertFalse(saveButton.isEnabled) // Add the credit card number back and save it tapExpiration() typeExpirationDate(exprDate: "0540") tapCardNr() mozWaitForElementToNotExist(app.otherElements.staticTexts["Enter a valid expiration date"]) + mozWaitForElementToExist(saveButton) XCTAssertTrue(saveButton.isEnabled) saveButton.tap() // The credit card is saved let cardsInfo = ["Test", "5/40"] - XCTAssertTrue(app.tables.cells.element(boundBy: 1).staticTexts.elementContainingText("1252").exists, - "1252 info is not displayed") + mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).staticTexts.elementContainingText("1252")) for i in cardsInfo { - XCTAssertTrue(app.tables.cells.element(boundBy: 1).staticTexts[i].exists, - "\(i) info is not displayed") + mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).staticTexts[i]) } } @@ -394,7 +403,7 @@ class CreditCardsTests: BaseTestCase { unlockLoginsView() // The credit card is saved and displayed in the Credit cards section mozWaitForElementToExist(app.staticTexts[creditCardsStaticTexts.AutoFillCreditCard.savedCards]) - XCTAssertTrue(app.tables.cells.element(boundBy: 1).staticTexts.elementContainingText("1111").exists) + mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).staticTexts.elementContainingText("1111")) let cardDetails = ["Test", "Expires", "5/40"] for i in cardDetails { XCTAssertTrue(app.tables.cells.element(boundBy: 1).staticTexts[i].exists, "\(i) does not exists") @@ -432,10 +441,10 @@ class CreditCardsTests: BaseTestCase { navigator.goto(CreditCardsSettings) unlockLoginsView() // Credit cards details did not change - XCTAssertTrue(app.tables.cells.element(boundBy: 1).staticTexts.elementContainingText("1252").exists) + mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).staticTexts.elementContainingText("1252")) var cardDetails = ["Test", "Expires", "5/40"] for i in cardDetails { - XCTAssertTrue(app.tables.cells.element(boundBy: 1).staticTexts[i].exists, "\(i) does not exists") + mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).staticTexts[i]) } // Repeat above steps and tap on "Save" navigator.goto(NewTabScreen) @@ -475,23 +484,24 @@ class CreditCardsTests: BaseTestCase { navigator.goto(CreditCardsSettings) unlockLoginsView() // Credit cards details changed - XCTAssertTrue(app.tables.cells.element(boundBy: 1).staticTexts.elementContainingText("1252").exists) + mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).staticTexts.elementContainingText("1252")) cardDetails = ["TestTest2", "Expires", "5/40"] for i in cardDetails { - XCTAssertTrue(app.tables.cells.element(boundBy: 1).staticTexts[i].exists, "\(i) does not exists") + mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).staticTexts[i]) } } // https://testrail.stage.mozaws.net/index.php?/cases/view/2306970 func testRedirectionToCreditCardsSection() { navigator.nowAt(NewTabScreen) + waitForTabsButton() navigator.goto(CreditCardsSettings) unlockLoginsView() mozWaitForElementToExist(app.staticTexts[creditCardsStaticTexts.AutoFillCreditCard.autoFillCreditCards]) restartInBackground() unlockLoginsView() let addCardButton = app.buttons[creditCardsStaticTexts.AutoFillCreditCard.addCard] - XCTAssertTrue(addCardButton.exists) + mozWaitForElementToExist(addCardButton) addCardButton.tap() addCreditCard(name: "Test", cardNumber: cards[0], expirationDate: "0540") restartInBackground() @@ -640,6 +650,7 @@ class CreditCardsTests: BaseTestCase { private func addCreditCardAndReachAutofillWebsite() { // Access any website with a credit card form and tap on the credit card number/ credit card name navigator.nowAt(NewTabScreen) + waitForTabsButton() navigator.goto(CreditCardsSettings) unlockLoginsView() mozWaitForElementToExist(app.staticTexts[creditCardsStaticTexts.AutoFillCreditCard.autoFillCreditCards]) @@ -667,6 +678,7 @@ class CreditCardsTests: BaseTestCase { private func addCardAndReachViewCardPage() { navigator.nowAt(NewTabScreen) + waitForTabsButton() navigator.goto(CreditCardsSettings) unlockLoginsView() mozWaitForElementToExist(app.staticTexts[creditCardsStaticTexts.AutoFillCreditCard.autoFillCreditCards]) @@ -677,7 +689,7 @@ class CreditCardsTests: BaseTestCase { app.tables.cells.element(boundBy: 1).tap() // The "View card" page is displayed with all the details of the card mozWaitForElementToExist(app.navigationBars[creditCardsStaticTexts.ViewCreditCard.viewCard]) - XCTAssertTrue(app.tables.cells.element(boundBy: 1).staticTexts.elementContainingText("1252").exists) + mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).staticTexts.elementContainingText("1252")) let cardDetails = ["Test", "05 / 40"] for i in cardDetails { if #available(iOS 16, *) { diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/DataManagementTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/DataManagementTests.swift index b3dc06977241..455dc30c7cac 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/DataManagementTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/DataManagementTests.swift @@ -11,7 +11,7 @@ class DataManagementTests: BaseTestCase { navigator.nowAt(NewTabScreen) waitForTabsButton() navigator.goto(WebsiteDataSettings) - mozWaitForElementToExist(app.tables.otherElements["Website Data"], timeout: 3) + mozWaitForElementToExist(app.tables.otherElements["Website Data"]) app.tables.otherElements["Website Data"].swipeDown() mozWaitForElementToExist(app.searchFields["Filter Sites"]) navigator.performAction(Action.TapOnFilterWebsites) @@ -23,7 +23,7 @@ class DataManagementTests: BaseTestCase { navigator.performAction(Action.TapOnFilterWebsites) app.buttons["Cancel"].tap() - mozWaitForElementToExist(app.tables.otherElements["Website Data"], timeout: 3) + mozWaitForElementToExist(app.tables.otherElements["Website Data"]) navigator.performAction(Action.AcceptClearAllWebsiteData) mozWaitForElementToExist(app.tables.cells["ClearAllWebsiteData"].staticTexts["Clear All Website Data"]) @@ -37,8 +37,12 @@ class DataManagementTests: BaseTestCase { navigator.openURL("example.com") waitUntilPageLoad() navigator.goto(WebsiteDataSettings) - mozWaitForElementToExist(app.tables.otherElements["Website Data"], timeout: 3) - XCTAssertTrue(app.staticTexts["example.com"].exists, "The website visited is not displayed on Website Data") + mozWaitForElementToExist(app.tables.otherElements["Website Data"]) + mozWaitForElementToExist(app.tables.buttons.images["circle"].firstMatch) + if app.cells["ShowMoreWebsiteData"].exists { + app.cells["ShowMoreWebsiteData"].tap() + } + mozWaitForElementToExist(app.staticTexts["example.com"]) // There should be 4 entries. One is the website visited and 3 for extrainfo from the page. // This assert will remain commented until a way is found of having website data clean on the first run // This is to avoid intermittent failings diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/DesktopModeTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/DesktopModeTests.swift index 78e7cbccc590..24ea1d956d4d 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/DesktopModeTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/DesktopModeTests.swift @@ -142,7 +142,7 @@ class DesktopModeTestsIphone: IphoneOnlyTestCase { navigator.openURL(path(forTestPage: "test-user-agent.html")) // Workaround to be sure the snackbar disappears waitUntilPageLoad() - mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.reloadButton], timeout: 5) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.reloadButton]) app.buttons[AccessibilityIdentifiers.Toolbar.reloadButton].tap() navigator.goto(BrowserTabMenu) navigator.goto(RequestMobileSite) // toggle off @@ -191,7 +191,7 @@ class DesktopModeTestsIphone: IphoneOnlyTestCase { if skipPlatform { return } navigator.openURL(path(forTestPage: "test-user-agent.html")) waitUntilPageLoad() - mozWaitForElementToExist(app.webViews.staticTexts.firstMatch, timeout: 5) + mozWaitForElementToExist(app.webViews.staticTexts.firstMatch) XCTAssert(app.webViews.staticTexts.matching(identifier: "MOBILE_UA").count > 0) navigator.nowAt(BrowserTab) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/DisplaySettingsTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/DisplaySettingsTests.swift index dff396002f75..24a676fd3bc8 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/DisplaySettingsTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/DisplaySettingsTests.swift @@ -10,7 +10,7 @@ class DisplaySettingTests: BaseTestCase { navigator.nowAt(NewTabScreen) navigator.goto(DisplaySettings) mozWaitForElementToExist(app.navigationBars["Theme"]) - XCTAssertTrue(app.tables["DisplayTheme.Setting.Options"].exists) + mozWaitForElementToExist(app.tables["DisplayTheme.Setting.Options"]) let switchValue = app.switches["SystemThemeSwitchValue"].value! XCTAssertEqual(switchValue as! String, "1") } @@ -30,27 +30,26 @@ class DisplaySettingTests: BaseTestCase { mozWaitForElementToExist(app.switches["SystemThemeSwitchValue"]) let switchValue = app.switches["SystemThemeSwitchValue"].value! XCTAssertEqual(switchValue as! String, "0") - XCTAssertTrue(app.cells.staticTexts["Light"].exists) - XCTAssertTrue(app.cells.staticTexts["Dark"].exists) + mozWaitForElementToExist(app.cells.staticTexts["Light"]) + mozWaitForElementToExist(app.cells.staticTexts["Dark"]) // Select the Automatic mode navigator.performAction(Action.SelectAutomatically) - - XCTAssertTrue(app.tables.otherElements["THRESHOLD"].exists) - XCTAssertFalse(app.cells.staticTexts["Light"].exists) - XCTAssertFalse(app.cells.staticTexts["Dark"].exists) + mozWaitForElementToExist(app.tables.otherElements["THRESHOLD"]) + mozWaitForElementToNotExist(app.cells.staticTexts["Light"]) + mozWaitForElementToNotExist(app.cells.staticTexts["Dark"]) // Now select the Manual mode navigator.performAction(Action.SelectManually) - XCTAssertFalse(app.tables.otherElements["THRESHOLD"].exists) - XCTAssertTrue(app.cells.staticTexts["Light"].exists) - XCTAssertTrue(app.cells.staticTexts["Dark"].exists) + mozWaitForElementToNotExist(app.tables.otherElements["THRESHOLD"]) + mozWaitForElementToExist(app.cells.staticTexts["Light"]) + mozWaitForElementToExist(app.cells.staticTexts["Dark"]) // Enable back system theme navigator.performAction(Action.SystemThemeSwitch) let switchValueAfter = app.switches["SystemThemeSwitchValue"].value! XCTAssertEqual(switchValueAfter as! String, "1") - XCTAssertFalse(app.tables["DisplayTheme.Setting.Options"].otherElements.staticTexts["SWITCH MODE"].exists) - XCTAssertFalse(app.tables["DisplayTheme.Setting.Options"].otherElements.staticTexts["THEME PICKER"].exists) + mozWaitForElementToNotExist(app.tables["DisplayTheme.Setting.Options"].otherElements.staticTexts["SWITCH MODE"]) + mozWaitForElementToNotExist(app.tables["DisplayTheme.Setting.Options"].otherElements.staticTexts["THEME PICKER"]) } } diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/DownloadsTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/DownloadsTests.swift index d6a4079e7cd3..22a23835b382 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/DownloadsTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/DownloadsTests.swift @@ -15,12 +15,17 @@ let testBLOBFileSize = "35 bytes" class DownloadsTests: BaseTestCase { override func tearDown() { // The downloaded file has to be removed between tests + app.terminate() + app.activate() + waitForTabsButton() + navigator.nowAt(NewTabScreen) + navigator.goto(LibraryPanel_Downloads) mozWaitForElementToExist(app.tables["DownloadsTable"]) let list = app.tables["DownloadsTable"].cells.count if list != 0 { for _ in 0...list-1 { mozWaitForElementToExist(app.tables["DownloadsTable"].cells.element(boundBy: 0)) - app.tables["DownloadsTable"].cells.element(boundBy: 0).swipeLeft() + app.tables["DownloadsTable"].cells.element(boundBy: 0).swipeLeft(velocity: 200) mozWaitForElementToExist(app.tables.cells.buttons["Delete"]) app.tables.cells.buttons["Delete"].tap() } @@ -29,8 +34,8 @@ class DownloadsTests: BaseTestCase { } private func deleteItem(itemName: String) { - app.tables.cells.staticTexts[itemName].swipeLeft() - mozWaitForElementToExist(app.tables.cells.buttons["Delete"], timeout: TIMEOUT) + app.tables.cells.staticTexts[itemName].swipeLeft(velocity: 200) + mozWaitForElementToExist(app.tables.cells.buttons["Delete"]) app.tables.cells.buttons["Delete"].tap() } @@ -38,8 +43,7 @@ class DownloadsTests: BaseTestCase { func testDownloadFilesAppMenuFirstTime() { navigator.nowAt(NewTabScreen) navigator.goto(LibraryPanel_Downloads) - mozWaitForElementToExist(app.tables["DownloadsTable"], timeout: TIMEOUT) - XCTAssertTrue(app.tables["DownloadsTable"].exists) + mozWaitForElementToExist(app.tables["DownloadsTable"]) // Check that there is not any items and the default text shown is correct checkTheNumberOfDownloadedItems(items: 0) mozWaitForElementToExist(app.staticTexts["Downloaded files will show up here."]) @@ -56,7 +60,7 @@ class DownloadsTests: BaseTestCase { } app.webViews.links[testFileName].firstMatch.tap() - mozWaitForElementToExist(app.tables["Context Menu"], timeout: TIMEOUT) + mozWaitForElementToExist(app.tables["Context Menu"]) mozWaitForElementToExist(app.tables["Context Menu"].staticTexts[testFileNameDownloadPanel]) mozWaitForElementToExist(app.tables["Context Menu"].otherElements[StandardImageIdentifiers.Large.download]) app.buttons["Cancel"].tap() @@ -72,7 +76,7 @@ class DownloadsTests: BaseTestCase { navigator.goto(BrowserTabMenu) navigator.goto(LibraryPanel_Downloads) - mozWaitForElementToExist(app.tables["DownloadsTable"], timeout: TIMEOUT) + mozWaitForElementToExist(app.tables["DownloadsTable"]) // There should be one item downloaded. It's name and size should be shown checkTheNumberOfDownloadedItems(items: 1) mozWaitForElementToExist(app.tables.cells.staticTexts[testFileNameDownloadPanel]) @@ -111,9 +115,8 @@ class DownloadsTests: BaseTestCase { navigator.goto(BrowserTabMenu) navigator.goto(LibraryPanel_Downloads) let shareButton = app.tables.buttons.staticTexts["Share"] - app.tables.cells.staticTexts[testFileNameDownloadPanel].swipeLeft() + app.tables.cells.staticTexts[testFileNameDownloadPanel].swipeLeft(velocity: 200) mozWaitForElementToExist(shareButton) - XCTAssertTrue(shareButton.exists) mozWaitForElementToExist(app.tables.buttons.staticTexts["Delete"]) shareButton.tap(force: true) mozWaitForElementToExist(app.tables["DownloadsTable"]) @@ -141,8 +144,9 @@ class DownloadsTests: BaseTestCase { mozWaitForElementToExist(app.tables["DownloadsTable"]) // Commenting out until share sheet can be managed with automated tests issue #5477 app.tables.cells.staticTexts[testFileNameDownloadPanel].press(forDuration: 2) - mozWaitForElementToExist(app.otherElements["ActivityListView"], timeout: TIMEOUT) + mozWaitForElementToExist(app.otherElements["ActivityListView"]) mozWaitForElementToExist(app.tables["DownloadsTable"].staticTexts[testFileNameDownloadPanel]) + /* if #available(iOS 16, *) { mozWaitForElementToExist(app.collectionViews.cells["Copy"]) } else { @@ -155,6 +159,7 @@ class DownloadsTests: BaseTestCase { // XCUITest does not allow me to click the greyed out portion of the app without the force option. app.buttons["Done"].tap(force: true) } + */ } private func downloadFile(fileName: String, numberOfDownloads: Int) { @@ -162,22 +167,22 @@ class DownloadsTests: BaseTestCase { waitUntilPageLoad() app.webViews.firstMatch.swipeLeft() for _ in 0.. MMScr func makeURLBarAvailable(_ screenState: MMScreenStateNode) { screenState.tap(app.textFields["url"], to: URLBarOpen) screenState.gesture(to: URLBarLongPressMenu) { - sleep(1) app.textFields["url"].press(forDuration: 1.0) } } @@ -1086,6 +1085,7 @@ func createScreenGraph(for test: XCTestCase, with app: XCUIApplication) -> MMScr } map.addScreenState(BrowserTabMenu) { screenState in + sleep(1) screenState.tap( app.tables.otherElements[StandardImageIdentifiers.Large.settings], to: SettingsScreen diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/HistoryTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/HistoryTests.swift index bf6525232d96..3cfcddf84fd4 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/HistoryTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/HistoryTests.swift @@ -62,8 +62,8 @@ class HistoryTests: BaseTestCase { // Go to History List from Top Sites and check it is empty navigator.goto(LibraryPanel_History) mozWaitForElementToExist(app.tables.cells[HistoryPanelA11y.recentlyClosedCell]) - XCTAssertTrue(app.tables.cells[HistoryPanelA11y.recentlyClosedCell].staticTexts["Recently Closed"].exists) - XCTAssertTrue(app.tables[HistoryPanelA11y.tableView].staticTexts[emptyRecentlyClosedMesg].exists) + mozWaitForElementToExist(app.tables.cells[HistoryPanelA11y.recentlyClosedCell].staticTexts["Recently Closed"]) + mozWaitForElementToExist(app.tables[HistoryPanelA11y.tableView].staticTexts[emptyRecentlyClosedMesg]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2307301 @@ -73,7 +73,7 @@ class HistoryTests: BaseTestCase { navigator.goto(TabTray) navigator.performAction(Action.ToggleSyncMode) mozWaitForElementToExist(app.otherElements.staticTexts["Firefox Sync"]) - XCTAssertTrue(app.otherElements.buttons["Sync and Save Data"].exists, "Sign in button does not appear") + mozWaitForElementToExist(app.otherElements.buttons["Sync and Save Data"]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2307487 @@ -82,9 +82,9 @@ class HistoryTests: BaseTestCase { navigator.nowAt(NewTabScreen) // Browse to have an item in history list navigator.goto(LibraryPanel_History) - mozWaitForElementToExist(app.tables.cells[HistoryPanelA11y.recentlyClosedCell], timeout: TIMEOUT) - XCTAssertTrue(app.tables.cells.staticTexts[oldHistoryEntries[0]].exists) - XCTAssertFalse(app.tables[HistoryPanelA11y.tableView].staticTexts[emptyRecentlyClosedMesg].exists) + mozWaitForElementToExist(app.tables.cells[HistoryPanelA11y.recentlyClosedCell]) + mozWaitForElementToExist(app.tables.cells.staticTexts[oldHistoryEntries[0]]) + mozWaitForElementToNotExist(app.tables[HistoryPanelA11y.tableView].staticTexts[emptyRecentlyClosedMesg]) // Clear all private data via the settings navigator.goto(HomePanelsScreen) @@ -97,8 +97,8 @@ class HistoryTests: BaseTestCase { navigator.goto(LibraryPanel_History) mozWaitForElementToExist(app.tables[HistoryPanelA11y.tableView]) mozWaitForElementToExist(app.tables.cells[HistoryPanelA11y.recentlyClosedCell]) - XCTAssertFalse(app.tables.cells.staticTexts[oldHistoryEntries[0]].exists) - XCTAssertTrue(app.tables[HistoryPanelA11y.tableView].staticTexts[emptyRecentlyClosedMesg].exists) + mozWaitForElementToNotExist(app.tables.cells.staticTexts[oldHistoryEntries[0]]) + mozWaitForElementToExist(app.tables[HistoryPanelA11y.tableView].staticTexts[emptyRecentlyClosedMesg]) } } @@ -107,15 +107,15 @@ class HistoryTests: BaseTestCase { func testClearPrivateData() throws { XCTExpectFailure("The app was not launched", strict: false) { navigator.nowAt(NewTabScreen) - mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton], timeout: TIMEOUT) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton]) // Clear private data from settings and confirm navigator.goto(ClearPrivateDataSettings) app.tables.cells["ClearPrivateData"].tap() - mozWaitForElementToExist(app.tables.cells["ClearPrivateData"], timeout: TIMEOUT) + mozWaitForElementToExist(app.tables.cells["ClearPrivateData"]) app.alerts.buttons["OK"].tap() // Wait for OK pop-up to disappear after confirming - mozWaitForElementToNotExist(app.alerts.buttons["OK"], timeout: TIMEOUT) + mozWaitForElementToNotExist(app.alerts.buttons["OK"]) // Try to tap on the disabled Clear Private Data button app.tables.cells["ClearPrivateData"].tap() @@ -136,8 +136,8 @@ class HistoryTests: BaseTestCase { navigator.goto(BrowserTabMenu) navigator.goto(LibraryPanel_History) mozWaitForElementToExist(app.tables[HistoryPanelA11y.tableView]) - XCTAssertFalse(app.tables.cells.staticTexts[bookOfMozilla["label"]!].exists) - XCTAssertTrue(app.tables[HistoryPanelA11y.tableView].staticTexts[emptyRecentlyClosedMesg].exists) + mozWaitForElementToNotExist(app.tables.cells.staticTexts[bookOfMozilla["label"]!]) + mozWaitForElementToExist(app.tables[HistoryPanelA11y.tableView].staticTexts[emptyRecentlyClosedMesg]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2307463 @@ -149,16 +149,16 @@ class HistoryTests: BaseTestCase { // On regular mode, the closed tab is listed in "Recently Closed" list navigator.nowAt(NewTabScreen) navigator.goto(HistoryRecentlyClosed) - mozWaitForElementToExist(app.tables["Recently Closed Tabs List"], timeout: TIMEOUT) - XCTAssertTrue(app.tables.cells.staticTexts[bookOfMozilla["label"]!].exists) + mozWaitForElementToExist(app.tables["Recently Closed Tabs List"]) + mozWaitForElementToExist(app.tables.cells.staticTexts[bookOfMozilla["label"]!]) // On private mode, the closed tab on regular mode is listed in "Recently Closed" list as well navigator.toggleOn(userState.isPrivate, withAction: Action.TogglePrivateMode) navigator.performAction(Action.OpenNewTabFromTabTray) closeKeyboard() navigator.goto(HistoryRecentlyClosed) - mozWaitForElementToExist(app.tables["Recently Closed Tabs List"], timeout: TIMEOUT) - XCTAssertTrue(app.tables.cells.staticTexts[bookOfMozilla["label"]!].exists) + mozWaitForElementToExist(app.tables["Recently Closed Tabs List"]) + mozWaitForElementToExist(app.tables.cells.staticTexts[bookOfMozilla["label"]!]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2307475 @@ -177,8 +177,8 @@ class HistoryTests: BaseTestCase { closeKeyboard() navigator.goto(LibraryPanel_History) mozWaitForElementToExist(app.tables[HistoryPanelA11y.tableView]) - XCTAssertTrue(app.tables[HistoryPanelA11y.tableView].staticTexts[emptyRecentlyClosedMesg].exists) - XCTAssertFalse(app.tables.cells.staticTexts[bookOfMozilla["label"]!].exists) + mozWaitForElementToExist(app.tables[HistoryPanelA11y.tableView].staticTexts[emptyRecentlyClosedMesg]) + mozWaitForElementToNotExist(app.tables.cells.staticTexts[bookOfMozilla["label"]!]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2307479 @@ -196,8 +196,8 @@ class HistoryTests: BaseTestCase { navigator.nowAt(NewTabScreen) navigator.goto(LibraryPanel_History) navigator.goto(HistoryRecentlyClosed) - mozWaitForElementToExist(app.tables["Recently Closed Tabs List"], timeout: TIMEOUT) - XCTAssertTrue(app.tables.cells.staticTexts[bookOfMozilla["label"]!].exists) + mozWaitForElementToExist(app.tables["Recently Closed Tabs List"]) + mozWaitForElementToExist(app.tables.cells.staticTexts[bookOfMozilla["label"]!]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2307482 @@ -210,7 +210,7 @@ class HistoryTests: BaseTestCase { navigator.nowAt(NewTabScreen) navigator.goto(HistoryRecentlyClosed) mozWaitForElementToExist(app.tables["Recently Closed Tabs List"]) - XCTAssertTrue(app.tables.cells.staticTexts[bookOfMozilla["label"]!].exists) + mozWaitForElementToExist(app.tables.cells.staticTexts[bookOfMozilla["label"]!]) // Clear all private data via the settings navigator.goto(HomePanelsScreen) @@ -222,8 +222,8 @@ class HistoryTests: BaseTestCase { // The closed tab is *not* listed in "Recently Closed Tabs List" navigator.goto(LibraryPanel_History) mozWaitForElementToExist(app.tables[HistoryPanelA11y.tableView]) - XCTAssertTrue(app.tables[HistoryPanelA11y.tableView].staticTexts[emptyRecentlyClosedMesg].exists) - XCTAssertFalse(app.tables.cells.staticTexts[bookOfMozilla["label"]!].exists) + mozWaitForElementToExist(app.tables[HistoryPanelA11y.tableView].staticTexts[emptyRecentlyClosedMesg]) + mozWaitForElementToNotExist(app.tables.cells.staticTexts[bookOfMozilla["label"]!]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2307483 @@ -236,11 +236,11 @@ class HistoryTests: BaseTestCase { navigator.nowAt(NewTabScreen) navigator.goto(HistoryRecentlyClosed) mozWaitForElementToExist(app.tables["Recently Closed Tabs List"]) - XCTAssertTrue(app.tables.cells.staticTexts[bookOfMozilla["label"]!].exists) + mozWaitForElementToExist(app.tables.cells.staticTexts[bookOfMozilla["label"]!]) app.tables.cells.staticTexts[bookOfMozilla["label"]!].press(forDuration: 1) mozWaitForElementToExist(app.tables["Context Menu"]) - XCTAssertTrue(app.tables.otherElements[StandardImageIdentifiers.Large.plus].exists) - XCTAssertTrue(app.tables.otherElements[StandardImageIdentifiers.Large.privateMode].exists) + mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.plus]) + mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.privateMode]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2307484 @@ -253,7 +253,7 @@ class HistoryTests: BaseTestCase { navigator.nowAt(NewTabScreen) navigator.goto(HistoryRecentlyClosed) mozWaitForElementToExist(app.tables["Recently Closed Tabs List"]) - XCTAssertTrue(app.tables.cells.staticTexts[bookOfMozilla["label"]!].exists) + mozWaitForElementToExist(app.tables.cells.staticTexts[bookOfMozilla["label"]!]) XCTAssertEqual(userState.numTabs, 1) app.tables.cells.staticTexts[bookOfMozilla["label"]!].press(forDuration: 1) mozWaitForElementToExist(app.tables["Context Menu"]) @@ -267,7 +267,7 @@ class HistoryTests: BaseTestCase { } else { mozWaitForElementToExist(app.navigationBars.staticTexts["Open Tabs"]) } - XCTAssertTrue(app.staticTexts[bookOfMozilla["title"]!].exists) + mozWaitForElementToExist(app.staticTexts[bookOfMozilla["title"]!]) // userState.numTabs does not work on iOS 15 if #available(iOS 16, *) { XCTAssertEqual(userState.numTabs, 2) @@ -284,7 +284,7 @@ class HistoryTests: BaseTestCase { navigator.nowAt(NewTabScreen) navigator.goto(HistoryRecentlyClosed) mozWaitForElementToExist(app.tables["Recently Closed Tabs List"]) - XCTAssertTrue(app.tables.cells.staticTexts[bookOfMozilla["label"]!].exists) + mozWaitForElementToExist(app.tables.cells.staticTexts[bookOfMozilla["label"]!]) app.tables.cells.staticTexts[bookOfMozilla["label"]!].press(forDuration: 1) mozWaitForElementToExist(app.tables["Context Menu"]) app.tables.otherElements[StandardImageIdentifiers.Large.privateMode].tap() @@ -304,7 +304,7 @@ class HistoryTests: BaseTestCase { } else { mozWaitForElementToExist(app.staticTexts["Private Browsing"]) } - XCTAssertTrue(app.staticTexts[bookOfMozilla["title"]!].exists) + mozWaitForElementToExist(app.staticTexts[bookOfMozilla["title"]!]) XCTAssertEqual(userState.numTabs, 1) } @@ -334,7 +334,7 @@ class HistoryTests: BaseTestCase { mozWaitForElementToExist(app.tables[HistoryPanelA11y.tableView]) mozWaitForElementToNotExist(app.tables["Recently Closed Tabs List"]) XCTAssertFalse(app.cells.staticTexts["Recently Closed"].isSelected) - XCTAssertTrue(app.tables[HistoryPanelA11y.tableView].staticTexts[emptyRecentlyClosedMesg].exists) + mozWaitForElementToExist(app.tables[HistoryPanelA11y.tableView].staticTexts[emptyRecentlyClosedMesg]) XCTAssertFalse(app.tables.cells.staticTexts[bookOfMozilla["label"]!].exists) // On regular mode, the "Recently Closed Tabs List" is empty, too @@ -345,7 +345,7 @@ class HistoryTests: BaseTestCase { mozWaitForElementToExist(app.tables[HistoryPanelA11y.tableView]) mozWaitForElementToNotExist(app.tables["Recently Closed Tabs List"]) XCTAssertFalse(app.cells.staticTexts["Recently Closed"].isSelected) - XCTAssertTrue(app.tables[HistoryPanelA11y.tableView].staticTexts[emptyRecentlyClosedMesg].exists) + mozWaitForElementToExist(app.tables[HistoryPanelA11y.tableView].staticTexts[emptyRecentlyClosedMesg]) XCTAssertFalse(app.tables.cells.staticTexts[bookOfMozilla["label"]!].exists) } @@ -357,19 +357,19 @@ class HistoryTests: BaseTestCase { let urlBarBackButton = app.windows.otherElements.buttons[AccessibilityIdentifiers.Toolbar.backButton] let urlBarForwardButton = app.windows.otherElements.buttons[AccessibilityIdentifiers.Toolbar.forwardButton] urlBarBackButton.press(forDuration: 1) - XCTAssertTrue(app.tables.staticTexts["The Book of Mozilla"].exists) + mozWaitForElementToExist(app.tables.staticTexts["The Book of Mozilla"]) app.tables.staticTexts["The Book of Mozilla"].tap() - XCTAssertFalse(app.tables.staticTexts["The Book of Mozilla"].exists) + mozWaitForElementToNotExist(app.tables.staticTexts["The Book of Mozilla"]) navigator.toggleOn(userState.isPrivate, withAction: Action.TogglePrivateMode) navigator.performAction(Action.OpenNewTabFromTabTray) openBookOfMozilla() urlBarBackButton.press(forDuration: 1) - XCTAssertTrue(app.tables.staticTexts["The Book of Mozilla"].exists) + mozWaitForElementToExist(app.tables.staticTexts["The Book of Mozilla"]) app.tables.staticTexts["The Book of Mozilla"].tap() urlBarBackButton.tap() XCTAssertFalse(urlBarBackButton.isEnabled) urlBarForwardButton.press(forDuration: 1) - XCTAssertTrue(app.tables.staticTexts["The Book of Mozilla"].exists) + mozWaitForElementToExist(app.tables.staticTexts["The Book of Mozilla"]) app.tables.staticTexts["The Book of Mozilla"].tap() mozWaitForValueContains(app.textFields["url"], value: "test-fixture/test-mozilla-book.html") } @@ -392,8 +392,8 @@ class HistoryTests: BaseTestCase { waitForTabsButton() navigator.nowAt(NewTabScreen) navigator.goto(LibraryPanel_History) - mozWaitForElementToExist(app.tables[HistoryPanelA11y.tableView], timeout: TIMEOUT) - XCTAssertTrue(app.tables.cells.staticTexts["Example Domain"].exists) + mozWaitForElementToExist(app.tables[HistoryPanelA11y.tableView]) + mozWaitForElementToExist(app.tables.cells.staticTexts["Example Domain"]) } private func openBookOfMozilla() { @@ -421,7 +421,7 @@ class HistoryTests: BaseTestCase { } private func closeKeyboard() { - mozWaitForElementToExist(app.buttons["urlBar-cancel"], timeout: TIMEOUT) + mozWaitForElementToExist(app.buttons["urlBar-cancel"]) navigator.performAction(Action.CloseURLBarOpen) navigator.nowAt(NewTabScreen) } @@ -436,10 +436,10 @@ class HistoryTests: BaseTestCase { // Older data will not be removed tapOnClearRecentHistoryOption(optionSelected: "Today") for entry in oldHistoryEntries { - XCTAssertTrue(app.tables.cells.staticTexts[entry].exists) + mozWaitForElementToExist(app.tables.cells.staticTexts[entry]) } - XCTAssertFalse(app.staticTexts["Today"].exists) - XCTAssertTrue(app.staticTexts["Older"].exists) + mozWaitForElementToNotExist(app.staticTexts["Today"]) + mozWaitForElementToExist(app.staticTexts["Older"]) // Begin Test for Today and Yesterday // Visit a page to create a recent history entry. @@ -451,8 +451,8 @@ class HistoryTests: BaseTestCase { for entry in oldHistoryEntries { XCTAssertTrue(app.tables.cells.staticTexts[entry].exists) } - XCTAssertFalse(app.staticTexts["Today"].exists) - XCTAssertTrue(app.staticTexts["Older"].exists) + mozWaitForElementToNotExist(app.staticTexts["Today"]) + mozWaitForElementToExist(app.staticTexts["Older"]) // Begin Test for Everything // Visit a page to create a recent history entry. @@ -462,11 +462,9 @@ class HistoryTests: BaseTestCase { tapOnClearRecentHistoryOption(optionSelected: "Everything") for entry in oldHistoryEntries { mozWaitForElementToNotExist(app.tables.cells.staticTexts[entry]) - - XCTAssertFalse(app.tables.cells.staticTexts[entry].exists, "History not removed") } - XCTAssertFalse(app.staticTexts["Today"].exists) - XCTAssertFalse(app.staticTexts["Older"].exists) + mozWaitForElementToNotExist(app.staticTexts["Today"]) + mozWaitForElementToNotExist(app.staticTexts["Older"]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2306890 @@ -474,14 +472,14 @@ class HistoryTests: BaseTestCase { func testDeleteHistoryEntryBySwiping() { navigateToPage() navigator.goto(LibraryPanel_History) - waitForExistence(app.cells.staticTexts["http://example.com/"], timeout: TIMEOUT) + waitForExistence(app.cells.staticTexts["http://example.com/"]) navigateToPage() navigator.goto(LibraryPanel_History) - mozWaitForElementToExist(app.cells.staticTexts["http://example.com/"], timeout: TIMEOUT) + mozWaitForElementToExist(app.cells.staticTexts["http://example.com/"]) app.cells.staticTexts["http://example.com/"].firstMatch.swipeLeft() - mozWaitForElementToExist(app.buttons["Delete"], timeout: TIMEOUT) + mozWaitForElementToExist(app.buttons["Delete"]) app.buttons["Delete"].tap() mozWaitForElementToNotExist(app.staticTexts["http://example.com"]) - XCTAssertTrue(app.tables[HistoryPanelA11y.tableView].staticTexts[emptyRecentlyClosedMesg].exists) + mozWaitForElementToExist(app.tables[HistoryPanelA11y.tableView].staticTexts[emptyRecentlyClosedMesg]) } } diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/HomeButtonTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/HomeButtonTests.swift index a25307b3d5e0..9f4b93aba10b 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/HomeButtonTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/HomeButtonTests.swift @@ -17,8 +17,7 @@ class HomeButtonTests: BaseTestCase { navigator.nowAt(NewTabScreen) } navigator.openURL(path(forTestPage: "test-mozilla-org.html"), waitForLoading: true) - mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.homeButton], timeout: 10) - XCTAssertTrue(app.buttons[AccessibilityIdentifiers.Toolbar.homeButton].exists) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.homeButton]) app.buttons[AccessibilityIdentifiers.Toolbar.homeButton].tap() navigator.nowAt(NewTabScreen) waitForTabsButton() @@ -27,8 +26,7 @@ class HomeButtonTests: BaseTestCase { navigator.nowAt(NewTabScreen) } navigator.openURL(path(forTestPage: "test-mozilla-book.html"), waitForLoading: true) - mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.homeButton], timeout: 5) - XCTAssertTrue(app.buttons[AccessibilityIdentifiers.Toolbar.homeButton].exists) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.homeButton]) XCUIDevice.shared.orientation = .landscapeRight XCTAssertTrue(app.buttons["Home"].exists) @@ -43,7 +41,7 @@ class HomeButtonTests: BaseTestCase { waitUntilPageLoad() // Switch to Homepage by taping the home button - mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.homeButton], timeout: 10) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.homeButton]) app.buttons[AccessibilityIdentifiers.Toolbar.homeButton].tap() validateHomePageAndKeyboardNotRaisedUp() @@ -51,7 +49,7 @@ class HomeButtonTests: BaseTestCase { // https://testrail.stage.mozaws.net/index.php?/cases/view/2306881 func testAppLaunchKeyboardNotRaisedUp() { - mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton], timeout: 5) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton]) validateHomePageAndKeyboardNotRaisedUp() } diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/HomePageSettingsUITest.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/HomePageSettingsUITest.swift index 6773901636df..a8a63eff86a9 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/HomePageSettingsUITest.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/HomePageSettingsUITest.swift @@ -54,7 +54,7 @@ class HomePageSettingsUITests: BaseTestCase { XCTAssertTrue(app.tables.cells["StartAtHomeAfterFourHours"].isSelected) // Include on Homepage - XCTAssertTrue(app.tables.cells["TopSitesSettings"].staticTexts["On"].exists) + mozWaitForElementToExist(app.tables.cells["TopSitesSettings"].staticTexts["On"]) let jumpBackIn = app.tables.cells.switches["Jump Back In"].value XCTAssertEqual("1", jumpBackIn as? String) let bookmarks = app.tables.cells.switches["Bookmarks"].value @@ -68,7 +68,7 @@ class HomePageSettingsUITests: BaseTestCase { // Current Homepage XCTAssertTrue(app.tables.cells["Firefox Home"].isSelected) - XCTAssertTrue(app.tables.cells["HomeAsCustomURL"].exists) + mozWaitForElementToExist(app.tables.cells["HomeAsCustomURL"]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2339257 @@ -82,8 +82,7 @@ class HomePageSettingsUITests: BaseTestCase { // Check if it is saved going back and then again to home settings menu navigator.goto(SettingsScreen) navigator.goto(HomeSettings) - let valueAfter = app.textFields["HomeAsCustomURLTextField"].value - XCTAssertEqual(valueAfter as? String, "http://example.com") + mozWaitForValueContains(app.textFields["HomeAsCustomURLTextField"], value: "http://example.com") // Check that it is actually set by opening a different website and going to Home navigator.openURL(path(forTestPage: "test-mozilla-org.html")) @@ -91,7 +90,7 @@ class HomePageSettingsUITests: BaseTestCase { // Now check open home page should load the previously saved home page let homePageMenuItem = app.buttons[AccessibilityIdentifiers.Toolbar.homeButton] - mozWaitForElementToExist(homePageMenuItem, timeout: TIMEOUT) + mozWaitForElementToExist(homePageMenuItem) homePageMenuItem.tap() waitUntilPageLoad() mozWaitForValueContains(app.textFields["url"], value: "example") @@ -119,8 +118,7 @@ class HomePageSettingsUITests: BaseTestCase { app.menuItems["Paste"].tap() mozWaitForValueContains(app.textFields["HomeAsCustomURLTextField"], value: "mozilla") // Check that the webpage has been correctly copied into the correct field - let value = app.textFields["HomeAsCustomURLTextField"].value as! String - XCTAssertEqual(value, websiteUrl1) + mozWaitForValueContains(app.textFields["HomeAsCustomURLTextField"], value: websiteUrl1) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2339260 @@ -136,7 +134,7 @@ class HomePageSettingsUITests: BaseTestCase { waitUntilPageLoad() navigator.nowAt(BrowserTab) navigator.performAction(Action.GoToHomePage) - mozWaitForElementToExist(app.textFields["url"], timeout: TIMEOUT) + mozWaitForElementToExist(app.textFields["url"]) // Now after setting History, make sure FF home is set navigator.goto(SettingsScreen) @@ -163,15 +161,14 @@ class HomePageSettingsUITests: BaseTestCase { // Workaround needed after Xcode 11.3 update Issue 5937 // Lets check only that website is open - mozWaitForElementToExist(app.textFields["url"], timeout: TIMEOUT) + mozWaitForElementToExist(app.textFields["url"]) mozWaitForValueContains(app.textFields["url"], value: "mozilla") } // https://testrail.stage.mozaws.net/index.php?/cases/view/2339489 func testDisableTopSitesSettingsRemovesSection() { mozWaitForElementToExist( - app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton], - timeout: TIMEOUT + app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton] ) navigator.nowAt(NewTabScreen) navigator.goto(HomeSettings) @@ -195,11 +192,13 @@ class HomePageSettingsUITests: BaseTestCase { enterWebPageAsHomepage(text: websiteUrl1) mozWaitForValueContains(app.textFields["HomeAsCustomURLTextField"], value: "mozilla") navigator.goto(SettingsScreen) + mozWaitForElementToExist(app.tables.cells["Home"]) XCTAssertEqual(app.tables.cells["Home"].label, "Homepage, Custom") // Switch to FXHome and check label navigator.performAction(Action.SelectHomeAsFirefoxHomePage) navigator.nowAt(HomeSettings) navigator.goto(SettingsScreen) + mozWaitForElementToExist(app.tables.cells["Home"]) XCTAssertEqual(app.tables.cells["Home"].label, "Homepage, Firefox Home") } @@ -223,21 +222,17 @@ class HomePageSettingsUITests: BaseTestCase { navigator.performAction(Action.OpenNewTabFromTabTray) navigator.nowAt(NewTabScreen) if !iPad() { - mozWaitForElementToExist(app.buttons["urlBar-cancel"], timeout: 5) + mozWaitForElementToExist(app.buttons["urlBar-cancel"]) navigator.performAction(Action.CloseURLBarOpen) } mozWaitForElementToExist( - app.buttons[AccessibilityIdentifiers.FirefoxHomepage.MoreButtons.jumpBackIn], - timeout: 5 - ) - XCTAssertTrue( - app.otherElements - .cells[AccessibilityIdentifiers.FirefoxHomepage.JumpBackIn.itemCell] - .staticTexts[urlExampleLabel].exists + app.buttons[AccessibilityIdentifiers.FirefoxHomepage.MoreButtons.jumpBackIn] ) + mozWaitForElementToExist(app.otherElements + .cells[AccessibilityIdentifiers.FirefoxHomepage.JumpBackIn.itemCell] + .staticTexts[urlExampleLabel]) mozWaitForElementToExist( - app.buttons[AccessibilityIdentifiers.FirefoxHomepage.MoreButtons.jumpBackIn], - timeout: 5 + app.buttons[AccessibilityIdentifiers.FirefoxHomepage.MoreButtons.jumpBackIn] ) app.buttons[AccessibilityIdentifiers.FirefoxHomepage.MoreButtons.jumpBackIn].tap() // Tab tray is open with recently open tab @@ -245,8 +240,7 @@ class HomePageSettingsUITests: BaseTestCase { mozWaitForElementToExist( app.otherElements .cells[AccessibilityIdentifiers.FirefoxHomepage.JumpBackIn.itemCell] - .staticTexts[urlExampleLabel], - timeout: 3) + .staticTexts[urlExampleLabel]) } else { mozWaitForElementToExist(app.otherElements.cells[urlExampleLabel]) } @@ -271,17 +265,17 @@ class HomePageSettingsUITests: BaseTestCase { // On iPad we have the homepage button always present, // on iPhone we have the search button instead when we're on a new tab page navigator.performAction(Action.ClickSearchButton) - XCTAssertFalse( - app.scrollViews.cells[AccessibilityIdentifiers.FirefoxHomepage.MoreButtons.bookmarks].exists + mozWaitForElementToNotExist( + app.scrollViews.cells[AccessibilityIdentifiers.FirefoxHomepage.MoreButtons.bookmarks] ) - mozWaitForElementToExist(app.buttons["urlBar-cancel"], timeout: 3) + mozWaitForElementToExist(app.buttons["urlBar-cancel"]) navigator.performAction(Action.CloseURLBarOpen) navigator.nowAt(NewTabScreen) navigator.performAction(Action.ToggleRecentlySaved) navigator.nowAt(HomeSettings) navigator.performAction(Action.OpenNewTabFromTabTray) if !iPad() { - mozWaitForElementToExist(app.buttons["urlBar-cancel"], timeout: 3) + mozWaitForElementToExist(app.buttons["urlBar-cancel"]) navigator.performAction(Action.CloseURLBarOpen) } checkBookmarks() @@ -361,12 +355,11 @@ class HomePageSettingsUITests: BaseTestCase { // Smoketest func testCustomizeHomepage() { if !iPad() { - mozWaitForElementToExist(app.collectionViews["FxCollectionView"], timeout: TIMEOUT) + mozWaitForElementToExist(app.collectionViews["FxCollectionView"]) app.collectionViews["FxCollectionView"].swipeUp() app.collectionViews["FxCollectionView"].swipeUp() mozWaitForElementToExist( - app.cells.otherElements.buttons[AccessibilityIdentifiers.FirefoxHomepage.MoreButtons.customizeHomePage], - timeout: TIMEOUT + app.cells.otherElements.buttons[AccessibilityIdentifiers.FirefoxHomepage.MoreButtons.customizeHomePage] ) } app.cells.otherElements.buttons[AccessibilityIdentifiers.FirefoxHomepage.MoreButtons.customizeHomePage].tap() @@ -375,14 +368,14 @@ class HomePageSettingsUITests: BaseTestCase { app.navigationBars[AccessibilityIdentifiers.Settings.Homepage.homePageNavigationBar], timeout: TIMEOUT_LONG ) - XCTAssertTrue( - app.tables.cells[AccessibilityIdentifiers.Settings.Homepage.StartAtHome.always].exists + mozWaitForElementToExist( + app.tables.cells[AccessibilityIdentifiers.Settings.Homepage.StartAtHome.always] ) - XCTAssertTrue( - app.tables.cells[AccessibilityIdentifiers.Settings.Homepage.StartAtHome.disabled].exists + mozWaitForElementToExist( + app.tables.cells[AccessibilityIdentifiers.Settings.Homepage.StartAtHome.disabled] ) - XCTAssertTrue( - app.tables.cells[AccessibilityIdentifiers.Settings.Homepage.StartAtHome.afterFourHours].exists + mozWaitForElementToExist( + app.tables.cells[AccessibilityIdentifiers.Settings.Homepage.StartAtHome.afterFourHours] ) // Commented due to experimental features // XCTAssertEqual( diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/IntegrationTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/IntegrationTests.swift index 5ed7daf407ae..dd3a3f8fde1e 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/IntegrationTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/IntegrationTests.swift @@ -112,9 +112,9 @@ class IntegrationTests: BaseTestCase { // Bookmark is added by the DB // Sign into Mozilla Account navigator.openURL("example.com") - mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.trackingProtection], timeout: 5) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.trackingProtection]) navigator.goto(BrowserTabMenu) - mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.bookmark], timeout: 15) + mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.bookmark]) app.tables.otherElements[StandardImageIdentifiers.Large.bookmark].tap() navigator.nowAt(BrowserTab) signInFxAccounts() @@ -130,7 +130,7 @@ class IntegrationTests: BaseTestCase { // Wait for initial sync to complete waitForInitialSyncComplete() navigator.goto(LibraryPanel_Bookmarks) - mozWaitForElementToExist(app.tables["Bookmarks List"].cells.staticTexts["Example Domain"], timeout: 5) + mozWaitForElementToExist(app.tables["Bookmarks List"].cells.staticTexts["Example Domain"]) } func testFxASyncTabs () { @@ -143,9 +143,9 @@ class IntegrationTests: BaseTestCase { navigator.nowAt(BrowserTab) // This is only to check that the device's name changed navigator.goto(SettingsScreen) - mozWaitForElementToExist(app.tables.cells.element(boundBy: 1), timeout: 10) + mozWaitForElementToExist(app.tables.cells.element(boundBy: 1)) app.tables.cells.element(boundBy: 1).tap() - mozWaitForElementToExist(app.cells["DeviceNameSetting"].textFields["DeviceNameSettingTextField"], timeout: 10) + mozWaitForElementToExist(app.cells["DeviceNameSetting"].textFields["DeviceNameSettingTextField"]) XCTAssertEqual( app.cells["DeviceNameSetting"].textFields["DeviceNameSettingTextField"].value! as! String, "Fennec (administrator) on iOS" @@ -153,7 +153,7 @@ class IntegrationTests: BaseTestCase { // Sync again just to make sure to sync after new name is shown app.buttons["Settings"].tap() - mozWaitForElementToExist(app.staticTexts["ACCOUNT"], timeout: TIMEOUT) + mozWaitForElementToExist(app.staticTexts["ACCOUNT"]) app.tables.cells.element(boundBy: 2).tap() mozWaitForElementToExist(app.tables.staticTexts["Sync Now"], timeout: TIMEOUT_LONG) } @@ -192,7 +192,7 @@ class IntegrationTests: BaseTestCase { // Check synced History navigator.goto(LibraryPanel_History) - mozWaitForElementToExist(app.tables.cells.staticTexts[historyItemSavedOnDesktop], timeout: 5) + mozWaitForElementToExist(app.tables.cells.staticTexts[historyItemSavedOnDesktop]) } func testFxASyncPasswordDesktop () { @@ -214,7 +214,7 @@ class IntegrationTests: BaseTestCase { passcodeInput.typeText("foo\n") navigator.goto(LoginsSettings) - mozWaitForElementToExist(app.tables["Login List"], timeout: 5) + mozWaitForElementToExist(app.tables["Login List"]) XCTAssertTrue(app.tables.cells.staticTexts[loginEntry].exists, "The login saved on desktop is not synced") } @@ -233,7 +233,7 @@ class IntegrationTests: BaseTestCase { // Need to swipe to get the data on the screen on focus app.swipeDown() - mozWaitForElementToExist(app.tables.otherElements["profile1"], timeout: TIMEOUT) + mozWaitForElementToExist(app.tables.otherElements["profile1"]) XCTAssertTrue(app.tables.staticTexts[tabOpenInDesktop].exists, "The tab is not synced") } @@ -246,8 +246,8 @@ class IntegrationTests: BaseTestCase { navigator.nowAt(SettingsScreen) // Check Bookmarks navigator.goto(LibraryPanel_Bookmarks) - mozWaitForElementToExist(app.tables["Bookmarks List"], timeout: 3) - mozWaitForElementToExist(app.tables["Bookmarks List"].cells.staticTexts["Example Domain"], timeout: 5) + mozWaitForElementToExist(app.tables["Bookmarks List"]) + mozWaitForElementToExist(app.tables["Bookmarks List"].cells.staticTexts["Example Domain"]) // Check Login navigator.performAction(Action.CloseBookmarkPanel) @@ -265,18 +265,18 @@ class IntegrationTests: BaseTestCase { passcodeInput.tap() passcodeInput.typeText("foo\n") - mozWaitForElementToExist(app.tables["Login List"], timeout: 3) + mozWaitForElementToExist(app.tables["Login List"]) // Verify the login mozWaitForElementToExist(app.staticTexts["https://accounts.google.com"]) // Disconnect account navigator.goto(SettingsScreen) app.tables.cells.element(boundBy: 1).tap() - mozWaitForElementToExist(app.cells["DeviceNameSetting"].textFields["DeviceNameSettingTextField"], timeout: 10) + mozWaitForElementToExist(app.cells["DeviceNameSetting"].textFields["DeviceNameSettingTextField"]) app.cells["SignOut"].tap() - mozWaitForElementToExist(app.buttons["Disconnect"], timeout: 5) + mozWaitForElementToExist(app.buttons["Disconnect"]) app.buttons["Disconnect"].tap() sleep(3) @@ -285,21 +285,21 @@ class IntegrationTests: BaseTestCase { app.tables.cells["SignInToSync"].tap() app.buttons["EmailSignIn.button"].tap() - mozWaitForElementToExist(app.secureTextFields.element(boundBy: 0), timeout: 10) + mozWaitForElementToExist(app.secureTextFields.element(boundBy: 0)) app.secureTextFields.element(boundBy: 0).tap() app.secureTextFields.element(boundBy: 0).typeText(userState.fxaPassword!) - mozWaitForElementToExist(app.webViews.buttons.element(boundBy: 0), timeout: 5) + mozWaitForElementToExist(app.webViews.buttons.element(boundBy: 0)) app.webViews.buttons.element(boundBy: 0).tap() navigator.nowAt(SettingsScreen) mozWaitForElementToExist(app.staticTexts["GENERAL"]) app.swipeDown() - mozWaitForElementToExist(app.staticTexts["ACCOUNT"], timeout: TIMEOUT) - mozWaitForElementToExist(app.tables.staticTexts["Sync Now"], timeout: 35) + mozWaitForElementToExist(app.staticTexts["ACCOUNT"]) + mozWaitForElementToExist(app.tables.staticTexts["Sync Now"], timeout: TIMEOUT_LONG) // Check Bookmarks navigator.goto(LibraryPanel_Bookmarks) - mozWaitForElementToExist(app.tables["Bookmarks List"].cells.staticTexts["Example Domain"], timeout: 5) + mozWaitForElementToExist(app.tables["Bookmarks List"].cells.staticTexts["Example Domain"]) // Check Logins navigator.performAction(Action.CloseBookmarkPanel) @@ -311,7 +311,7 @@ class IntegrationTests: BaseTestCase { passcodeInput.tap() passcodeInput.typeText("foo\n") - mozWaitForElementToExist(app.tables["Login List"], timeout: 10) - mozWaitForElementToExist(app.staticTexts["https://accounts.google.com"], timeout: 10) + mozWaitForElementToExist(app.tables["Login List"]) + mozWaitForElementToExist(app.staticTexts["https://accounts.google.com"]) } } diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/JumpBackInTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/JumpBackInTests.swift index 51888b4837ed..cf4925ed6eb1 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/JumpBackInTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/JumpBackInTests.swift @@ -26,9 +26,12 @@ class JumpBackInTests: BaseTestCase { // "Jump Back In" is enabled by default. See Settings -> Homepage navigator.goto(HomeSettings) + mozWaitForElementToExist(app.switches["Jump Back In"]) XCTAssertEqual(app.switches["Jump Back In"].value as! String, "1") navigator.goto(NewTabScreen) + waitForTabsButton() + mozWaitForElementToExist(app.textFields["url"]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2306922 @@ -43,7 +46,7 @@ class JumpBackInTests: BaseTestCase { closeKeyboard() // "Jump Back In" section is displayed - mozWaitForElementToExist(app.cells["JumpBackInCell"].firstMatch, timeout: TIMEOUT) + mozWaitForElementToExist(app.cells["JumpBackInCell"].firstMatch) // The contextual hint box is not displayed consistently, so // I don't test for its existence. } @@ -152,7 +155,7 @@ class JumpBackInTests: BaseTestCase { navigator.openURL(path(forTestPage: "test-example.html")) mozWaitForElementToExist(app.webViews.links[website_2["link"]!], timeout: TIMEOUT_LONG) app.webViews.links[website_2["link"]!].press(forDuration: 2) - mozWaitForElementToExist(app.otherElements.collectionViews.element(boundBy: 0), timeout: TIMEOUT) + mozWaitForElementToExist(app.otherElements.collectionViews.element(boundBy: 0)) mozWaitForElementToExist(app.buttons["Open in New Tab"]) app.buttons["Open in New Tab"].tap() waitUntilPageLoad() diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/LoginsTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/LoginsTests.swift index 6bc75170b8fb..64fe66472907 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/LoginsTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/LoginsTests.swift @@ -28,15 +28,15 @@ class LoginTest: BaseTestCase { private func saveLogin(givenUrl: String) { navigator.openURL(givenUrl) waitUntilPageLoad() - mozWaitForElementToExist(app.buttons["submit"], timeout: 10) + mozWaitForElementToExist(app.buttons["submit"]) app.buttons["submit"].tap() - mozWaitForElementToExist(app.buttons["SaveLoginPrompt.saveLoginButton"], timeout: 10) + mozWaitForElementToExist(app.buttons["SaveLoginPrompt.saveLoginButton"]) app.buttons["SaveLoginPrompt.saveLoginButton"].tap() } private func openLoginsSettings() { navigator.goto(SettingsScreen) - mozWaitForElementToExist(app.cells["SignInToSync"], timeout: 5) + mozWaitForElementToExist(app.cells["SignInToSync"]) app.cells["SignInToSync"].swipeUp() navigator.goto(LoginsSettings) @@ -45,9 +45,9 @@ class LoginTest: BaseTestCase { } private func openLoginsSettingsFromBrowserTab() { - waitForExistence(app.buttons["TabToolbar.menuButton"], timeout: TIMEOUT) + waitForExistence(app.buttons["TabToolbar.menuButton"]) navigator.goto(BrowserTabMenu) - waitForExistence(app.tables.otherElements[StandardImageIdentifiers.Large.login], timeout: 5) + waitForExistence(app.tables.otherElements[StandardImageIdentifiers.Large.login]) navigator.goto(LoginsSettings) unlockLoginsView() @@ -62,7 +62,7 @@ class LoginTest: BaseTestCase { navigator.goto(LoginsSettings) unlockLoginsView() mozWaitForElementToExist(app.tables["Login List"]) - XCTAssertTrue(app.searchFields[searchPasswords].exists) + mozWaitForElementToExist(app.searchFields[searchPasswords]) XCTAssertEqual(app.tables["Login List"].cells.count, defaultNumRowsLoginsList) app.buttons["Settings"].tap() navigator.performAction(Action.OpenNewTabFromTabTray) @@ -71,9 +71,9 @@ class LoginTest: BaseTestCase { navigator.goto(LoginsSettings) unlockLoginsView() mozWaitForElementToExist(app.tables["Login List"]) - XCTAssertTrue(app.searchFields[searchPasswords].exists) - XCTAssertTrue(app.staticTexts[domain].exists) - XCTAssertTrue(app.staticTexts[domainLogin].exists) + mozWaitForElementToExist(app.searchFields[searchPasswords]) + mozWaitForElementToExist(app.staticTexts[domain]) + mozWaitForElementToExist(app.staticTexts[domainLogin]) XCTAssertEqual(app.tables["Login List"].cells.count, defaultNumRowsLoginsList + 1) } @@ -94,7 +94,7 @@ class LoginTest: BaseTestCase { saveLogin(givenUrl: testLoginPage) openLoginsSettings() mozWaitForElementToExist(app.tables["Login List"]) - XCTAssertTrue(app.staticTexts[domain].exists) + mozWaitForElementToExist(app.staticTexts[domain]) // XCTAssertTrue(app.staticTexts[domainLogin].exists) XCTAssertEqual(app.tables["Login List"].cells.count, defaultNumRowsLoginsList + 1) @@ -111,7 +111,7 @@ class LoginTest: BaseTestCase { saveLogin(givenUrl: testSecondLoginPage) openLoginsSettings() mozWaitForElementToExist(app.tables["Login List"]) - XCTAssertTrue(app.staticTexts[domain].exists) + mozWaitForElementToExist(app.staticTexts[domain]) // XCTAssertTrue(app.staticTexts[domainSecondLogin].exists) // Workaround for Bitrise specific issue. "vagrant" user is used in Bitrise. if (ProcessInfo.processInfo.environment["HOME"]!).contains(String("vagrant")) { @@ -130,8 +130,8 @@ class LoginTest: BaseTestCase { app.buttons["SaveLoginPrompt.dontSaveButton"].tap() // There should not be any login saved openLoginsSettings() - XCTAssertFalse(app.staticTexts[domain].exists) - XCTAssertFalse(app.staticTexts[domainLogin].exists) + mozWaitForElementToNotExist(app.staticTexts[domain]) + mozWaitForElementToNotExist(app.staticTexts[domainLogin]) XCTAssertEqual(app.tables["Login List"].cells.count, defaultNumRowsLoginsList) } @@ -140,20 +140,18 @@ class LoginTest: BaseTestCase { saveLogin(givenUrl: testLoginPage) navigator.goto(SettingsScreen) openLoginsSettings() - XCTAssertTrue(app.staticTexts[domain].exists) - XCTAssertTrue(app.staticTexts[domainLogin].exists) + mozWaitForElementToExist(app.staticTexts[domain]) + mozWaitForElementToExist(app.staticTexts[domainLogin]) XCTAssertTrue(app.buttons["Edit"].isHittable) app.buttons["Edit"].tap() - XCTAssertTrue(app.buttons["Select All"].exists) - XCTAssertTrue(app.staticTexts[domain].exists) - XCTAssertTrue(app.staticTexts[domainLogin].exists) + mozWaitForElementToExist(app.buttons["Select All"]) + mozWaitForElementToExist(app.staticTexts[domain]) + mozWaitForElementToExist(app.staticTexts[domainLogin]) app.staticTexts[domain].tap() mozWaitForElementToExist(app.buttons["Deselect All"]) - - XCTAssertTrue(app.buttons["Deselect All"].exists) - XCTAssertTrue(app.buttons["Delete"].exists) + mozWaitForElementToExist(app.buttons["Delete"]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2306963 @@ -167,8 +165,8 @@ class LoginTest: BaseTestCase { mozWaitForElementToExist(app.alerts["Remove Password?"]) app.alerts.buttons["Remove"].tap() mozWaitForElementToExist(app.tables["Login List"]) - XCTAssertFalse(app.staticTexts[domain].exists) - XCTAssertFalse(app.staticTexts[domainLogin].exists) + mozWaitForElementToNotExist(app.staticTexts[domain]) + mozWaitForElementToNotExist(app.staticTexts[domainLogin]) XCTAssertEqual(app.tables["Login List"].cells.count, defaultNumRowsLoginsList) } @@ -183,10 +181,10 @@ class LoginTest: BaseTestCase { app.staticTexts[domain].tap() // The login details are available waitForExistence(app.tables["Login Detail List"]) - XCTAssertTrue(app.tables.cells[loginsListURLLabel].exists) - XCTAssertTrue(app.tables.cells[loginsListUsernameLabel].exists) - XCTAssertTrue(app.tables.cells[loginsListPasswordLabel].exists) - XCTAssertTrue(app.tables.cells.staticTexts["Delete"].exists) + mozWaitForElementToExist(app.tables.cells[loginsListURLLabel]) + mozWaitForElementToExist(app.tables.cells[loginsListUsernameLabel]) + mozWaitForElementToExist(app.tables.cells[loginsListPasswordLabel]) + mozWaitForElementToExist(app.tables.cells.staticTexts["Delete"]) // Change the username app.buttons["Edit"].tap() mozWaitForElementToExist(app.tables["Login Detail List"]) @@ -200,10 +198,10 @@ class LoginTest: BaseTestCase { app.buttons["Done"].tap() // The username is correctly changed mozWaitForElementToExist(app.tables["Login Detail List"]) - XCTAssertTrue(app.tables.cells[loginsListURLLabel].exists) - XCTAssertFalse(app.tables.cells[loginsListUsernameLabel].exists) - XCTAssertTrue(app.tables.cells[loginsListUsernameLabelEdited].exists) - XCTAssertTrue(app.tables.cells[loginsListPasswordLabel].exists) + mozWaitForElementToExist(app.tables.cells[loginsListURLLabel]) + mozWaitForElementToNotExist(app.tables.cells[loginsListUsernameLabel]) + mozWaitForElementToExist(app.tables.cells[loginsListUsernameLabelEdited]) + mozWaitForElementToExist(app.tables.cells[loginsListPasswordLabel]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2306964 @@ -234,7 +232,7 @@ class LoginTest: BaseTestCase { navigator.openURL(urlLogin) waitUntilPageLoad() // Provided text fields are completely empty - mozWaitForElementToExist(app.webViews.staticTexts["Username:"], timeout: 15) + mozWaitForElementToExist(app.webViews.staticTexts["Username:"]) // Fill in the username text box app.webViews.textFields.element(boundBy: 0).tap() @@ -245,7 +243,7 @@ class LoginTest: BaseTestCase { // Submit form and choose to save the logins app.buttons["submit"].tap() - mozWaitForElementToExist(app.buttons["SaveLoginPrompt.saveLoginButton"], timeout: 5) + mozWaitForElementToExist(app.buttons["SaveLoginPrompt.saveLoginButton"]) app.buttons["SaveLoginPrompt.saveLoginButton"].tap() // Clear Data and go to test page, fields should be filled in @@ -256,7 +254,7 @@ class LoginTest: BaseTestCase { navigator.performAction(Action.OpenNewTabFromTabTray) navigator.openURL(urlLogin) waitUntilPageLoad() - mozWaitForElementToExist(app.webViews.textFields.element(boundBy: 0), timeout: 3) + mozWaitForElementToExist(app.webViews.textFields.element(boundBy: 0)) // let emailValue = app.webViews.textFields.element(boundBy: 0).value! // XCTAssertEqual(emailValue as! String, mailLogin) // let passwordValue = app.webViews.secureTextFields.element(boundBy: 0).value! @@ -269,7 +267,7 @@ class LoginTest: BaseTestCase { closeURLBar() navigator.goto(LoginsSettings) unlockLoginsView() - mozWaitForElementToExist(app.tables["Login List"], timeout: 15) + mozWaitForElementToExist(app.tables["Login List"]) mozWaitForElementToExist(app.navigationBars["Passwords"]) mozWaitForElementToExist(app.staticTexts["No passwords found"]) mozWaitForElementToExist(app.buttons["Add"]) @@ -286,8 +284,8 @@ class LoginTest: BaseTestCase { openLoginsSettingsFromBrowserTab() createLoginManually() // The login is correctly created. - XCTAssertTrue(app.tables["Login List"].staticTexts["https://testweb"].exists) - XCTAssertTrue(app.tables["Login List"].staticTexts["foo"].exists) + mozWaitForElementToExist(app.tables["Login List"].staticTexts["https://testweb"]) + mozWaitForElementToExist(app.tables["Login List"].staticTexts["foo"]) // Repeat previous step, adding the same login createLoginManually() // The login cannot be duplicated @@ -297,8 +295,8 @@ class LoginTest: BaseTestCase { private func createLoginManually() { app.buttons["Add"].tap() - mozWaitForElementToExist(app.tables["Add Credential"], timeout: 15) - XCTAssertTrue(app.tables["Add Credential"].cells.staticTexts.containingText("Web").element.exists) + mozWaitForElementToExist(app.tables["Add Credential"]) + mozWaitForElementToExist(app.tables["Add Credential"].cells.staticTexts.containingText("Web").element) mozWaitForElementToExist(app.tables["Add Credential"].cells.staticTexts["Username"]) mozWaitForElementToExist(app.tables["Add Credential"].cells.staticTexts["Password"]) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/MicrosurveyTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/MicrosurveyTests.swift index b54313b241d8..bcddf3142ffb 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/MicrosurveyTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/MicrosurveyTests.swift @@ -15,9 +15,9 @@ final class MicrosurveyTests: BaseTestCase { func testShowMicrosurveyPromptFromHomepageTrigger() { generateTriggerForMicrosurvey() - XCTAssertTrue(app.buttons[AccessibilityIdentifiers.Microsurvey.Prompt.takeSurveyButton].exists) - XCTAssertTrue(app.images[AccessibilityIdentifiers.Microsurvey.Prompt.firefoxLogo].exists) - XCTAssertTrue(app.buttons[AccessibilityIdentifiers.Microsurvey.Prompt.closeButton].exists) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Microsurvey.Prompt.takeSurveyButton]) + mozWaitForElementToExist(app.images[AccessibilityIdentifiers.Microsurvey.Prompt.firefoxLogo]) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Microsurvey.Prompt.closeButton]) } func testURLBorderHiddenWhenMicrosurveyPromptShown() throws { @@ -40,9 +40,9 @@ final class MicrosurveyTests: BaseTestCase { func testCloseButtonDismissesMicrosurveyPrompt() { generateTriggerForMicrosurvey() app.buttons[AccessibilityIdentifiers.Microsurvey.Prompt.closeButton].tap() - XCTAssertFalse(app.buttons[AccessibilityIdentifiers.Microsurvey.Prompt.takeSurveyButton].exists) - XCTAssertFalse(app.images[AccessibilityIdentifiers.Microsurvey.Prompt.firefoxLogo].exists) - XCTAssertFalse(app.images[AccessibilityIdentifiers.Microsurvey.Prompt.closeButton].exists) + mozWaitForElementToNotExist(app.buttons[AccessibilityIdentifiers.Microsurvey.Prompt.takeSurveyButton]) + mozWaitForElementToNotExist(app.images[AccessibilityIdentifiers.Microsurvey.Prompt.firefoxLogo]) + mozWaitForElementToNotExist(app.images[AccessibilityIdentifiers.Microsurvey.Prompt.closeButton]) } func testShowMicrosurvey() { @@ -50,8 +50,8 @@ final class MicrosurveyTests: BaseTestCase { let continueButton = app.buttons[AccessibilityIdentifiers.Microsurvey.Prompt.takeSurveyButton] continueButton.tap() - XCTAssertTrue(app.images[AccessibilityIdentifiers.Microsurvey.Survey.firefoxLogo].exists) - XCTAssertTrue(app.buttons[AccessibilityIdentifiers.Microsurvey.Survey.closeButton].exists) + mozWaitForElementToExist(app.images[AccessibilityIdentifiers.Microsurvey.Survey.firefoxLogo]) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Microsurvey.Survey.closeButton]) let tablesQuery = app.scrollViews.otherElements.tables let firstOption = tablesQuery.cells.firstMatch firstOption.tap() @@ -72,11 +72,11 @@ final class MicrosurveyTests: BaseTestCase { app.buttons[AccessibilityIdentifiers.Microsurvey.Survey.closeButton].tap() - XCTAssertFalse(app.images[AccessibilityIdentifiers.Microsurvey.Survey.firefoxLogo].exists) - XCTAssertFalse(app.buttons[AccessibilityIdentifiers.Microsurvey.Survey.closeButton].exists) - XCTAssertFalse(app.buttons[AccessibilityIdentifiers.Microsurvey.Prompt.takeSurveyButton].exists) - XCTAssertFalse(app.images[AccessibilityIdentifiers.Microsurvey.Prompt.firefoxLogo].exists) - XCTAssertFalse(app.images[AccessibilityIdentifiers.Microsurvey.Prompt.closeButton].exists) + mozWaitForElementToNotExist(app.images[AccessibilityIdentifiers.Microsurvey.Survey.firefoxLogo]) + mozWaitForElementToNotExist(app.buttons[AccessibilityIdentifiers.Microsurvey.Survey.closeButton]) + mozWaitForElementToNotExist(app.buttons[AccessibilityIdentifiers.Microsurvey.Prompt.takeSurveyButton]) + mozWaitForElementToNotExist(app.images[AccessibilityIdentifiers.Microsurvey.Prompt.firefoxLogo]) + mozWaitForElementToNotExist(app.images[AccessibilityIdentifiers.Microsurvey.Prompt.closeButton]) } private func generateTriggerForMicrosurvey() { diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/NavigationTest.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/NavigationTest.swift index ddcbb7c8a0d1..57bb8c7a6396 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/NavigationTest.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/NavigationTest.swift @@ -24,7 +24,7 @@ class NavigationTest: BaseTestCase { // https://testrail.stage.mozaws.net/index.php?/cases/view/2441488 func testNavigation() { let urlPlaceholder = "Search or enter address" - XCTAssert(app.textFields["url"].exists) + mozWaitForElementToExist(app.textFields["url"]) let defaultValuePlaceholder = app.textFields["url"].placeholderValue! // Check the url placeholder text and that the back and forward buttons are disabled @@ -101,7 +101,7 @@ class NavigationTest: BaseTestCase { closeButtonFxView.tap() } - // Because the Settings menu does not stretch tot the top we need a different function to check + // Because the Settings menu does not stretch tot the top we need a different function to check // if the Firefox Sync screen is shown private func checkFirefoxSyncScreenShownViaSettings() { mozWaitForElementToExist( @@ -152,12 +152,12 @@ class NavigationTest: BaseTestCase { // Smoketest func testLongPressLinkOptions() { openContextMenuForArticleLink() - XCTAssertTrue(app.buttons["Open in New Tab"].exists, "The option is not shown") - XCTAssertTrue(app.buttons["Open in New Private Tab"].exists, "The option is not shown") - XCTAssertTrue(app.buttons["Copy Link"].exists, "The option is not shown") - XCTAssertTrue(app.buttons["Download Link"].exists, "The option is not shown") - XCTAssertTrue(app.buttons["Share Link"].exists, "The option is not shown") - XCTAssertTrue(app.buttons["Bookmark Link"].exists, "The option is not shown") + mozWaitForElementToExist(app.buttons["Open in New Tab"]) + mozWaitForElementToExist(app.buttons["Open in New Private Tab"]) + mozWaitForElementToExist(app.buttons["Copy Link"]) + mozWaitForElementToExist(app.buttons["Download Link"]) + mozWaitForElementToExist(app.buttons["Share Link"]) + mozWaitForElementToExist(app.buttons["Bookmark Link"]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2441496 @@ -279,7 +279,7 @@ class NavigationTest: BaseTestCase { // There should be one item downloaded. It's name and size should be shown let downloadedList = app.tables["DownloadsTable"].cells.count XCTAssertEqual(downloadedList, 1, "The number of items in the downloads table is not correct") - XCTAssertTrue(app.tables.cells.staticTexts["example-domains.html"].exists) + mozWaitForElementToExist(app.tables.cells.staticTexts["example-domains.html"]) // Tap on the just downloaded link to check that the web page is loaded app.tables.cells.staticTexts["example-domains.html"].tap() @@ -291,17 +291,17 @@ class NavigationTest: BaseTestCase { func testShareLink() { longPressLinkOptions(optionSelected: "Share Link") if #available(iOS 16, *) { - mozWaitForElementToExist(app.cells["Copy"], timeout: TIMEOUT) + mozWaitForElementToExist(app.cells["Copy"]) } else { - mozWaitForElementToExist(app.buttons["Copy"], timeout: TIMEOUT) + mozWaitForElementToExist(app.buttons["Copy"]) } if !iPad() { - mozWaitForElementToExist(app.scrollViews.staticTexts["Messages"], timeout: TIMEOUT) + mozWaitForElementToExist(app.scrollViews.staticTexts["Messages"]) } if #unavailable(iOS 17) { - mozWaitForElementToExist(app.scrollViews.cells["XCElementSnapshotPrivilegedValuePlaceholder"], timeout: TIMEOUT) + mozWaitForElementToExist(app.scrollViews.cells["XCElementSnapshotPrivilegedValuePlaceholder"]) } else { - mozWaitForElementToExist(app.scrollViews.staticTexts["Reminders"], timeout: TIMEOUT) + mozWaitForElementToExist(app.scrollViews.staticTexts["Reminders"]) } } @@ -311,17 +311,17 @@ class NavigationTest: BaseTestCase { navigator.toggleOn(userState.isPrivate, withAction: Action.TogglePrivateMode) longPressLinkOptions(optionSelected: "Share Link") if #available(iOS 16, *) { - mozWaitForElementToExist(app.cells["Copy"], timeout: TIMEOUT) + mozWaitForElementToExist(app.cells["Copy"]) } else { - mozWaitForElementToExist(app.buttons["Copy"], timeout: TIMEOUT) + mozWaitForElementToExist(app.buttons["Copy"]) } if !iPad() { - mozWaitForElementToExist(app.scrollViews.staticTexts["Messages"], timeout: TIMEOUT) + mozWaitForElementToExist(app.scrollViews.staticTexts["Messages"]) } if #unavailable(iOS 17) { - mozWaitForElementToExist(app.scrollViews.cells["XCElementSnapshotPrivilegedValuePlaceholder"], timeout: TIMEOUT) + mozWaitForElementToExist(app.scrollViews.cells["XCElementSnapshotPrivilegedValuePlaceholder"]) } else { - mozWaitForElementToExist(app.scrollViews.staticTexts["Reminders"], timeout: TIMEOUT) + mozWaitForElementToExist(app.scrollViews.staticTexts["Reminders"]) } } @@ -368,7 +368,7 @@ class NavigationTest: BaseTestCase { navigator.nowAt(NewTabScreen) navigator.openURL("https://expired.badssl.com/") - mozWaitForElementToExist(app.buttons["Advanced"], timeout: TIMEOUT) + mozWaitForElementToExist(app.buttons["Advanced"]) app.buttons["Advanced"].tap() mozWaitForElementToExist(app.links["Visit site anyway"]) @@ -391,35 +391,35 @@ class NavigationTest: BaseTestCase { navigator.openURL(path(forTestPage: "test-mozilla-org.html")) waitUntilPageLoad() navigator.openURL(path(forTestPage: "test-window-opener.html")) - mozWaitForElementToExist(app.links["link-created-by-parent"], timeout: TIMEOUT) + mozWaitForElementToExist(app.links["link-created-by-parent"]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2307020 // Smoketest func testVerifyBrowserTabMenu() { - mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton], timeout: TIMEOUT) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton]) navigator.nowAt(NewTabScreen) navigator.goto(BrowserTabMenu) mozWaitForElementToExist(app.tables["Context Menu"]) - XCTAssertTrue(app.tables.otherElements[StandardImageIdentifiers.Large.bookmarkTrayFill].exists) - XCTAssertTrue(app.tables.otherElements[StandardImageIdentifiers.Large.history].exists) - XCTAssertTrue(app.tables.otherElements[StandardImageIdentifiers.Large.download].exists) - XCTAssertTrue(app.tables.otherElements[StandardImageIdentifiers.Large.readingList].exists) - XCTAssertTrue(app.tables.otherElements[StandardImageIdentifiers.Large.login].exists) - XCTAssertTrue(app.tables.otherElements[StandardImageIdentifiers.Large.sync].exists) - XCTAssertTrue(app.tables.otherElements[StandardImageIdentifiers.Large.nightMode].exists) - XCTAssertTrue(app.tables.otherElements[StandardImageIdentifiers.Large.whatsNew].exists) - XCTAssertTrue(app.tables.otherElements[StandardImageIdentifiers.Large.helpCircle].exists) - XCTAssertTrue(app.tables.otherElements[StandardImageIdentifiers.Large.edit].exists) - XCTAssertTrue(app.tables.otherElements[StandardImageIdentifiers.Large.settings].exists) + mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.bookmarkTrayFill]) + mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.history]) + mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.download]) + mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.readingList]) + mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.login]) + mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.sync]) + mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.nightMode]) + mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.whatsNew]) + mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.helpCircle]) + mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.edit]) + mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.settings]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2441775 // Smoketest func testURLBar() { let urlBar = app.textFields["url"] - mozWaitForElementToExist(urlBar, timeout: TIMEOUT) + mozWaitForElementToExist(urlBar) urlBar.tap() let addressBar = app.textFields["address"] @@ -446,7 +446,7 @@ class NavigationTest: BaseTestCase { mozWaitForElementToExist(app.otherElements["Tabs Tray"].cells.staticTexts["Example Domain"]) let numTabs = app.otherElements["Tabs Tray"].cells.count XCTAssertEqual(numTabs, 2, "Total number of opened tabs should be 2") - XCTAssertTrue(app.otherElements["Tabs Tray"].cells.elementContainingText("Example Domain.").exists) + mozWaitForElementToExist(app.otherElements["Tabs Tray"].cells.elementContainingText("Example Domain.")) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2441773 @@ -459,7 +459,7 @@ class NavigationTest: BaseTestCase { navigator.goto(TabTray) var numTabs = app.otherElements["Tabs Tray"].cells.count XCTAssertEqual(numTabs, 1, "Total number of regulat opened tabs should be 1") - XCTAssertTrue(app.otherElements["Tabs Tray"].cells.elementContainingText("Example Domain.").exists) + mozWaitForElementToExist(app.otherElements["Tabs Tray"].cells.elementContainingText("Example Domain.")) if iPad() { app.buttons["Private"].tap() } else { @@ -467,7 +467,7 @@ class NavigationTest: BaseTestCase { } numTabs = app.otherElements["Tabs Tray"].cells.count XCTAssertEqual(numTabs, 1, "Total number of private opened tabs should be 1") - XCTAssertTrue(app.otherElements["Tabs Tray"].cells.staticTexts["Example Domains"].exists) + mozWaitForElementToExist(app.otherElements["Tabs Tray"].cells.staticTexts["Example Domains"]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2441774 @@ -478,14 +478,14 @@ class NavigationTest: BaseTestCase { app.buttons["Bookmark Link"].tap() // The link has been added to the Bookmarks panel in Library navigator.goto(LibraryPanel_Bookmarks) - mozWaitForElementToExist(app.tables["Bookmarks List"], timeout: 5) - XCTAssertTrue(app.tables["Bookmarks List"].staticTexts[website_2["link"]!].exists) + mozWaitForElementToExist(app.tables["Bookmarks List"]) + mozWaitForElementToExist(app.tables["Bookmarks List"].staticTexts[website_2["link"]!]) } private func openContextMenuForArticleLink() { navigator.openURL(path(forTestPage: "test-example.html")) mozWaitForElementToExist(app.webViews.links[website_2["link"]!], timeout: TIMEOUT_LONG) app.webViews.links[website_2["link"]!].press(forDuration: 2) - mozWaitForElementToExist(app.otherElements.collectionViews.element(boundBy: 0), timeout: TIMEOUT) + mozWaitForElementToExist(app.otherElements.collectionViews.element(boundBy: 0)) } } diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/NewTabSettings.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/NewTabSettings.swift index 53fcc89fc81c..0861a512cd8d 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/NewTabSettings.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/NewTabSettings.swift @@ -6,22 +6,28 @@ import XCTest let websiteUrl = "www.mozilla.org" class NewTabSettingsTest: BaseTestCase { + override func setUp() { + super.setUp() + waitForTabsButton() + mozWaitForElementToExist(app.textFields["url"]) + } + // https://testrail.stage.mozaws.net/index.php?/cases/view/2307026 // Smoketest func testCheckNewTabSettingsByDefault() { - mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton], timeout: 5) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton]) navigator.nowAt(NewTabScreen) navigator.goto(NewTabSettings) mozWaitForElementToExist(app.navigationBars["New Tab"]) - XCTAssertTrue(app.tables.cells["Firefox Home"].exists) - XCTAssertTrue(app.tables.cells["Blank Page"].exists) - XCTAssertTrue(app.tables.cells["NewTabAsCustomURL"].exists) + mozWaitForElementToExist(app.tables.cells["Firefox Home"]) + mozWaitForElementToExist(app.tables.cells["Blank Page"]) + mozWaitForElementToExist(app.tables.cells["NewTabAsCustomURL"]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2307027 // Smoketest func testChangeNewTabSettingsShowBlankPage() { - mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton], timeout: 5) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton]) navigator.nowAt(NewTabScreen) navigator.goto(NewTabSettings) mozWaitForElementToExist(app.navigationBars["New Tab"]) @@ -45,7 +51,7 @@ class NewTabSettingsTest: BaseTestCase { navigator.nowAt(NewTabScreen) navigator.performAction(Action.SelectNewTabAsBlankPage) navigator.performAction(Action.OpenNewTabFromTabTray) - mozWaitForElementToExist(app.buttons["urlBar-cancel"], timeout: TIMEOUT) + mozWaitForElementToExist(app.buttons["urlBar-cancel"]) navigator.performAction(Action.CloseURLBarOpen) navigator.nowAt(NewTabScreen) mozWaitForElementToNotExist( @@ -67,8 +73,7 @@ class NewTabSettingsTest: BaseTestCase { navigator.goto(NewTabSettings) mozWaitForElementToExist(app.navigationBars["New Tab"]) // Check the placeholder value - let placeholderValue = app.textFields["NewTabAsCustomURLTextField"].value as! String - XCTAssertEqual(placeholderValue, "Custom URL") + mozWaitForValueContains(app.textFields["NewTabAsCustomURLTextField"], value: "Custom URL") navigator.performAction(Action.SelectNewTabAsCustomURL) // Check the value typed app.textFields["NewTabAsCustomURLTextField"].typeText("mozilla.org") @@ -80,7 +85,7 @@ class NewTabSettingsTest: BaseTestCase { navigator.nowAt(NewTabScreen) // Check that website is open - mozWaitForElementToExist(app.webViews.firstMatch, timeout: 20) + mozWaitForElementToExist(app.webViews.firstMatch, timeout: TIMEOUT_LONG) mozWaitForValueContains(app.textFields["url"], value: "mozilla") } @@ -112,7 +117,7 @@ class NewTabSettingsTest: BaseTestCase { // Smoketest func testKeyboardRaisedWhenTabOpenedFromTabTray() { // Add New tab and set it as Blank - mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton], timeout: 5) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton]) navigator.nowAt(NewTabScreen) navigator.goto(NewTabSettings) mozWaitForElementToExist(app.navigationBars["New Tab"]) @@ -133,7 +138,7 @@ class NewTabSettingsTest: BaseTestCase { // Smoketest func testNewTabCustomURLKeyboardNotRaised() { // Set a custom URL - mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton], timeout: 5) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton]) navigator.nowAt(NewTabScreen) navigator.goto(NewTabSettings) navigator.performAction(Action.SelectNewTabAsCustomURL) @@ -168,7 +173,7 @@ class NewTabSettingsTest: BaseTestCase { XCTAssertTrue(addressBar.value(forKey: "hasKeyboardFocus") as? Bool ?? false) XCTAssertTrue(app.keyboards.element.isVisible(), "The keyboard is not shown") // Tap the back button - mozWaitForElementToExist(app.buttons["urlBar-cancel"], timeout: TIMEOUT) + mozWaitForElementToExist(app.buttons["urlBar-cancel"]) navigator.performAction(Action.CloseURLBarOpen) // The keyboard is dismissed and the URL is unfocused mozWaitForElementToExist(app.textFields["url"]) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/OnboardingTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/OnboardingTests.swift index 27eaf027658b..fb0ce7285479 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/OnboardingTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/OnboardingTests.swift @@ -23,29 +23,27 @@ class OnboardingTests: BaseTestCase { func testFirstRunTour() { // Complete the First run from first screen to the latest one // Check that the first's tour screen is shown as well as all the elements in there - mozWaitForElementToExist(app.images["\(rootA11yId)ImageView"], timeout: 15) - XCTAssertTrue(app.images["\(rootA11yId)ImageView"].exists) - XCTAssertTrue(app.staticTexts["\(rootA11yId)TitleLabel"].exists) - XCTAssertTrue(app.staticTexts["\(rootA11yId)DescriptionLabel"].exists) - XCTAssertTrue(app.buttons["\(rootA11yId)PrimaryButton"].exists) - XCTAssertTrue(app.buttons["\(rootA11yId)SecondaryButton"].exists) - XCTAssertTrue(app.buttons["\(AccessibilityIdentifiers.Onboarding.closeButton)"].exists) - XCTAssertTrue(app.pageIndicators["\(AccessibilityIdentifiers.Onboarding.pageControl)"].exists) + mozWaitForElementToExist(app.images["\(rootA11yId)ImageView"]) + mozWaitForElementToExist(app.staticTexts["\(rootA11yId)TitleLabel"]) + mozWaitForElementToExist(app.staticTexts["\(rootA11yId)DescriptionLabel"]) + mozWaitForElementToExist(app.buttons["\(rootA11yId)PrimaryButton"]) + mozWaitForElementToExist(app.buttons["\(rootA11yId)SecondaryButton"]) + mozWaitForElementToExist(app.buttons["\(AccessibilityIdentifiers.Onboarding.closeButton)"]) + mozWaitForElementToExist(app.pageIndicators["\(AccessibilityIdentifiers.Onboarding.pageControl)"]) // Swipe to the second screen app.buttons["\(rootA11yId)SecondaryButton"].tap() currentScreen += 1 - mozWaitForElementToExist(app.images["\(rootA11yId)ImageView"], timeout: 15) - XCTAssertTrue(app.images["\(rootA11yId)ImageView"].exists) - XCTAssertTrue(app.staticTexts["\(rootA11yId)TitleLabel"].exists) - XCTAssertTrue(app.staticTexts["\(rootA11yId)DescriptionLabel"].exists) - XCTAssertTrue(app.buttons["\(rootA11yId)PrimaryButton"].exists) - XCTAssertTrue(app.buttons["\(rootA11yId)SecondaryButton"].exists) + mozWaitForElementToExist(app.images["\(rootA11yId)ImageView"]) + mozWaitForElementToExist(app.staticTexts["\(rootA11yId)TitleLabel"]) + mozWaitForElementToExist(app.staticTexts["\(rootA11yId)DescriptionLabel"]) + mozWaitForElementToExist(app.buttons["\(rootA11yId)PrimaryButton"]) + mozWaitForElementToExist(app.buttons["\(rootA11yId)SecondaryButton"]) // Swipe to the third screen app.buttons["\(rootA11yId)SecondaryButton"].tap() currentScreen += 1 - mozWaitForElementToExist(app.images["\(rootA11yId)ImageView"], timeout: 15) + mozWaitForElementToExist(app.images["\(rootA11yId)ImageView"]) XCTAssertTrue(app.images["\(rootA11yId)ImageView"].exists) XCTAssertTrue(app.staticTexts["\(rootA11yId)TitleLabel"].exists) XCTAssertTrue(app.staticTexts["\(rootA11yId)DescriptionLabel"].exists) @@ -102,18 +100,18 @@ class OnboardingTests: BaseTestCase { let mySubstring = textUrl[range] let releaseVersion = String(mySubstring) - XCTAssertTrue(app.staticTexts[releaseVersion].exists) + mozWaitForElementToExist(app.staticTexts[releaseVersion]) mozWaitForValueContains( app.textFields["url"], value: "www.mozilla.org/en-US/firefox/ios/" + releaseVersion + "/releasenotes/" ) - XCTAssertTrue(app.staticTexts["Release Notes"].exists) + mozWaitForElementToExist(app.staticTexts["Release Notes"]) if iPad() { - XCTAssertTrue( - app.staticTexts["Firefox for iOS \(releaseVersion), See All New Features, Updates and Fixes"].exists + mozWaitForElementToExist( + app.staticTexts["Firefox for iOS \(releaseVersion), See All New Features, Updates and Fixes"] ) } - XCTAssertTrue(app.staticTexts["Firefox for iOS Release"].exists) - XCTAssertTrue(app.staticTexts["Get the most recent version"].exists) + mozWaitForElementToExist(app.staticTexts["Firefox for iOS Release"]) + mozWaitForElementToExist(app.staticTexts["Get the most recent version"]) } } diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/OpeningScreenTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/OpeningScreenTests.swift index e8601be815be..0685b0d49317 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/OpeningScreenTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/OpeningScreenTests.swift @@ -4,6 +4,12 @@ import Foundation class OpeningScreenTests: BaseTestCase { + override func setUp() { + super.setUp() + waitForTabsButton() + mozWaitForElementToExist(app.textFields["url"]) + } + // https://testrail.stage.mozaws.net/index.php?/cases/view/2307039 func testLastOpenedTab() { // Open a web page diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/PerformanceTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/PerformanceTests.swift index 4832cba150d1..805ab28e4b16 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/PerformanceTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/PerformanceTests.swift @@ -87,8 +87,8 @@ class PerformanceTests: BaseTestCase { let tabsButtonNumber = app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton].staticTexts["20"] let doneButton = app.buttons[AccessibilityIdentifiers.TabTray.doneButton] - mozWaitForElementToExist(tabsButton, timeout: TIMEOUT) - mozWaitForElementToExist(tabsButtonNumber, timeout: TIMEOUT) + mozWaitForElementToExist(tabsButton) + mozWaitForElementToExist(tabsButtonNumber) measure(metrics: [ XCTClockMetric(), // to measure timeClock Mon @@ -96,9 +96,9 @@ class PerformanceTests: BaseTestCase { XCTStorageMetric(), // to measure storage consuming XCTMemoryMetric()]) { // go to tab tray - mozWaitForElementToExist(tabsButton, timeout: TIMEOUT) + mozWaitForElementToExist(tabsButton) tabsButton.tap() - mozWaitForElementToExist(doneButton, timeout: TIMEOUT) + mozWaitForElementToExist(doneButton) doneButton.tap() } // Handle termination ourselves as it sometimes hangs when given to xctrunner @@ -111,8 +111,8 @@ class PerformanceTests: BaseTestCase { let tabsButtonNumber = app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton].staticTexts["∞"] let doneButton = app.buttons[AccessibilityIdentifiers.TabTray.doneButton] - mozWaitForElementToExist(tabsButton, timeout: TIMEOUT) - mozWaitForElementToExist(tabsButtonNumber, timeout: TIMEOUT) + mozWaitForElementToExist(tabsButton) + mozWaitForElementToExist(tabsButtonNumber) measure(metrics: [ XCTClockMetric(), // to measure timeClock Mon @@ -120,9 +120,9 @@ class PerformanceTests: BaseTestCase { XCTStorageMetric(), // to measure storage consuming XCTMemoryMetric()]) { // go to tab tray - mozWaitForElementToExist(tabsButton, timeout: TIMEOUT) + mozWaitForElementToExist(tabsButton) tabsButton.tap() - mozWaitForElementToExist(doneButton, timeout: TIMEOUT) + mozWaitForElementToExist(doneButton) doneButton.tap() } // Handle termination ourselves as it sometimes hangs when given to xctrunner @@ -132,7 +132,7 @@ class PerformanceTests: BaseTestCase { func testPerfHistory1startUp() { // Warning: Avoid using mozWaitForElementToExist as it is up to 25x less performant let tabsButton = app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton] - mozWaitForElementToExist(tabsButton, timeout: TIMEOUT) + mozWaitForElementToExist(tabsButton) app.terminate() measure(metrics: [ @@ -143,7 +143,7 @@ class PerformanceTests: BaseTestCase { XCTMemoryMetric()]) { // activity measurement here app.launch() - mozWaitForElementToExist(tabsButton, timeout: TIMEOUT) + mozWaitForElementToExist(tabsButton) app.terminate() } // Handle termination ourselves as it sometimes hangs when given to xctrunner @@ -153,14 +153,14 @@ class PerformanceTests: BaseTestCase { func testPerfHistory1openMenu() { // Warning: Avoid using mozWaitForElementToExist as it is up to 25x less performant let tabsButton = app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton] - mozWaitForElementToExist(tabsButton, timeout: TIMEOUT) + mozWaitForElementToExist(tabsButton) navigator.goto(LibraryPanel_History) // Ensure 'History List' exists before taking a snapshot to avoid expensive retries. // Return firstMatch to avoid traversing the entire { Window, Window } element tree. let historyList = app.tables["History List"].firstMatch - mozWaitForElementToExist(historyList, timeout: TIMEOUT) + mozWaitForElementToExist(historyList) measure(metrics: [ XCTMemoryMetric(), @@ -174,7 +174,7 @@ class PerformanceTests: BaseTestCase { let historyListCells = historyListSnapshot.children.filter { $0.elementType == .cell } let historyItems = historyListCells.dropFirst() - // Warning: If the history database used for this test is updated, so will the date of + // Warning: If the history database used for this test is updated, so will the date of // those history items. This means as those history items age, they will fall into older // buckets, causing new cells to be created representing this new age bucket // (i.e. 'yesterday', 'a week', etc) where the 100 entries will be split across multiple age @@ -193,7 +193,7 @@ class PerformanceTests: BaseTestCase { func testPerfHistory100startUp() { // Warning: Avoid using mozWaitForElementToExist as it is up to 25x less performant let tabsButton = app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton] - mozWaitForElementToExist(tabsButton, timeout: TIMEOUT) + mozWaitForElementToExist(tabsButton) app.terminate() measure(metrics: [ @@ -204,7 +204,7 @@ class PerformanceTests: BaseTestCase { XCTMemoryMetric()]) { // activity measurement here app.launch() - mozWaitForElementToExist(tabsButton, timeout: TIMEOUT) + mozWaitForElementToExist(tabsButton) app.terminate() } // Handle termination ourselves as it sometimes hangs when given to xctrunner @@ -214,14 +214,14 @@ class PerformanceTests: BaseTestCase { func testPerfHistory100openMenu() { // Warning: Avoid using mozWaitForElementToExist as it is up to 25x less performant let tabsButton = app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton] - mozWaitForElementToExist(tabsButton, timeout: TIMEOUT) + mozWaitForElementToExist(tabsButton) navigator.goto(LibraryPanel_History) // Ensure 'History List' exists before taking a snapshot to avoid expensive retries. // Return firstMatch to avoid traversing the entire { Window, Window } element tree. let historyList = app.tables["History List"].firstMatch - mozWaitForElementToExist(historyList, timeout: TIMEOUT) + mozWaitForElementToExist(historyList) measure(metrics: [ XCTMemoryMetric(), @@ -254,7 +254,7 @@ class PerformanceTests: BaseTestCase { func testPerfBookmarks1startUp() { // Warning: Avoid using mozWaitForElementToExist as it is up to 25x less performant let tabsButton = app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton] - mozWaitForElementToExist(tabsButton, timeout: TIMEOUT) + mozWaitForElementToExist(tabsButton) app.terminate() measure(metrics: [ @@ -265,7 +265,7 @@ class PerformanceTests: BaseTestCase { XCTMemoryMetric()]) { // activity measurement here app.launch() - mozWaitForElementToExist(tabsButton, timeout: TIMEOUT) + mozWaitForElementToExist(tabsButton) app.terminate() } // Handle termination ourselves as it sometimes hangs when given to xctrunner @@ -275,14 +275,14 @@ class PerformanceTests: BaseTestCase { func testPerfBookmarks1openMenu() { // Warning: Avoid using mozWaitForElementToExist as it is up to 25x less performant let tabsButton = app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton] - mozWaitForElementToExist(tabsButton, timeout: TIMEOUT) + mozWaitForElementToExist(tabsButton) navigator.goto(LibraryPanel_Bookmarks) // Ensure 'Bookmarks List' exists before taking a snapshot to avoid expensive retries. // Return firstMatch to avoid traversing the entire { Window, Window } element tree. let bookmarksList = app.tables["Bookmarks List"].firstMatch - mozWaitForElementToExist(bookmarksList, timeout: TIMEOUT) + mozWaitForElementToExist(bookmarksList) measure(metrics: [ XCTMemoryMetric(), @@ -311,7 +311,7 @@ class PerformanceTests: BaseTestCase { func testPerfBookmarks100startUp() { // Warning: Avoid using mozWaitForElementToExist as it is up to 25x less performant let tabsButton = app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton] - mozWaitForElementToExist(tabsButton, timeout: TIMEOUT) + mozWaitForElementToExist(tabsButton) app.terminate() measure(metrics: [ @@ -322,7 +322,7 @@ class PerformanceTests: BaseTestCase { XCTMemoryMetric()]) { // Activity measurement here app.launch() - mozWaitForElementToExist(tabsButton, timeout: TIMEOUT) + mozWaitForElementToExist(tabsButton) app.terminate() } // Handle termination ourselves as it sometimes hangs when given to xctrunner @@ -332,14 +332,14 @@ class PerformanceTests: BaseTestCase { func testPerfBookmarks100openMenu() { // Warning: Avoid using mozWaitForElementToExist as it is up to 25x less performant let tabsButton = app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton] - mozWaitForElementToExist(tabsButton, timeout: TIMEOUT) + mozWaitForElementToExist(tabsButton) navigator.goto(LibraryPanel_Bookmarks) // Ensure 'Bookmarks List' exists before taking a snapshot to avoid expensive retries. // Return firstMatch to avoid traversing the entire { Window, Window } element tree. let bookmarksList = app.tables["Bookmarks List"].firstMatch - mozWaitForElementToExist(bookmarksList, timeout: TIMEOUT) + mozWaitForElementToExist(bookmarksList) measure(metrics: [ XCTMemoryMetric(), @@ -368,7 +368,7 @@ class PerformanceTests: BaseTestCase { func testPerfBookmarks1000startUp() { // Warning: Avoid using mozWaitForElementToExist as it is up to 25x less performant let tabsButton = app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton] - mozWaitForElementToExist(tabsButton, timeout: TIMEOUT) + mozWaitForElementToExist(tabsButton) app.terminate() measure(metrics: [ @@ -379,7 +379,7 @@ class PerformanceTests: BaseTestCase { XCTMemoryMetric()]) { // Activity measurement here app.launch() - mozWaitForElementToExist(tabsButton, timeout: TIMEOUT) + mozWaitForElementToExist(tabsButton) app.terminate() } // Handle termination ourselves as it sometimes hangs when given to xctrunner @@ -389,14 +389,14 @@ class PerformanceTests: BaseTestCase { func testPerfBookmarks1000openMenu() { // Warning: Avoid using mozWaitForElementToExist as it is up to 25x less performant let tabsButton = app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton] - mozWaitForElementToExist(tabsButton, timeout: TIMEOUT) + mozWaitForElementToExist(tabsButton) navigator.goto(LibraryPanel_Bookmarks) // Ensure 'Bookmarks List' exists before taking a snapshot to avoid expensive retries. // Return firstMatch to avoid traversing the entire { Window, Window } element tree. let bookmarksList = app.tables["Bookmarks List"].firstMatch - mozWaitForElementToExist(bookmarksList, timeout: TIMEOUT) + mozWaitForElementToExist(bookmarksList) measure(metrics: [ XCTMemoryMetric(), diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/PhotonActionSheetTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/PhotonActionSheetTests.swift index b1c001dc320b..c4fa07086bd6 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/PhotonActionSheetTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/PhotonActionSheetTests.swift @@ -76,11 +76,11 @@ class PhotonActionSheetTests: BaseTestCase { if #unavailable(iOS 16) { mozWaitForElementToExist(app.otherElements["ActivityListView"].navigationBars["UIActivityContentView"]) - mozWaitForElementToExist(app.buttons["Copy"], timeout: TIMEOUT) + mozWaitForElementToExist(app.buttons["Copy"]) } else { mozWaitForElementToExist(app.otherElements["ActivityListView"].otherElements["Example Domain"]) mozWaitForElementToExist(app.otherElements["ActivityListView"].otherElements["example.com"]) - mozWaitForElementToExist(app.collectionViews.cells["Copy"], timeout: TIMEOUT) + mozWaitForElementToExist(app.collectionViews.cells["Copy"]) } var fennecElement = app.collectionViews.scrollViews.cells.elementContainingText("Fennec") // This is not ideal but only way to get the element on iPhone 8 @@ -88,7 +88,7 @@ class PhotonActionSheetTests: BaseTestCase { if #unavailable(iOS 17) { fennecElement = app.collectionViews.scrollViews.cells.element(boundBy: 2) } - mozWaitForElementToExist(fennecElement, timeout: 5) + mozWaitForElementToExist(fennecElement) fennecElement.tap() mozWaitForElementToExist(app.navigationBars["ShareTo.ShareView"]) } @@ -97,12 +97,11 @@ class PhotonActionSheetTests: BaseTestCase { // Smoketest func testSharePageWithShareSheetOptions() { openNewShareSheet() - mozWaitForElementToExist(app.staticTexts["Open in Firefox"], timeout: 10) - XCTAssertTrue(app.staticTexts["Open in Firefox"].exists) - XCTAssertTrue(app.staticTexts["Load in Background"].exists) - XCTAssertTrue(app.staticTexts["Bookmark This Page"].exists) - XCTAssertTrue(app.staticTexts["Add to Reading List"].exists) - XCTAssertTrue(app.staticTexts["Send to Device"].exists) + mozWaitForElementToExist(app.staticTexts["Open in Firefox"]) + mozWaitForElementToExist(app.staticTexts["Load in Background"]) + mozWaitForElementToExist(app.staticTexts["Bookmark This Page"]) + mozWaitForElementToExist(app.staticTexts["Add to Reading List"]) + mozWaitForElementToExist(app.staticTexts["Send to Device"]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2323203 @@ -111,11 +110,10 @@ class PhotonActionSheetTests: BaseTestCase { mozWaitForElementToExist(app.staticTexts["Send to Device"]) app.staticTexts["Send to Device"].tap() mozWaitForElementToExist( - app.navigationBars.buttons[AccessibilityIdentifiers.ShareTo.HelpView.doneButton], - timeout: 10 + app.navigationBars.buttons[AccessibilityIdentifiers.ShareTo.HelpView.doneButton] ) - XCTAssertTrue(app.staticTexts["You are not signed in to your account."].exists) + mozWaitForElementToExist(app.staticTexts["You are not signed in to your account."]) app.navigationBars.buttons[AccessibilityIdentifiers.ShareTo.HelpView.doneButton].tap() } diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/PrivateBrowsingTest.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/PrivateBrowsingTest.swift index f7cc99166a7c..f66e6c59c363 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/PrivateBrowsingTest.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/PrivateBrowsingTest.swift @@ -24,7 +24,7 @@ class PrivateBrowsingTest: BaseTestCase { navigator.goto(LibraryPanel_History) mozWaitForElementToExist(app.tables[HistoryPanelA11y.tableView]) - XCTAssertTrue(app.tables[HistoryPanelA11y.tableView].staticTexts[url1And3Label].exists) + mozWaitForElementToExist(app.tables[HistoryPanelA11y.tableView].staticTexts[url1And3Label]) // History without counting Clear Recent History and Recently Closed let history = app.tables[HistoryPanelA11y.tableView].cells.count - 1 @@ -37,8 +37,8 @@ class PrivateBrowsingTest: BaseTestCase { mozWaitForValueContains(app.textFields["url"], value: "mozilla") navigator.goto(LibraryPanel_History) mozWaitForElementToExist(app.tables[HistoryPanelA11y.tableView]) - XCTAssertTrue(app.tables[HistoryPanelA11y.tableView].staticTexts[url1And3Label].exists) - XCTAssertFalse(app.tables[HistoryPanelA11y.tableView].staticTexts[url2Label].exists) + mozWaitForElementToExist(app.tables[HistoryPanelA11y.tableView].staticTexts[url1And3Label]) + mozWaitForElementToNotExist(app.tables[HistoryPanelA11y.tableView].staticTexts[url2Label]) // Open one tab in private browsing and check the total number of tabs let privateHistory = app.tables[HistoryPanelA11y.tableView].cells.count - 1 @@ -93,7 +93,7 @@ class PrivateBrowsingTest: BaseTestCase { func testClosePrivateTabsOptionClosesPrivateTabs() { // Check that Close Private Tabs when closing the Private Browsing Button is off by default navigator.nowAt(NewTabScreen) - mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton], timeout: TIMEOUT) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton]) navigator.goto(SettingsScreen) // FXIOS-8672: "Close Private Tabs" has been removed from the settings. @@ -129,8 +129,8 @@ class PrivateBrowsingTest: BaseTestCase { func checkIndexedDBIsCreated() { navigator.openURL(urlIndexedDB) waitUntilPageLoad() - XCTAssertTrue(app.webViews.staticTexts["DB_CREATED_PAGE"].exists) - XCTAssertTrue(app.webViews.staticTexts["DB_CREATED_WORKER"].exists) + mozWaitForElementToExist(app.webViews.staticTexts["DB_CREATED_PAGE"]) + mozWaitForElementToExist(app.webViews.staticTexts["DB_CREATED_WORKER"]) } navigator.toggleOn(userState.isPrivate, withAction: Action.TogglePrivateMode) @@ -180,27 +180,26 @@ class PrivateBrowsingTest: BaseTestCase { navigator.toggleOn(userState.isPrivate, withAction: Action.TogglePrivateMode) navigator.openURL(path(forTestPage: "test-example.html")) - mozWaitForElementToExist(app.webViews.links[website_2["link"]!], timeout: TIMEOUT) + mozWaitForElementToExist(app.webViews.links[website_2["link"]!]) app.webViews.links[website_2["link"]!].press(forDuration: 2) mozWaitForElementToExist( - app.collectionViews.staticTexts[website_2["moreLinkLongPressUrl"]!], - timeout: TIMEOUT + app.collectionViews.staticTexts[website_2["moreLinkLongPressUrl"]!] ) - XCTAssertFalse(app.buttons["Open in New Tab"].exists, "The option is not shown") - XCTAssertTrue(app.buttons["Open in New Private Tab"].exists, "The option is not shown") - XCTAssertTrue(app.buttons["Copy Link"].exists, "The option is not shown") - XCTAssertTrue(app.buttons["Download Link"].exists, "The option is not shown") + mozWaitForElementToNotExist(app.buttons["Open in New Tab"]) + mozWaitForElementToExist(app.buttons["Open in New Private Tab"]) + mozWaitForElementToExist(app.buttons["Copy Link"]) + mozWaitForElementToExist(app.buttons["Download Link"]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2497357 func testAllPrivateTabsRestore() { - // Several tabs opened in private tabs tray. Tap on the trashcan + // Several tabs opened in private tabs tray. Tap on the trashcan navigator.nowAt(NewTabScreen) navigator.toggleOn(userState.isPrivate, withAction: Action.TogglePrivateMode) for _ in 1...4 { navigator.createNewTab() if app.keyboards.element.isVisible() && !iPad() { - mozWaitForElementToExist(app.buttons["urlBar-cancel"], timeout: TIMEOUT) + mozWaitForElementToExist(app.buttons["urlBar-cancel"]) navigator.performAction(Action.CloseURLBarOpen) } } @@ -302,9 +301,9 @@ class PrivateBrowsingTestIphone: IphoneOnlyTestCase { // Check that the tab has changed waitUntilPageLoad() - mozWaitForElementToExist(app.textFields["url"], timeout: 5) + mozWaitForElementToExist(app.textFields["url"]) mozWaitForValueContains(app.textFields["url"], value: "iana") - XCTAssertTrue(app.links["RFC 2606"].exists) + mozWaitForElementToExist(app.links["RFC 2606"]) mozWaitForElementToExist(app.buttons["Show Tabs"]) let numPrivTab = app.buttons["Show Tabs"].value as? String XCTAssertEqual("2", numPrivTab) @@ -314,6 +313,12 @@ class PrivateBrowsingTestIphone: IphoneOnlyTestCase { class PrivateBrowsingTestIpad: IpadOnlyTestCase { typealias HistoryPanelA11y = AccessibilityIdentifiers.LibraryPanels.HistoryPanel + override func setUp() { + super.setUp() + waitForTabsButton() + mozWaitForElementToExist(app.textFields["url"]) + } + // This test is only enabled for iPad. Shortcut does not exists on iPhone // https://testrail.stage.mozaws.net/index.php?/cases/view/2307008 func testClosePrivateTabsOptionClosesPrivateTabsShortCutiPad() { @@ -321,7 +326,7 @@ class PrivateBrowsingTestIpad: IpadOnlyTestCase { waitForTabsButton() navigator.toggleOn(userState.isPrivate, withAction: Action.TogglePrivateMode) navigator.openURL(url2) - mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton], timeout: TIMEOUT) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton]) // Leave PM by tapping on PM shourt cut navigator.toggleOff(userState.isPrivate, withAction: Action.TogglePrivateModeFromTabBarHomePanel) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/ReadingListTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/ReadingListTests.swift index 5ecac9fc7b09..15aa751be555 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/ReadingListTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/ReadingListTests.swift @@ -12,11 +12,11 @@ class ReadingListTests: BaseTestCase { navigator.openURL(path(forTestPage: "test-mozilla-book.html")) navigator.nowAt(BrowserTab) mozWaitForElementToNotExist(app.staticTexts["Fennec pasted from XCUITests-Runner"]) - mozWaitForElementToExist(app.buttons["Reader View"], timeout: TIMEOUT) + mozWaitForElementToExist(app.buttons["Reader View"]) app.buttons["Reader View"].tap() // The settings of reader view are shown as well as the content of the web site - mozWaitForElementToExist(app.buttons["Display Settings"], timeout: TIMEOUT) - XCTAssertTrue(app.webViews.staticTexts["The Book of Mozilla"].exists) + mozWaitForElementToExist(app.buttons["Display Settings"]) + mozWaitForElementToExist(app.webViews.staticTexts["The Book of Mozilla"]) } private func checkReadingListNumberOfItems(items: Int) { @@ -44,7 +44,6 @@ class ReadingListTests: BaseTestCase { // Check that there is one item let savedToReadingList = app.tables["ReadingTable"].cells.staticTexts["The Book of Mozilla"] mozWaitForElementToExist(savedToReadingList) - XCTAssertTrue(savedToReadingList.exists) checkReadingListNumberOfItems(items: 1) } @@ -53,7 +52,7 @@ class ReadingListTests: BaseTestCase { navigator.nowAt(NewTabScreen) navigator.toggleOn(userState.isPrivate, withAction: Action.TogglePrivateMode) navigator.performAction(Action.OpenNewTabFromTabTray) - mozWaitForElementToExist(app.buttons["urlBar-cancel"], timeout: TIMEOUT) + mozWaitForElementToExist(app.buttons["urlBar-cancel"]) navigator.performAction(Action.CloseURLBarOpen) navigator.nowAt(NewTabScreen) waitForTabsButton() @@ -71,14 +70,13 @@ class ReadingListTests: BaseTestCase { // Check that there is one item let savedToReadingList = app.tables["ReadingTable"].cells.staticTexts["The Book of Mozilla"] mozWaitForElementToExist(savedToReadingList) - XCTAssertTrue(savedToReadingList.exists) checkReadingListNumberOfItems(items: 1) app.buttons["Done"].tap() updateScreenGraph() // Check that it appears on regular mode navigator.toggleOff(userState.isPrivate, withAction: Action.ToggleRegularMode) navigator.performAction(Action.OpenNewTabFromTabTray) - mozWaitForElementToExist(app.buttons["urlBar-cancel"], timeout: TIMEOUT) + mozWaitForElementToExist(app.buttons["urlBar-cancel"]) navigator.performAction(Action.CloseURLBarOpen) navigator.nowAt(NewTabScreen) waitForTabsButton() @@ -125,11 +123,11 @@ class ReadingListTests: BaseTestCase { mozWaitForElementToExist(app.tables["ReadingTable"]) // Check that there is one item let savedToReadingList = app.tables["ReadingTable"].cells.staticTexts["The Book of Mozilla"] - XCTAssertTrue(savedToReadingList.exists) + mozWaitForElementToExist(savedToReadingList) // Mark it as read/unread savedToReadingList.swipeLeft() - mozWaitForElementToExist(app.tables.cells.buttons.staticTexts["Mark as Read"], timeout: TIMEOUT) + mozWaitForElementToExist(app.tables.cells.buttons.staticTexts["Mark as Read"]) app.tables["ReadingTable"].cells.buttons.element(boundBy: 1).tap() savedToReadingList.swipeLeft() mozWaitForElementToExist(app.tables.cells.buttons.staticTexts["Mark as Unread"]) @@ -148,7 +146,7 @@ class ReadingListTests: BaseTestCase { savedToReadingList.swipeLeft() mozWaitForElementToExist(app.buttons["Remove"]) app.buttons["Remove"].tap() - XCTAssertFalse(savedToReadingList.exists) + mozWaitForElementToNotExist(savedToReadingList) // Reader list view should be empty checkReadingListNumberOfItems(items: 0) @@ -212,7 +210,6 @@ class ReadingListTests: BaseTestCase { // Verify the item has been removed mozWaitForElementToNotExist(app.tables["ReadingTable"].cells.staticTexts["The Book of Mozilla"]) - XCTAssertFalse(app.tables["ReadingTable"].cells.staticTexts["The Book of Mozilla"].exists) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2306893 @@ -237,7 +234,7 @@ class ReadingListTests: BaseTestCase { // Tap on an article savedToReadingList.tap() // The article is displayed in Reader View - mozWaitForElementToExist(app.buttons["Reader View"], timeout: TIMEOUT) + mozWaitForElementToExist(app.buttons["Reader View"]) XCTAssertTrue(app.buttons["Reader View"].isSelected) XCTAssertTrue(app.buttons["Reader View"].isEnabled) app.buttons[AccessibilityIdentifiers.Toolbar.homeButton].tap() @@ -248,8 +245,8 @@ class ReadingListTests: BaseTestCase { mozWaitForElementToExist(app.tables["ReadingTable"].cells.elementContainingText("The Book of Mozilla, read")) savedToReadingList.swipeLeft() // Two options are revealed - mozWaitForElementToExist(app.tables.cells.buttons.staticTexts["Mark as Unread"], timeout: TIMEOUT) - mozWaitForElementToExist(app.tables.cells.buttons.staticTexts["Remove"], timeout: TIMEOUT) + mozWaitForElementToExist(app.tables.cells.buttons.staticTexts["Mark as Unread"]) + mozWaitForElementToExist(app.tables.cells.buttons.staticTexts["Remove"]) // Tap 'Mark as Unread' app.tables.cells.buttons.staticTexts["Mark as Unread"].tap(force: true) // The article has been marked as Unread @@ -269,7 +266,7 @@ class ReadingListTests: BaseTestCase { func testAddToReaderListOptions() { addContentToReaderView() // Check that Settings layouts options are shown - mozWaitForElementToExist(app.buttons["ReaderModeBarView.settingsButton"], timeout: TIMEOUT) + mozWaitForElementToExist(app.buttons["ReaderModeBarView.settingsButton"]) app.buttons["ReaderModeBarView.settingsButton"].tap() let layoutOptions = ["Light", "Sepia", "Dark", "Decrease text size", "Reset text size", "Increase text size", "Remove from Reading List", "Mark as Read"] diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/ReportSiteTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/ReportSiteTests.swift index 5fe7f8e71c57..916dd7a20082 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/ReportSiteTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/ReportSiteTests.swift @@ -13,7 +13,7 @@ class ReportSiteTests: BaseTestCase { func testReportSiteIssueOn() { launchAndGoToMenu() - XCTAssertTrue(app.tables.otherElements[StandardImageIdentifiers.Large.lightbulb].exists) + mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.lightbulb]) } func testReportSiteIssueOff() { @@ -23,7 +23,7 @@ class ReportSiteTests: BaseTestCase { launchAndGoToMenu() - XCTAssertFalse(app.tables.otherElements[StandardImageIdentifiers.Large.lightbulb].exists) + mozWaitForElementToNotExist(app.tables.otherElements[StandardImageIdentifiers.Large.lightbulb]) } // MARK: Helper diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/SearchTest.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/SearchTest.swift index 99ba97255007..25cee8cccb52 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/SearchTest.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/SearchTest.swift @@ -15,7 +15,7 @@ private let SuggestedSite6: String = "foobar bomb baby" class SearchTests: BaseTestCase { private func typeOnSearchBar(text: String) { - mozWaitForElementToExist(app.textFields.firstMatch, timeout: 10) + mozWaitForElementToExist(app.textFields.firstMatch) app.textFields.firstMatch.tap() app.textFields.firstMatch.tap() app.textFields.firstMatch.typeText(text) @@ -37,7 +37,7 @@ class SearchTests: BaseTestCase { // In the search suggestion, "text" should be displayed let predicate = NSPredicate(format: "label CONTAINS[c] %@", "http://localhost:") let elementQuery = app.staticTexts.containing(predicate) - XCTAssertTrue(elementQuery.element.exists) + mozWaitForElementToExist(elementQuery.element) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2436093 @@ -49,7 +49,6 @@ class SearchTests: BaseTestCase { // Suggestions should be shown mozWaitForElementToExist(app.tables["SiteTable"].cells.firstMatch) - XCTAssertTrue(app.tables["SiteTable"].cells.firstMatch.exists) // Disable Search suggestion app.buttons["urlBar-cancel"].tap() @@ -65,7 +64,6 @@ class SearchTests: BaseTestCase { navigator.goto(URLBarOpen) typeOnSearchBar(text: "foobar") mozWaitForElementToNotExist(app.tables["SiteTable"].cells.firstMatch) - XCTAssertFalse(app.tables["SiteTable"].cells.firstMatch.exists) // Verify that previous choice is remembered app.buttons["urlBar-cancel"].tap() @@ -74,7 +72,6 @@ class SearchTests: BaseTestCase { typeOnSearchBar(text: "foobar") mozWaitForElementToNotExist(app.tables["SiteTable"].cells[SuggestedSite]) - XCTAssertFalse(app.tables["SiteTable"].cells.firstMatch.exists) app.buttons["urlBar-cancel"].tap() waitForTabsButton() @@ -89,7 +86,6 @@ class SearchTests: BaseTestCase { // Suggestions prompt should appear typeOnSearchBar(text: "foobar") mozWaitForElementToExist(app.tables["SiteTable"].cells.firstMatch) - XCTAssertTrue(app.tables["SiteTable"].cells.firstMatch.exists) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2436094 @@ -105,8 +101,7 @@ class SearchTests: BaseTestCase { if !(app.tables["SiteTable"].cells.staticTexts[SuggestedSite].exists) { if !(app.tables["SiteTable"].cells.staticTexts[SuggestedSite2].exists) { mozWaitForElementToExist( - app.tables["SiteTable"].cells.staticTexts[SuggestedSite3], - timeout: 5 + app.tables["SiteTable"].cells.staticTexts[SuggestedSite3] ) } } @@ -134,19 +129,18 @@ class SearchTests: BaseTestCase { typeOnSearchBar(text: "www.mozilla.org") app.textFields["address"].press(forDuration: 5) app.menuItems["Select All"].tap() - mozWaitForElementToExist(app.menuItems["Copy"], timeout: 3) + mozWaitForElementToExist(app.menuItems["Copy"]) app.menuItems["Copy"].tap() mozWaitForElementToExist(app.buttons["urlBar-cancel"]) app.buttons["urlBar-cancel"].tap() navigator.nowAt(HomePanelsScreen) mozWaitForElementToExist( - app.collectionViews.cells[AccessibilityIdentifiers.FirefoxHomepage.TopSites.itemCell], - timeout: 10 + app.collectionViews.cells[AccessibilityIdentifiers.FirefoxHomepage.TopSites.itemCell] ) - mozWaitForElementToExist(app.textFields["url"], timeout: 3) + mozWaitForElementToExist(app.textFields["url"]) app.textFields["url"].tap() - mozWaitForElementToExist(app.textFields["address"], timeout: 3) + mozWaitForElementToExist(app.textFields["address"]) app.textFields["address"].tap() mozWaitForElementToExist(app.menuItems["Paste"]) @@ -181,7 +175,7 @@ class SearchTests: BaseTestCase { tablesQuery2.staticTexts[searchEngine].tap() navigator.openURL("foo bar") - mozWaitForElementToExist(app.webViews.firstMatch, timeout: 3) + mozWaitForElementToExist(app.webViews.firstMatch) mozWaitForValueContains(app.textFields["url"], value: searchEngine.lowercased()) } @@ -209,7 +203,7 @@ class SearchTests: BaseTestCase { navigator.nowAt(NewTabScreen) navigator.openURL(path(forTestPage: "test-mozilla-book.html")) waitUntilPageLoad() - mozWaitForElementToExist(app.webViews.staticTexts["cloud"], timeout: 10) + mozWaitForElementToExist(app.webViews.staticTexts["cloud"]) // Select some text and long press to find the option app.webViews.staticTexts["cloud"].press(forDuration: 1) // Click on the > button to get to that option only on iPhone @@ -240,10 +234,10 @@ class SearchTests: BaseTestCase { // Smoketest func testSearchStartAfterTypingTwoWords() { navigator.goto(URLBarOpen) - mozWaitForElementToExist(app.textFields["url"], timeout: 10) + mozWaitForElementToExist(app.textFields["url"]) app.typeText("foo bar") app.typeText(XCUIKeyboardKey.return.rawValue) - mozWaitForElementToExist(app.textFields["url"], timeout: 20) + mozWaitForElementToExist(app.textFields["url"]) mozWaitForValueContains(app.textFields["url"], value: "google") } @@ -257,7 +251,7 @@ class SearchTests: BaseTestCase { // Search icon is displayed. mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.searchButton]) XCTAssertEqual(app.buttons[AccessibilityIdentifiers.Toolbar.searchButton].label, "Search") - XCTAssertTrue(app.buttons[AccessibilityIdentifiers.Toolbar.searchButton].exists) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.searchButton]) app.buttons[AccessibilityIdentifiers.Toolbar.searchButton].tap() let addressBar = app.textFields["address"] @@ -273,7 +267,7 @@ class SearchTests: BaseTestCase { mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.homeButton]) XCTAssertEqual(app.buttons[AccessibilityIdentifiers.Toolbar.homeButton].label, "Home") app.buttons[AccessibilityIdentifiers.Toolbar.homeButton].tap() - waitForExistence(app.buttons[AccessibilityIdentifiers.Toolbar.backButton]) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.backButton]) app.buttons[AccessibilityIdentifiers.Toolbar.backButton].tap() mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.homeButton]) @@ -303,8 +297,7 @@ class SearchTests: BaseTestCase { restartInBackground() // Open new tab mozWaitForElementToExist( - app.buttons[AccessibilityIdentifiers.Browser.UrlBar.cancelButton], - timeout: TIMEOUT + app.buttons[AccessibilityIdentifiers.Browser.UrlBar.cancelButton] ) navigator.performAction(Action.CloseURLBarOpen) waitForTabsButton() @@ -455,7 +448,7 @@ class SearchTests: BaseTestCase { // navigator.nowAt(NewTabScreen) // navigator.goto(SearchSettings) // navigator.nowAt(SearchSettings) -// +// // // By default, disable search suggest in private mode // let privateModeSearchSuggestSwitch = app.otherElements.tables.cells[ // AccessibilityIdentifiers.Settings.Search.disableSearchSuggestsInPrivateMode diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/SettingsTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/SettingsTests.swift index c04d0ad7c462..b66b1466a454 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/SettingsTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/SettingsTests.swift @@ -41,7 +41,7 @@ class SettingsTests: BaseTestCase { waitForTabsButton() navigator.nowAt(NewTabScreen) navigator.performAction(Action.OpenSiriFromSettings) - mozWaitForElementToExist(app.cells["SiriSettings"], timeout: 5) + mozWaitForElementToExist(app.cells["SiriSettings"]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2334756 @@ -84,10 +84,9 @@ class SettingsTests: BaseTestCase { // Check that the list is shown mozWaitForElementToExist(app.tables["OpenWithPage.Setting.Options"]) - XCTAssertTrue(app.tables["OpenWithPage.Setting.Options"].exists) // Check that the list is shown with all elements disabled - XCTAssertTrue(app.tables.staticTexts["OPEN MAIL LINKS WITH"].exists) + mozWaitForElementToExist(app.tables.staticTexts["OPEN MAIL LINKS WITH"]) XCTAssertFalse(app.tables.cells.staticTexts["Mail"].isSelected) XCTAssertFalse(app.tables.cells.staticTexts["Outlook"].isSelected) XCTAssertFalse(app.tables.cells.staticTexts["ProtonMail"].isSelected) @@ -137,7 +136,7 @@ class SettingsTests: BaseTestCase { // https://testrail.stage.mozaws.net/index.php?/cases/view/2306808 // Smoketest func testSettingsOptionSubtitles() { - mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton], timeout: TIMEOUT) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton]) navigator.nowAt(NewTabScreen) navigator.goto(SettingsScreen) let table = app.tables.element(boundBy: 0) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/SyncFAUITests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/SyncFAUITests.swift index e897c1a37e07..6466439ee864 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/SyncFAUITests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/SyncFAUITests.swift @@ -30,15 +30,10 @@ class SyncUITests: BaseTestCase { private func verifyFxASigninScreen() { mozWaitForElementToExist( - app.navigationBars[AccessibilityIdentifiers.Settings.FirefoxAccount.fxaNavigationBar], - timeout: 30 + app.navigationBars[AccessibilityIdentifiers.Settings.FirefoxAccount.fxaNavigationBar] ) mozWaitForElementToExist( - app.webViews.textFields[AccessibilityIdentifiers.Settings.FirefoxAccount.emailTextField], - timeout: 10 - ) - XCTAssertTrue( - app.webViews.textFields[AccessibilityIdentifiers.Settings.FirefoxAccount.emailTextField].exists + app.webViews.textFields[AccessibilityIdentifiers.Settings.FirefoxAccount.emailTextField] ) // Verify the placeholdervalues here for the textFields @@ -49,7 +44,7 @@ class SyncUITests: BaseTestCase { defaultMailPlaceholder, "The mail placeholder does not show the correct value" ) - XCTAssertTrue(app.webViews.buttons[AccessibilityIdentifiers.Settings.FirefoxAccount.continueButton].exists) + mozWaitForElementToExist(app.webViews.buttons[AccessibilityIdentifiers.Settings.FirefoxAccount.continueButton]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2448874 @@ -59,13 +54,12 @@ class SyncUITests: BaseTestCase { navigator.goto(FxASigninScreen) mozWaitForElementToExist( app.navigationBars[AccessibilityIdentifiers.Settings.FirefoxAccount.fxaNavigationBar], - timeout: 60 + timeout: TIMEOUT_LONG ) // Tap Sign in without any value in email Password focus on Email mozWaitForElementToExist( - app.webViews.buttons[AccessibilityIdentifiers.Settings.FirefoxAccount.continueButton], - timeout: 20 + app.webViews.buttons[AccessibilityIdentifiers.Settings.FirefoxAccount.continueButton] ) navigator.performAction(Action.FxATapOnContinueButton) mozWaitForElementToExist(app.webViews.staticTexts["Valid email required"]) @@ -93,10 +87,10 @@ class SyncUITests: BaseTestCase { func testCreateAnAccountLink() { navigator.nowAt(NewTabScreen) navigator.goto(FxASigninScreen) - mozWaitForElementToExist(app.webViews.firstMatch, timeout: 20) + mozWaitForElementToExist(app.webViews.firstMatch, timeout: TIMEOUT_LONG) mozWaitForElementToExist( app.webViews.textFields[AccessibilityIdentifiers.Settings.FirefoxAccount.emailTextField], - timeout: 40 + timeout: TIMEOUT_LONG ) userState.fxaUsername = "foo1bar2@gmail.com" navigator.performAction(Action.FxATypeEmail) @@ -113,7 +107,7 @@ class SyncUITests: BaseTestCase { navigator.goto(FxASigninScreen) mozWaitForElementToExist( app.webViews.textFields[AccessibilityIdentifiers.Settings.FirefoxAccount.emailTextField], - timeout: 20 + timeout: TIMEOUT_LONG ) // Typing on Email should not show Show (password) option userState.fxaUsername = "iosmztest@gmail.com" @@ -124,7 +118,7 @@ class SyncUITests: BaseTestCase { mozWaitForElementToExist(app.secureTextFields.element(boundBy: 1)) navigator.performAction(Action.FxATypePasswordNewAccount) let passMessage = "Your password is currently hidden." - mozWaitForElementToExist(app.webViews.buttons[passMessage], timeout: 3) + mozWaitForElementToExist(app.webViews.buttons[passMessage]) // Remove the password typed, Show (password) option should not be shown app.keyboards.keys["delete"].tap() mozWaitForElementToNotExist(app.webViews.staticTexts[passMessage]) @@ -138,8 +132,7 @@ class SyncUITests: BaseTestCase { // QR does not work on sim but checking that the button works, no crash navigator.performAction(Action.OpenEmailToQR) mozWaitForElementToExist( - app.navigationBars[AccessibilityIdentifiers.Settings.FirefoxAccount.fxaNavigationBar], - timeout: 5 + app.navigationBars[AccessibilityIdentifiers.Settings.FirefoxAccount.fxaNavigationBar] ) mozWaitForElementToExist(app.buttons["Ready to Scan"]) mozWaitForElementToExist(app.buttons["Use Email Instead"]) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/TabCounterTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/TabCounterTests.swift index a0a9e63f67a7..8c1640ec4c3f 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/TabCounterTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/TabCounterTests.swift @@ -6,6 +6,12 @@ import Common import XCTest class TabCounterTests: BaseTestCase { + override func setUp() { + super.setUp() + waitForTabsButton() + mozWaitForElementToExist(app.textFields["url"]) + } + // https://testrail.stage.mozaws.net/index.php?/cases/view/2359077 func testTabIncrement() throws { navigator.nowAt(NewTabScreen) @@ -83,7 +89,7 @@ class TabCounterTests: BaseTestCase { tabsOpen = app.segmentedControls.buttons.element(boundBy: 0).label XCTAssertTrue(app.segmentedControls.buttons.element(boundBy: 0).isSelected) if !isTablet { - mozWaitForElementToExist(app.segmentedControls.firstMatch, timeout: 5) + mozWaitForElementToExist(app.segmentedControls.firstMatch) let tabsOpenTabTray: String = app.segmentedControls.buttons.firstMatch.label XCTAssertTrue(tabsOpenTabTray.hasSuffix("1")) } diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/ThirdPartySearchTest.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/ThirdPartySearchTest.swift index ab3e22c5fa63..a94476c479ed 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/ThirdPartySearchTest.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/ThirdPartySearchTest.swift @@ -15,7 +15,7 @@ class ThirdPartySearchTest: BaseTestCase { func testCustomSearchEngines() { addCustomSearchEngine() - mozWaitForElementToExist(app.navigationBars["Search"].buttons["Settings"], timeout: 3) + mozWaitForElementToExist(app.navigationBars["Search"].buttons["Settings"]) app.navigationBars["Search"].buttons["Settings"].tap() mozWaitForElementToExist(app.navigationBars["Settings"].buttons[AccessibilityIdentifiers.Settings.navigationBarItem]) app.navigationBars["Settings"].buttons[AccessibilityIdentifiers.Settings.navigationBarItem].tap() @@ -64,7 +64,7 @@ class ThirdPartySearchTest: BaseTestCase { // https://testrail.stage.mozaws.net/index.php?/cases/view/2306941 func testCustomSearchEngineDeletion() { addCustomSearchEngine() - mozWaitForElementToExist(app.navigationBars["Search"].buttons["Settings"], timeout: 3) + mozWaitForElementToExist(app.navigationBars["Search"].buttons["Settings"]) app.navigationBars["Search"].buttons["Settings"].tap() mozWaitForElementToExist(app.navigationBars["Settings"].buttons[AccessibilityIdentifiers.Settings.navigationBarItem]) @@ -75,10 +75,9 @@ class ThirdPartySearchTest: BaseTestCase { app.textFields.firstMatch.press(forDuration: 1) app.staticTexts["Paste"].tap() mozWaitForElementToExist(app.scrollViews.otherElements.buttons["Mozilla Engine search"]) - XCTAssertTrue(app.scrollViews.otherElements.buttons["Mozilla Engine search"].exists) // Need to go step by step to Search Settings. The ScreenGraph will fail to go to the Search Settings Screen - mozWaitForElementToExist(app.buttons["urlBar-cancel"], timeout: 3) + mozWaitForElementToExist(app.buttons["urlBar-cancel"]) app.buttons["urlBar-cancel"].tap() app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton].tap() app.tables["Context Menu"].otherElements["Settings"].tap() @@ -91,7 +90,7 @@ class ThirdPartySearchTest: BaseTestCase { dismissSearchScreen() // Perform a search to check - mozWaitForElementToExist(app.textFields["url"], timeout: 3) + mozWaitForElementToExist(app.textFields["url"]) app.textFields["url"].tap() mozWaitForElementToExist(app.buttons["urlBar-cancel"]) UIPasteboard.general.string = "window" @@ -99,7 +98,6 @@ class ThirdPartySearchTest: BaseTestCase { app.staticTexts["Paste"].tap() mozWaitForElementToNotExist(app.scrollViews.otherElements.buttons["Mozilla Engine search"]) - XCTAssertFalse(app.scrollViews.otherElements.buttons["Mozilla Engine search"].exists) } } @@ -107,7 +105,7 @@ class ThirdPartySearchTest: BaseTestCase { waitForTabsButton() navigator.nowAt(NewTabScreen) navigator.performAction(Action.AddCustomSearchEngine) - mozWaitForElementToExist(app.buttons["customEngineSaveButton"], timeout: 3) + mozWaitForElementToExist(app.buttons["customEngineSaveButton"]) app.buttons["customEngineSaveButton"].tap() if #unavailable(iOS 16) { // Wait for "Fennec pasted from XCUITests-Runner" banner to disappear @@ -136,7 +134,7 @@ class ThirdPartySearchTest: BaseTestCase { .textViews["customEngineUrl"] .staticTexts["URL (Replace Query with %s)"] - XCTAssertTrue(customengineurlTextView.exists) + mozWaitForElementToExist(customengineurlTextView) UIPasteboard.general.string = searchUrl customengineurlTextView.tap() @@ -153,9 +151,9 @@ class ThirdPartySearchTest: BaseTestCase { pasteOption.tap() } - mozWaitForElementToExist(app.buttons["customEngineSaveButton"], timeout: 3) + mozWaitForElementToExist(app.buttons["customEngineSaveButton"]) app.buttons["customEngineSaveButton"].tap() - mozWaitForElementToExist(app.navigationBars["Add Search Engine"], timeout: 3) + mozWaitForElementToExist(app.navigationBars["Add Search Engine"]) app.navigationBars["Add Search Engine"].buttons["Save"].tap() // The alert appears on iOS 15 but it disappears by itself immediately. diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/ToolbarMenuTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/ToolbarMenuTests.swift index a45933ad10f7..d4feb9480831 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/ToolbarMenuTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/ToolbarMenuTests.swift @@ -45,7 +45,7 @@ class ToolbarMenuTests: BaseTestCase { mozWaitForElementToExist(app.tables["Context Menu"]) validateMenuOptions() XCUIDevice.shared.orientation = .landscapeLeft - mozWaitForElementToExist(hamburgerMenu, timeout: 15) + mozWaitForElementToExist(hamburgerMenu) mozWaitForElementToNotExist(app.tables["Context Menu"]) mozWaitForElementToExist(app.textFields["url"]) mozWaitForElementToExist(app.webViews["contentView"]) @@ -75,16 +75,15 @@ class ToolbarMenuTests: BaseTestCase { } private func validateMenuOptions() { - XCTAssertTrue(app.tables.otherElements[StandardImageIdentifiers.Large.bookmarkTrayFill].exists) - XCTAssertTrue(app.tables.otherElements[StandardImageIdentifiers.Large.history].exists) - XCTAssertTrue(app.tables.otherElements[StandardImageIdentifiers.Large.download].exists) - XCTAssertTrue(app.tables.otherElements[StandardImageIdentifiers.Large.readingList].exists) - XCTAssertTrue(app.tables.otherElements[StandardImageIdentifiers.Large.login].exists) - XCTAssertTrue(app.tables.otherElements[StandardImageIdentifiers.Large.sync].exists) - XCTAssertTrue(app.tables.otherElements[StandardImageIdentifiers.Large.nightMode].exists) - XCTAssertTrue(app.tables.otherElements[StandardImageIdentifiers.Large.whatsNew].exists) - XCTAssertTrue(app.tables.otherElements[StandardImageIdentifiers.Large.helpCircle].exists) - XCTAssertTrue(app.tables.otherElements[StandardImageIdentifiers.Large.edit].exists) - XCTAssertTrue(app.tables.otherElements[StandardImageIdentifiers.Large.settings].exists) + mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.bookmarkTrayFill]) + mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.download]) + mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.readingList]) + mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.login]) + mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.sync]) + mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.nightMode]) + mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.whatsNew]) + mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.helpCircle]) + mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.edit]) + mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.settings]) } } diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/TopTabsTest.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/TopTabsTest.swift index 8059ec4c6593..89e81bc404d5 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/TopTabsTest.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/TopTabsTest.swift @@ -22,7 +22,7 @@ class TopTabsTest: BaseTestCase { // Smoketest func testAddTabFromTabTray() throws { XCTExpectFailure("The app was not launched", strict: false) { - mozWaitForElementToExist(app.collectionViews["FxCollectionView"], timeout: TIMEOUT) + mozWaitForElementToExist(app.collectionViews["FxCollectionView"]) } navigator.nowAt(NewTabScreen) waitForTabsButton() @@ -36,12 +36,12 @@ class TopTabsTest: BaseTestCase { // The tab tray shows the correct tabs if iPad() { - mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton], timeout: 15) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton]) app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton].tap() } else { navigator.goto(TabTray) } - mozWaitForElementToExist(app.cells.staticTexts[urlLabel], timeout: TIMEOUT) + mozWaitForElementToExist(app.cells.staticTexts[urlLabel]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2354300 @@ -53,7 +53,7 @@ class TopTabsTest: BaseTestCase { XCTAssertEqual("1", tabsOpenInitially as? String) // Open link in a different tab and switch to it - mozWaitForElementToExist(app.webViews.links.staticTexts["More information..."], timeout: 5) + mozWaitForElementToExist(app.webViews.links.staticTexts["More information..."]) app.webViews.links.staticTexts["More information..."].press(forDuration: 5) app.buttons["Open in New Tab"].tap() waitUntilPageLoad() @@ -126,13 +126,13 @@ class TopTabsTest: BaseTestCase { waitForTabsButton() navigator.nowAt(BrowserTab) if iPad() { - mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton], timeout: 10) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton]) app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton].tap() - mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.TabTray.newTabButton], timeout: 10) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.TabTray.newTabButton]) app.buttons[AccessibilityIdentifiers.TabTray.newTabButton].tap() } else { navigator.performAction(Action.OpenNewTabFromTabTray) - mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton], timeout: 5) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton]) } if iPad() { @@ -149,12 +149,11 @@ class TopTabsTest: BaseTestCase { app.otherElements.buttons.staticTexts["Undo"].tap() mozWaitForElementToExist( - app.collectionViews.cells[AccessibilityIdentifiers.FirefoxHomepage.TopSites.itemCell], - timeout: 5 + app.collectionViews.cells[AccessibilityIdentifiers.FirefoxHomepage.TopSites.itemCell] ) navigator.nowAt(BrowserTab) if !iPad() { - mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton], timeout: 5) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton]) } if iPad() { @@ -180,13 +179,13 @@ class TopTabsTest: BaseTestCase { waitForTabsButton() if iPad() { - mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton], timeout: 10) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton]) app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton].tap() - mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.TabTray.newTabButton], timeout: 10) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.TabTray.newTabButton]) app.buttons[AccessibilityIdentifiers.TabTray.newTabButton].tap() } else { navigator.performAction(Action.OpenNewTabFromTabTray) - mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton], timeout: 5) + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton]) } navigator.goto(URLBarOpen) @@ -198,7 +197,7 @@ class TopTabsTest: BaseTestCase { } // Close all tabs, undo it and check that the number of tabs is correct navigator.performAction(Action.AcceptRemovingAllTabs) - mozWaitForElementToExist(app.staticTexts["Private Browsing"], timeout: 10) + mozWaitForElementToExist(app.staticTexts["Private Browsing"]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2354579 @@ -243,7 +242,7 @@ class TopTabsTest: BaseTestCase { checkNumberOfTabsExpectedToBeOpen(expectedNumberOfTabsOpen: 2) // Close all tabs and check that the number of tabs is correct navigator.performAction(Action.AcceptRemovingAllTabs) - mozWaitForElementToExist(app.staticTexts["Private Browsing"], timeout: TIMEOUT) + mozWaitForElementToExist(app.staticTexts["Private Browsing"]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2306884 @@ -256,8 +255,7 @@ class TopTabsTest: BaseTestCase { app.buttons[AccessibilityIdentifiers.Toolbar.addNewTabButton].tap() } else { mozWaitForElementToExist( - app.buttons[AccessibilityIdentifiers.Toolbar.addNewTabButton], - timeout: 15 + app.buttons[AccessibilityIdentifiers.Toolbar.addNewTabButton] ) app.buttons[AccessibilityIdentifiers.Toolbar.addNewTabButton].tap() } @@ -278,11 +276,10 @@ class TopTabsTest: BaseTestCase { if !iPad() { // Long tap on Tab Counter should show the correct options navigator.nowAt(NewTabScreen) - mozWaitForElementToExist(app.buttons["Show Tabs"], timeout: 10) + mozWaitForElementToExist(app.buttons["Show Tabs"]) app.buttons["Show Tabs"].press(forDuration: 1) mozWaitForElementToExist(app.cells.otherElements[StandardImageIdentifiers.Large.plus]) - XCTAssertTrue(app.cells.otherElements[StandardImageIdentifiers.Large.plus].exists) - XCTAssertTrue(app.cells.otherElements[StandardImageIdentifiers.Large.cross].exists) + mozWaitForElementToExist(app.cells.otherElements[StandardImageIdentifiers.Large.cross]) // Open New Tab app.cells.otherElements[StandardImageIdentifiers.Large.plus].tap() @@ -332,7 +329,7 @@ class TopTabsTest: BaseTestCase { for _ in 1...10 { navigator.createNewTab() if app.keyboards.element.isVisible() && !iPad() { - mozWaitForElementToExist(app.buttons["urlBar-cancel"], timeout: TIMEOUT) + mozWaitForElementToExist(app.buttons["urlBar-cancel"]) navigator.performAction(Action.CloseURLBarOpen) } } @@ -429,7 +426,7 @@ class TopTabsTest: BaseTestCase { for _ in 1...4 { navigator.createNewTab() if app.keyboards.element.isVisible() && !iPad() { - mozWaitForElementToExist(app.buttons["urlBar-cancel"], timeout: TIMEOUT) + mozWaitForElementToExist(app.buttons["urlBar-cancel"]) navigator.performAction(Action.CloseURLBarOpen) } } @@ -451,7 +448,7 @@ class TopTabsTest: BaseTestCase { for _ in 1...nrOfTabs { navigator.createNewTab() if app.keyboards.element.isVisible() && !iPad() { - mozWaitForElementToExist(app.buttons["urlBar-cancel"], timeout: TIMEOUT) + mozWaitForElementToExist(app.buttons["urlBar-cancel"]) navigator.performAction(Action.CloseURLBarOpen) } } @@ -496,6 +493,12 @@ fileprivate extension BaseTestCase { } class TopTabsTestIphone: IphoneOnlyTestCase { + override func setUp() { + super.setUp() + waitForTabsButton() + mozWaitForElementToExist(app.textFields["url"]) + } + // https://testrail.stage.mozaws.net/index.php?/cases/view/2355535 // Smoketest func testCloseTabFromLongPressTabsButton() { @@ -589,14 +592,14 @@ class TopTabsTestIphone: IphoneOnlyTestCase { waitUntilPageLoad() app.webViews.links.firstMatch.press(forDuration: 1) - mozWaitForElementToExist(app.buttons["Open in New Tab"], timeout: 3) + mozWaitForElementToExist(app.buttons["Open in New Tab"]) app.buttons["Open in New Private Tab"].press(forDuration: 1) - mozWaitForElementToExist(app.buttons["Switch"], timeout: 5) + mozWaitForElementToExist(app.buttons["Switch"]) app.buttons["Switch"].tap() // Check that the tab has changed to the new open one and that the user is in private mode waitUntilPageLoad() - mozWaitForElementToExist(app.textFields["url"], timeout: 5) + mozWaitForElementToExist(app.textFields["url"]) mozWaitForValueContains(app.textFields["url"], value: "iana") navigator.goto(TabTray) XCTAssertTrue(app.buttons["privateModeLarge"].isEnabled) @@ -606,6 +609,12 @@ class TopTabsTestIphone: IphoneOnlyTestCase { // Tests to check if Tab Counter is updating correctly after opening three tabs by tapping on '+' button // and closing the tabs by tapping 'x' button class TopTabsTestIpad: IpadOnlyTestCase { + override func setUp() { + super.setUp() + waitForTabsButton() + mozWaitForElementToExist(app.textFields["url"]) + } + // https://testrail.stage.mozaws.net/index.php?/cases/view/2307023 func testUpdateTabCounter() { if skipPlatform { return } diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/TrackingProtectionTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/TrackingProtectionTests.swift index 80559d261842..fab6baf65927 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/TrackingProtectionTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/TrackingProtectionTests.swift @@ -35,8 +35,7 @@ class TrackingProtectionTests: BaseTestCase { // The lock icon should still be there mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.trackingProtection]) mozWaitForElementToExist( - app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton], - timeout: 5 + app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton] ) // Switch to Private Browsing @@ -47,14 +46,13 @@ class TrackingProtectionTests: BaseTestCase { // Make sure TP is also there in PBM mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.trackingProtection]) mozWaitForElementToExist( - app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton], - timeout: TIMEOUT + app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton] ) navigator.goto(BrowserTabMenu) - mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.settings], timeout: 5) + mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.settings]) app.tables.otherElements[StandardImageIdentifiers.Large.settings].tap() navigator.nowAt(SettingsScreen) - mozWaitForElementToExist(app.tables.cells["NewTab"], timeout: 5) + mozWaitForElementToExist(app.tables.cells["NewTab"]) app.tables.cells["NewTab"].swipeUp() // Enable TP again navigator.goto(TrackingProtectionSettings) @@ -94,7 +92,7 @@ class TrackingProtectionTests: BaseTestCase { } navigator.nowAt(BrowserTab) navigator.goto(TrackingProtectionContextMenuDetails) - mozWaitForElementToExist(app.staticTexts["Connection is not secure"], timeout: 5) + mozWaitForElementToExist(app.staticTexts["Connection is not secure"]) var switchValue = app.switches.firstMatch.value! // Need to make sure first the setting was not turned off previously if switchValue as! String == "0" { @@ -109,7 +107,7 @@ class TrackingProtectionTests: BaseTestCase { // Open TP Settings menu app.buttons["Protection Settings"].tap() - mozWaitForElementToExist(app.navigationBars["Tracking Protection"], timeout: 5) + mozWaitForElementToExist(app.navigationBars["Tracking Protection"]) let switchSettingsValue = app.switches["prefkey.trackingprotection.normalbrowsing"].value! XCTAssertEqual(switchSettingsValue as! String, "1") app.switches["prefkey.trackingprotection.normalbrowsing"].tap() @@ -118,8 +116,8 @@ class TrackingProtectionTests: BaseTestCase { app.buttons["Done"].tap() navigator.nowAt(BrowserTab) navigator.goto(TrackingProtectionContextMenuDetails) - mozWaitForElementToExist(app.staticTexts["Connection is not secure"], timeout: 5) - XCTAssertFalse(app.switches.element.exists) + mozWaitForElementToExist(app.staticTexts["Connection is not secure"]) + mozWaitForElementToNotExist(app.switches.element) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2318742 @@ -128,12 +126,12 @@ class TrackingProtectionTests: BaseTestCase { navigator.goto(TrackingProtectionSettings) // See Basic mode info app.cells["Settings.TrackingProtectionOption.BlockListBasic"].buttons["More Info"].tap() - XCTAssertTrue(app.navigationBars["Client.TPAccessoryInfo"].exists) - XCTAssertTrue(app.cells.staticTexts["Social Trackers"].exists) - XCTAssertTrue(app.cells.staticTexts["Cross-Site Trackers"].exists) - XCTAssertTrue(app.cells.staticTexts["Fingerprinters"].exists) - XCTAssertTrue(app.cells.staticTexts["Cryptominers"].exists) - XCTAssertFalse(app.cells.staticTexts["Tracking content"].exists) + mozWaitForElementToExist(app.navigationBars["Client.TPAccessoryInfo"]) + mozWaitForElementToExist(app.cells.staticTexts["Social Trackers"]) + mozWaitForElementToExist(app.cells.staticTexts["Cross-Site Trackers"]) + mozWaitForElementToExist(app.cells.staticTexts["Fingerprinters"]) + mozWaitForElementToExist(app.cells.staticTexts["Cryptominers"]) + mozWaitForElementToNotExist(app.cells.staticTexts["Tracking content"]) // Go back to TP settings app.buttons["Tracking Protection"].tap() @@ -150,7 +148,7 @@ class TrackingProtectionTests: BaseTestCase { func testLockIconSecureConnection() { navigator.openURL("https://www.Mozilla.org") waitUntilPageLoad() - // iOS 15 displays a toast for the paste. The toast may cover areas to be + // iOS 15 displays a toast for the paste. The toast may cover areas to be // tapped in the next step. if #unavailable(iOS 16) { sleep(2) @@ -159,11 +157,8 @@ class TrackingProtectionTests: BaseTestCase { navigator.nowAt(BrowserTab) navigator.goto(TrackingProtectionContextMenuDetails) // A page displaying the connection is secure - XCTAssertTrue(app.staticTexts["mozilla.org"].exists) - XCTAssertTrue( - app.staticTexts["Connection is secure"].exists, - "Missing Connection is secure info" - ) + mozWaitForElementToExist(app.staticTexts["mozilla.org"]) + mozWaitForElementToExist(app.staticTexts["Connection is secure"]) XCTAssertEqual( app.buttons[AccessibilityIdentifiers.Toolbar.trackingProtection].label, "Secure connection" @@ -178,7 +173,7 @@ class TrackingProtectionTests: BaseTestCase { waitUntilPageLoad() // The page is correctly displayed with the lock icon disabled mozWaitForElementToExist(app.staticTexts["This Connection is Untrusted"], timeout: TIMEOUT_LONG) - XCTAssertTrue(app.staticTexts.elementContainingText("Firefox has not connected to this website.").exists) + mozWaitForElementToExist(app.staticTexts.elementContainingText("Firefox has not connected to this website.")) XCTAssertEqual(app.buttons[AccessibilityIdentifiers.Toolbar.trackingProtection].label, "Connection not secure") } } From 4113f1f4cc276e3c6be1f162dc9cda2743f03a2a Mon Sep 17 00:00:00 2001 From: Lina Butler Date: Thu, 1 Aug 2024 00:53:49 -0700 Subject: [PATCH 023/128] Remove FXIOS-9706 - Remove the awesomebar.{engagement, abandonment} events. (#21386) --- .../Views/BrowserViewController.swift | 2 -- .../Client/Telemetry/TelemetryWrapper.swift | 6 ---- firefox-ios/Client/metrics.yaml | 32 ------------------- 3 files changed, 40 deletions(-) diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift index 65dd3c90261d..f3fd68e5f1a7 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift @@ -3323,13 +3323,11 @@ extension BrowserViewController: SearchViewControllerDelegate { case .engaged: let visibleSuggestionsTelemetryInfo = searchViewController.visibleSuggestionsTelemetryInfo visibleSuggestionsTelemetryInfo.forEach { trackVisibleSuggestion(telemetryInfo: $0) } - TelemetryWrapper.gleanRecordEvent(category: .action, method: .engagement, object: .locationBar) searchViewController.searchTelemetry?.recordURLBarSearchEngagementTelemetryEvent() case .abandoned: searchViewController.searchTelemetry?.engagementType = .dismiss let visibleSuggestionsTelemetryInfo = searchViewController.visibleSuggestionsTelemetryInfo visibleSuggestionsTelemetryInfo.forEach { trackVisibleSuggestion(telemetryInfo: $0) } - TelemetryWrapper.gleanRecordEvent(category: .action, method: .abandonment, object: .locationBar) searchViewController.searchTelemetry?.recordURLBarSearchAbandonmentTelemetryEvent() default: break diff --git a/firefox-ios/Client/Telemetry/TelemetryWrapper.swift b/firefox-ios/Client/Telemetry/TelemetryWrapper.swift index f434c94b83d0..6ccc87e3753b 100644 --- a/firefox-ios/Client/Telemetry/TelemetryWrapper.swift +++ b/firefox-ios/Client/Telemetry/TelemetryWrapper.swift @@ -312,8 +312,6 @@ extension TelemetryWrapper { case switchControl = "switch-control" case dynamicTextSize = "dynamic-text-size" case error = "error" - case engagement = "engagement" - case abandonment = "abandonment" } public enum EventObject: String { @@ -1927,10 +1925,6 @@ extension TelemetryWrapper { GleanMetrics.Awesomebar.shareButtonTapped.record() case (.action, .drag, .locationBar, _, _): GleanMetrics.Awesomebar.dragLocationBar.record() - case (.action, .engagement, .locationBar, _, _): - GleanMetrics.Awesomebar.engagement.record() - case (.action, .abandonment, .locationBar, _, _): - GleanMetrics.Awesomebar.abandonment.record() // MARK: - GleanPlumb Messaging case (.information, .view, .messaging, .messageImpression, let extras): guard let messageSurface = extras?[EventExtraKey.messageSurface.rawValue] as? String, diff --git a/firefox-ios/Client/metrics.yaml b/firefox-ios/Client/metrics.yaml index 97ca132540ca..da204988ea0a 100755 --- a/firefox-ios/Client/metrics.yaml +++ b/firefox-ios/Client/metrics.yaml @@ -4620,38 +4620,6 @@ awesomebar: notification_emails: - fx-ios-data-stewards@mozilla.com expires: "2025-01-01" - engagement: - type: event - description: | - Recorded when the user completes their search session by - tapping a search result, or entering a URL or a search term. - bugs: - - https://mozilla-hub.atlassian.net/browse/FXIOS-8326 - - https://mozilla-hub.atlassian.net/browse/FXIOS-8550 - data_reviews: - - https://github.com/mozilla-mobile/firefox-ios/pull/18452 - - https://github.com/mozilla-mobile/firefox-ios/pull/19009 - notification_emails: - - fx-ios-data-stewards@mozilla.com - data_sensitivity: - - interaction - expires: "2025-01-01" - abandonment: - type: event - description: | - Recorded when the user dismisses the awesomebar without completing their - search. - bugs: - - https://mozilla-hub.atlassian.net/browse/FXIOS-8326 - - https://mozilla-hub.atlassian.net/browse/FXIOS-8550 - data_reviews: - - https://github.com/mozilla-mobile/firefox-ios/pull/18452 - - https://github.com/mozilla-mobile/firefox-ios/pull/19009 - notification_emails: - - fx-ios-data-stewards@mozilla.com - data_sensitivity: - - interaction - expires: "2025-01-01" # Share sheet specific metrics From a4e54fe2ba9bb2fa9a95f49a1d5d38ab93a5f5d5 Mon Sep 17 00:00:00 2001 From: dicarobinho <61138287+dicarobinho@users.noreply.github.com> Date: Thu, 1 Aug 2024 11:14:09 +0300 Subject: [PATCH 024/128] Bugfix FXIOS-9681 - Few constraints and scrollview are not working as expected for TrackingProtectionViewController (#21315) * FXIOS-9681 #21294 - Few constraints and scrollview are not working as expected for TrackingProtectionViewController Fixed some SwiftLint warnings Fixed testShowEnhancedTrackingProtection test Fixed some review changes Fixed testLockIconMenu() test and added a new UX value Fixed testLockIconMenu() test. Added a TODO comment --- firefox-ios/Client.xcodeproj/project.pbxproj | 4 + ...nhancedTrackingProtectionCoordinator.swift | 84 +- .../SlideoverPresentationController.swift | 11 +- .../TrackingProtectionViewController.swift | 905 ++++++++++++++++++ .../BrowserCoordinatorTests.swift | 9 +- .../XCUITests/TrackingProtectionTests.swift | 12 +- 6 files changed, 995 insertions(+), 30 deletions(-) create mode 100644 firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionViewController.swift diff --git a/firefox-ios/Client.xcodeproj/project.pbxproj b/firefox-ios/Client.xcodeproj/project.pbxproj index b66e0206d3af..b95e775f0bad 100644 --- a/firefox-ios/Client.xcodeproj/project.pbxproj +++ b/firefox-ios/Client.xcodeproj/project.pbxproj @@ -15,6 +15,7 @@ 047F9B3224E1FE1F00CD7DF7 /* WidgetKitExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 047F9B2724E1FE1C00CD7DF7 /* WidgetKitExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 047F9B3E24E1FF4000CD7DF7 /* SearchQuickLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 047F9B3A24E1FF4000CD7DF7 /* SearchQuickLinks.swift */; }; 047F9B4224E1FF4000CD7DF7 /* ImageButtonWithLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 047F9B3C24E1FF4000CD7DF7 /* ImageButtonWithLabel.swift */; }; + 0A49784A2C53E63200B1E82A /* TrackingProtectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A4978492C53E63200B1E82A /* TrackingProtectionViewController.swift */; }; 0AC659272BF35854005C614A /* FxAWebViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AC659262BF35854005C614A /* FxAWebViewModelTests.swift */; }; 0AC659292BF493CE005C614A /* MockFxAWebViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AC659282BF493CE005C614A /* MockFxAWebViewModel.swift */; }; 0AD3EEAC2C2485A7001044E5 /* ThemedCenteredTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AD3EEAB2C2485A7001044E5 /* ThemedCenteredTableViewCell.swift */; }; @@ -2144,6 +2145,7 @@ 09D94B5E8CF4C06397168F78 /* my */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = my; path = "my.lproj/Default Browser.strings"; sourceTree = ""; }; 09F14D989587092C60A0078F /* ga */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ga; path = ga.lproj/Shared.strings; sourceTree = ""; }; 0A3A4A9EB784F7903FB13B7A /* ms */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ms; path = ms.lproj/LoginManager.strings; sourceTree = ""; }; + 0A4978492C53E63200B1E82A /* TrackingProtectionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrackingProtectionViewController.swift; sourceTree = ""; }; 0A574D09BF8D9E37D6C9C654 /* bn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bn; path = bn.lproj/ClearHistoryConfirm.strings; sourceTree = ""; }; 0A5B4CE9B0996AE804491134 /* an */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = an; path = an.lproj/Shared.strings; sourceTree = ""; }; 0A734328A164466314ECE4BE /* ia */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ia; path = ia.lproj/Menu.strings; sourceTree = ""; }; @@ -10937,6 +10939,7 @@ AB9CBC012C53B64B00102610 /* TrackingProtectionState.swift */, AB2AC6652BD15E6300022AAB /* CertificatesHandler.swift */, AB936A682C05F2B100600F82 /* TrackingProtectionButton.swift */, + 0A4978492C53E63200B1E82A /* TrackingProtectionViewController.swift */, ); path = TrackingProtection; sourceTree = ""; @@ -15390,6 +15393,7 @@ C849E46126B9C39B00260F0B /* EnhancedTrackingProtectionVC.swift in Sources */, E40FAB0C1A7ABB77009CB80D /* WebServer.swift in Sources */, 59A68D66379CFA85C4EAF00B /* TwoLineImageOverlayCell.swift in Sources */, + 0A49784A2C53E63200B1E82A /* TrackingProtectionViewController.swift in Sources */, 8A04136928258DF600D20B10 /* SponsoredTileTelemetry.swift in Sources */, D04CD718215EBD85004FF5B0 /* SettingsLoadingView.swift in Sources */, 21420EF72ABA338D00B28550 /* TabTrayCoordinator.swift in Sources */, diff --git a/firefox-ios/Client/Coordinators/EnhancedTrackingProtectionCoordinator.swift b/firefox-ios/Client/Coordinators/EnhancedTrackingProtectionCoordinator.swift index 4316d5c47bf3..c30aac68d667 100644 --- a/firefox-ios/Client/Coordinators/EnhancedTrackingProtectionCoordinator.swift +++ b/firefox-ios/Client/Coordinators/EnhancedTrackingProtectionCoordinator.swift @@ -13,11 +13,17 @@ protocol EnhancedTrackingProtectionCoordinatorDelegate: AnyObject { } class EnhancedTrackingProtectionCoordinator: BaseCoordinator, - EnhancedTrackingProtectionMenuDelegate { + TrackingProtectionMenuDelegate, + EnhancedTrackingProtectionMenuDelegate, + FeatureFlaggable { private let profile: Profile private let tabManager: TabManager - private let enhancedTrackingProtectionMenuVC: EnhancedTrackingProtectionMenuVC + private var legacyEnhancedTrackingProtectionMenuVC: EnhancedTrackingProtectionMenuVC? + private var enhancedTrackingProtectionMenuVC: TrackingProtectionViewController? weak var parentCoordinator: EnhancedTrackingProtectionCoordinatorDelegate? + private var trackingProtectionRefactorStatus: Bool { + featureFlags.isFeatureEnabled(.trackingProtectionRefactor, checking: .buildOnly) + } init(router: Router, profile: Profile = AppContainer.shared.resolve(), @@ -27,33 +33,69 @@ class EnhancedTrackingProtectionCoordinator: BaseCoordinator, let url = tab?.url ?? URL(fileURLWithPath: "") let displayTitle = tab?.displayTitle ?? "" let contentBlockerStatus = tab?.contentBlocker?.status ?? .blocking + let contentBlockerStats = tab?.contentBlocker?.stats let connectionSecure = tab?.webView?.hasOnlySecureContent ?? true - let etpViewModel = EnhancedTrackingProtectionMenuVM( - url: url, - displayTitle: displayTitle, - connectionSecure: connectionSecure, - globalETPIsEnabled: FirefoxTabContentBlocker.isTrackingProtectionEnabled(prefs: profile.prefs), - contentBlockerStatus: contentBlockerStatus) - - self.enhancedTrackingProtectionMenuVC = EnhancedTrackingProtectionMenuVC(viewModel: etpViewModel, - windowUUID: tabManager.windowUUID) self.profile = profile self.tabManager = tabManager super.init(router: router) - enhancedTrackingProtectionMenuVC.enhancedTrackingProtectionMenuDelegate = self + if self.trackingProtectionRefactorStatus { + let etpViewModel = TrackingProtectionModel( + url: url, + displayTitle: displayTitle, + connectionSecure: connectionSecure, + globalETPIsEnabled: FirefoxTabContentBlocker.isTrackingProtectionEnabled(prefs: profile.prefs), + contentBlockerStatus: contentBlockerStatus, + contentBlockerStats: contentBlockerStats + ) + + self.enhancedTrackingProtectionMenuVC = TrackingProtectionViewController(viewModel: etpViewModel, + windowUUID: tabManager.windowUUID) + } else { + let oldEtpViewModel = EnhancedTrackingProtectionMenuVM( + url: url, + displayTitle: displayTitle, + connectionSecure: connectionSecure, + globalETPIsEnabled: FirefoxTabContentBlocker.isTrackingProtectionEnabled(prefs: profile.prefs), + contentBlockerStatus: contentBlockerStatus + ) + + self.legacyEnhancedTrackingProtectionMenuVC = EnhancedTrackingProtectionMenuVC(viewModel: oldEtpViewModel, + windowUUID: tabManager.windowUUID) + } + enhancedTrackingProtectionMenuVC?.enhancedTrackingProtectionMenuDelegate = self } func start(sourceView: UIView) { - if UIDevice.current.userInterfaceIdiom == .phone { - enhancedTrackingProtectionMenuVC.modalPresentationStyle = .custom - enhancedTrackingProtectionMenuVC.transitioningDelegate = self - } else { - enhancedTrackingProtectionMenuVC.asPopover = true - enhancedTrackingProtectionMenuVC.modalPresentationStyle = .popover - enhancedTrackingProtectionMenuVC.popoverPresentationController?.sourceView = sourceView - enhancedTrackingProtectionMenuVC.popoverPresentationController?.permittedArrowDirections = .up + if trackingProtectionRefactorStatus, let enhancedTrackingProtectionMenuVC { + if UIDevice.current.userInterfaceIdiom == .phone { + if let sheetPresentationController = enhancedTrackingProtectionMenuVC.sheetPresentationController { + sheetPresentationController.detents = [.medium(), .large()] + sheetPresentationController.prefersScrollingExpandsWhenScrolledToEdge = true + sheetPresentationController.preferredCornerRadius = TPMenuUX.UX.modalMenuCornerRadius + } + router.present(enhancedTrackingProtectionMenuVC, animated: true, completion: nil) + } else { + enhancedTrackingProtectionMenuVC.asPopover = true + if trackingProtectionRefactorStatus { + enhancedTrackingProtectionMenuVC.preferredContentSize = CGSize(width: 480, height: 517) + } + enhancedTrackingProtectionMenuVC.modalPresentationStyle = .popover + enhancedTrackingProtectionMenuVC.popoverPresentationController?.sourceView = sourceView + enhancedTrackingProtectionMenuVC.popoverPresentationController?.permittedArrowDirections = .up + router.present(enhancedTrackingProtectionMenuVC, animated: true, completion: nil) + } + } else if let legacyEnhancedTrackingProtectionMenuVC { + if UIDevice.current.userInterfaceIdiom == .phone { + legacyEnhancedTrackingProtectionMenuVC.modalPresentationStyle = .custom + legacyEnhancedTrackingProtectionMenuVC.transitioningDelegate = self + } else { + legacyEnhancedTrackingProtectionMenuVC.asPopover = true + legacyEnhancedTrackingProtectionMenuVC.modalPresentationStyle = .popover + legacyEnhancedTrackingProtectionMenuVC.popoverPresentationController?.sourceView = sourceView + legacyEnhancedTrackingProtectionMenuVC.popoverPresentationController?.permittedArrowDirections = .up + } + router.present(legacyEnhancedTrackingProtectionMenuVC, animated: true, completion: nil) } - router.present(enhancedTrackingProtectionMenuVC, animated: true, completion: nil) } // MARK: - EnhancedTrackingProtectionMenuDelegate diff --git a/firefox-ios/Client/Frontend/Browser/EnhancedTrackingProtection/SlideoverPresentationController.swift b/firefox-ios/Client/Frontend/Browser/EnhancedTrackingProtection/SlideoverPresentationController.swift index 7e48c68f3c4f..56a250661bac 100644 --- a/firefox-ios/Client/Frontend/Browser/EnhancedTrackingProtection/SlideoverPresentationController.swift +++ b/firefox-ios/Client/Frontend/Browser/EnhancedTrackingProtection/SlideoverPresentationController.swift @@ -8,11 +8,12 @@ struct SlideOverUXConstants { static let ETPMenuCornerRadius: CGFloat = 8 } -class SlideOverPresentationController: UIPresentationController { +class SlideOverPresentationController: UIPresentationController, FeatureFlaggable { let blurEffectView: UIVisualEffectView! var tapGestureRecognizer = UITapGestureRecognizer() var globalETPStatus: Bool weak var enhancedTrackingProtectionMenuDelegate: EnhancedTrackingProtectionMenuDelegate? + weak var legacyTrackingProtectionMenuDelegate: TrackingProtectionMenuDelegate? init( presentedViewController: UIViewController, @@ -88,7 +89,13 @@ class SlideOverPresentationController: UIPresentationController { @objc func dismissController() { - enhancedTrackingProtectionMenuDelegate?.didFinish() + let trackingProtectionRefactorStatus = featureFlags.isFeatureEnabled(.trackingProtectionRefactor, + checking: .buildOnly) + if trackingProtectionRefactorStatus { + enhancedTrackingProtectionMenuDelegate?.didFinish() + } else { + legacyTrackingProtectionMenuDelegate?.didFinish() + } } override func preferredContentSizeDidChange(forChildContentContainer container: UIContentContainer) { diff --git a/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionViewController.swift b/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionViewController.swift new file mode 100644 index 000000000000..037015272164 --- /dev/null +++ b/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionViewController.swift @@ -0,0 +1,905 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/ + +import Shared +import UIKit +import Common +import ComponentLibrary +import SiteImageView + +struct TPMenuUX { + struct Fonts { + static let websiteTitle: TextStyling = FXFontStyles.Regular.headline + static let viewTitleLabels: TextStyling = FXFontStyles.Regular.body + static let detailsLabel: TextStyling = FXFontStyles.Regular.caption1 + static let minorInfoLabel: TextStyling = FXFontStyles.Regular.subheadline + } + + struct UX { + static let baseCellHeight: CGFloat = 44 + static let popoverTopDistance: CGFloat = 20 + static let horizontalMargin: CGFloat = 16 + static let viewCornerRadius: CGFloat = 8 + static let headerLabelDistance: CGFloat = 2.0 + static let headerLinesLimit: Int = 2 + static let foxImageSize: CGFloat = 100 + static let iconSize: CGFloat = 24 + static let protectionViewBottomSpacing: CGFloat = 70 + static let siteDomainLabelsVerticalSpacing: CGFloat = 12 + static let connectionDetailsLabelBottomSpacing: CGFloat = 28 + static let connectionDetailsHeaderMargins: CGFloat = 8 + static let faviconImageSize: CGFloat = 40 + static let closeButtonSize: CGFloat = 30 + static let faviconCornerRadius: CGFloat = 5 + static let scrollContentHorizontalPadding: CGFloat = 16 + + static let clearDataButtonCornerRadius: CGFloat = 12 + static let clearDataButtonBorderWidth: CGFloat = 1 + static let settingsLinkButtonBottomSpacing: CGFloat = 32 + static let connectionDetailsStackSpacing = 15.0 + + static let modalMenuCornerRadius: CGFloat = 12 + struct Line { + static let height: CGFloat = 1 + } + struct TrackingDetails { + static let baseDistance: CGFloat = 20 + static let imageMargins: CGFloat = 10 + static let bottomDistance: CGFloat = 350 + static let viewCertButtonTopDistance: CGFloat = 8.0 + } + struct BlockedTrackers { + static let headerDistance: CGFloat = 8 + } + } +} + +protocol TrackingProtectionMenuDelegate: AnyObject { + func settingsOpenPage(settings: Route.SettingsSection) + func didFinish() +} + +// TODO: FXIOS-9726 #21369 - Refactor/Split TrackingProtectionViewController UI into more custom views +class TrackingProtectionViewController: UIViewController, Themeable, Notifiable, UIScrollViewDelegate, BottomSheetChild { + var themeManager: ThemeManager + var themeObserver: NSObjectProtocol? + var notificationCenter: NotificationProtocol + let windowUUID: WindowUUID + var currentWindowUUID: UUID? { windowUUID } + + weak var enhancedTrackingProtectionMenuDelegate: TrackingProtectionMenuDelegate? + + private var faviconHeightConstraint: NSLayoutConstraint? + private var faviconWidthConstraint: NSLayoutConstraint? + private var foxImageHeightConstraint: NSLayoutConstraint? + private var shieldImageHeightConstraint: NSLayoutConstraint? + private var lockImageHeightConstraint: NSLayoutConstraint? + + private var trackersArrowHeightConstraint: NSLayoutConstraint? + private var connectionArrowHeightConstraint: NSLayoutConstraint? + + private lazy var scrollView: UIScrollView = .build { scrollView in + scrollView.translatesAutoresizingMaskIntoConstraints = false + scrollView.showsVerticalScrollIndicator = false + } + + private let baseView: UIView = .build { view in + view.translatesAutoresizingMaskIntoConstraints = false + } + + // MARK: UI components Header View + private let headerContainer: UIView = .build { view in + view.backgroundColor = .clear + } + + private lazy var headerLabelsContainer: UIStackView = .build { stack in + stack.backgroundColor = .clear + stack.alignment = .leading + stack.axis = .vertical + stack.spacing = TPMenuUX.UX.headerLabelDistance + } + + private var favicon: FaviconImageView = .build { favicon in + favicon.manuallySetImage( + UIImage(named: StandardImageIdentifiers.Large.globe)?.withRenderingMode(.alwaysTemplate) ?? UIImage()) + } + + private let siteDisplayTitleLabel: UILabel = .build { label in + label.font = FXFontStyles.Regular.headline.scaledFont() + label.numberOfLines = TPMenuUX.UX.headerLinesLimit + label.adjustsFontForContentSizeCategory = true + label.translatesAutoresizingMaskIntoConstraints = false + } + + private let siteDomainLabel: UILabel = .build { label in + label.font = FXFontStyles.Regular.caption1.scaledFont() + label.numberOfLines = 0 + label.adjustsFontForContentSizeCategory = true + label.translatesAutoresizingMaskIntoConstraints = false + } + + private var closeButton: CloseButton = .build { button in + button.layer.cornerRadius = 0.5 * TPMenuUX.UX.closeButtonSize + } + + // MARK: Connection Details View + private let connectionDetailsHeaderView: UIView = .build { view in + view.layer.cornerRadius = TPMenuUX.UX.viewCornerRadius + view.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner] + view.layer.masksToBounds = true + } + private let connectionDetailsContentView: UIView = .build { view in + view.layer.cornerRadius = TPMenuUX.UX.viewCornerRadius + view.layer.masksToBounds = true + } + + private let foxStatusImage: UIImageView = .build { image in + image.contentMode = .scaleAspectFit + image.clipsToBounds = true + } + + private var connectionDetailsLabelsContainer: UIStackView = .build { stack in + stack.backgroundColor = .clear + stack.distribution = .fillProportionally + stack.alignment = .leading + stack.axis = .vertical + stack.spacing = TPMenuUX.UX.connectionDetailsStackSpacing + } + + private var connectionDetailsTitleLabel: UILabel = .build { label in + label.font = FXFontStyles.Bold.subheadline.scaledFont() + label.numberOfLines = 0 + label.adjustsFontForContentSizeCategory = true + } + + private let connectionDetailsStatusLabel: UILabel = .build { label in + label.font = FXFontStyles.Regular.subheadline.scaledFont() + label.numberOfLines = 0 + label.adjustsFontForContentSizeCategory = true + } + + // MARK: Blocked Trackers View + private let trackersView: UIView = .build { view in + view.backgroundColor = .clear + } + + private let shieldImage: UIImageView = .build { image in + image.contentMode = .scaleAspectFit + image.clipsToBounds = true + image.layer.masksToBounds = true + image.image = UIImage(imageLiteralResourceName: StandardImageIdentifiers.Large.shield) + .withRenderingMode(.alwaysTemplate) + } + + private let trackersLabel: UILabel = .build { label in + label.font = FXFontStyles.Regular.body.scaledFont() + label.numberOfLines = 0 + label.adjustsFontForContentSizeCategory = true + } + + private let trackersDetailArrow: UIImageView = .build { image in + image.image = UIImage(imageLiteralResourceName: StandardImageIdentifiers.Large.chevronLeft) + .withRenderingMode(.alwaysTemplate) + .imageFlippedForRightToLeftLayoutDirection() + image.transform = CGAffineTransform(rotationAngle: .pi) + } + + private let trackersHorizontalLine: UIView = .build { _ in } + private let trackersButton: UIButton = .build { button in } + + // MARK: Connection Status View + private let connectionView: UIView = .build { view in + view.backgroundColor = .clear + } + + private let connectionStatusImage: UIImageView = .build { image in + image.contentMode = .scaleAspectFit + image.clipsToBounds = true + image.layer.masksToBounds = true + } + + private let connectionStatusLabel: UILabel = .build { label in + label.font = FXFontStyles.Regular.body.scaledFont() + label.numberOfLines = 0 + label.adjustsFontForContentSizeCategory = true + } + + private let connectionDetailArrow: UIImageView = .build { image in + image.image = UIImage(imageLiteralResourceName: StandardImageIdentifiers.Large.chevronLeft) + .withRenderingMode(.alwaysTemplate) + .imageFlippedForRightToLeftLayoutDirection() + image.transform = CGAffineTransform(rotationAngle: .pi) + } + + private let connectionButton: UIButton = .build { button in } + private let connectionHorizontalLine: UIView = .build { _ in } + + // MARK: Toggle View + private let toggleView: UIView = .build { view in + view.layer.cornerRadius = TPMenuUX.UX.viewCornerRadius + view.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMaxYCorner] + view.backgroundColor = .clear + view.translatesAutoresizingMaskIntoConstraints = false + } + private let toggleLabelsContainer: UIStackView = .build { stack in + stack.backgroundColor = .clear + stack.distribution = .fill + stack.alignment = .leading + stack.axis = .vertical + stack.spacing = TPMenuUX.UX.headerLabelDistance + } + + private let toggleLabel: UILabel = .build { label in + label.font = FXFontStyles.Regular.body.scaledFont() + label.numberOfLines = 0 + label.adjustsFontForContentSizeCategory = true + } + + private let toggleSwitch: UISwitch = .build { toggleSwitch in + toggleSwitch.isEnabled = true + } + + private let toggleStatusLabel: UILabel = .build { label in + label.font = FXFontStyles.Regular.caption1.scaledFont() + label.numberOfLines = 0 + label.adjustsFontForContentSizeCategory = true + } + + // MARK: Clear Cookies View + private lazy var clearCookiesButton: TrackingProtectionButton = .build { button in + button.titleLabel?.textAlignment = .left + button.titleLabel?.numberOfLines = 0 + button.layer.cornerRadius = TPMenuUX.UX.clearDataButtonCornerRadius + button.layer.borderWidth = TPMenuUX.UX.clearDataButtonBorderWidth + button.addTarget(self, action: #selector(self.didTapClearCookiesAndSiteData), for: .touchUpInside) + } + + // MARK: Protection setting view + private lazy var settingsLinkButton: LinkButton = .build { button in + button.titleLabel?.textAlignment = .left + button.titleLabel?.numberOfLines = 0 + button.addTarget(self, action: #selector(self.protectionSettingsTapped), for: .touchUpInside) + } + + private var constraints = [NSLayoutConstraint]() + + // MARK: - Variables + + private var viewModel: TrackingProtectionModel + private var hasSetPointOrigin = false + private var pointOrigin: CGPoint? + var asPopover = false + + private var toggleContainerShouldBeHidden: Bool { + return !viewModel.globalETPIsEnabled + } + + private var protectionViewTopConstraint: NSLayoutConstraint? + + // MARK: - View lifecycle + + init(viewModel: TrackingProtectionModel, + windowUUID: WindowUUID, + themeManager: ThemeManager = AppContainer.shared.resolve(), + notificationCenter: NotificationProtocol = NotificationCenter.default) { + self.viewModel = viewModel + self.windowUUID = windowUUID + self.themeManager = themeManager + self.notificationCenter = notificationCenter + super.init(nibName: nil, bundle: nil) + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func viewDidLoad() { + super.viewDidLoad() + if !asPopover { + addGestureRecognizer() + } + setupView() + listenForThemeChange(view) + setupNotifications(forObserver: self, + observing: [.DynamicFontChanged]) + scrollView.delegate = self + } + + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + self.view.invalidateIntrinsicContentSize() // Adjusts size based on content. + if !hasSetPointOrigin { + hasSetPointOrigin = true + pointOrigin = self.view.frame.origin + } + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + updateViewDetails() + applyTheme() + } + + private func setupView() { + constraints.removeAll() + + setupContentView() + setupHeaderView() + setupConnectionHeaderView() + setupBlockedTrackersView() + setupConnectionStatusView() + setupToggleView() + setupClearCookiesButton() + setupProtectionSettingsView() + setupViewActions() + + NSLayoutConstraint.activate(constraints) + setupAccessibilityIdentifiers() + } + + // MARK: Content View + private func setupContentView() { + view.addSubview(scrollView) + + let scrollViewConstraints = [ + scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor), + scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor), + scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor) + ] + + constraints.append(contentsOf: scrollViewConstraints) + scrollView.addSubview(baseView) + + let baseViewConstraints = [ + baseView.topAnchor.constraint(equalTo: scrollView.topAnchor), + baseView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor), + baseView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor), + baseView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor), + baseView.widthAnchor.constraint(equalTo: scrollView.widthAnchor) + ] + + constraints.append(contentsOf: baseViewConstraints) + } + + // MARK: Header Setup + private func setupHeaderView() { + headerLabelsContainer.addArrangedSubview(siteDisplayTitleLabel) + headerLabelsContainer.addArrangedSubview(siteDomainLabel) + + headerContainer.addSubviews(favicon, headerLabelsContainer, closeButton) + baseView.addSubview(headerContainer) + + faviconHeightConstraint = favicon.heightAnchor.constraint(equalToConstant: TPMenuUX.UX.faviconImageSize) + faviconWidthConstraint = favicon.widthAnchor.constraint(equalToConstant: TPMenuUX.UX.faviconImageSize) + let topDistance = asPopover ? TPMenuUX.UX.popoverTopDistance : 0 + + let headerConstraints = [ + headerContainer.leadingAnchor.constraint(equalTo: baseView.leadingAnchor), + headerContainer.trailingAnchor.constraint(equalTo: baseView.trailingAnchor), + headerContainer.topAnchor.constraint( + equalTo: baseView.topAnchor, + constant: topDistance + ), + + favicon.leadingAnchor.constraint( + equalTo: headerContainer.leadingAnchor, + constant: TPMenuUX.UX.horizontalMargin + ), + favicon.centerYAnchor.constraint(equalTo: headerContainer.centerYAnchor), + faviconHeightConstraint!, + faviconWidthConstraint!, + + headerLabelsContainer.topAnchor.constraint( + equalTo: headerContainer.topAnchor, + constant: TPMenuUX.UX.siteDomainLabelsVerticalSpacing + ), + headerLabelsContainer.bottomAnchor.constraint( + equalTo: headerContainer.bottomAnchor, + constant: -TPMenuUX.UX.siteDomainLabelsVerticalSpacing + ), + headerLabelsContainer.leadingAnchor.constraint( + equalTo: favicon.trailingAnchor, + constant: TPMenuUX.UX.siteDomainLabelsVerticalSpacing + ), + headerLabelsContainer.trailingAnchor.constraint( + equalTo: closeButton.leadingAnchor, + constant: -TPMenuUX.UX.horizontalMargin + ), + + closeButton.trailingAnchor.constraint( + equalTo: headerContainer.trailingAnchor, + constant: -TPMenuUX.UX.horizontalMargin + ), + closeButton.topAnchor.constraint( + equalTo: headerContainer.topAnchor, + constant: TPMenuUX.UX.horizontalMargin + ), + closeButton.heightAnchor.constraint(greaterThanOrEqualToConstant: TPMenuUX.UX.closeButtonSize), + closeButton.widthAnchor.constraint(greaterThanOrEqualToConstant: TPMenuUX.UX.closeButtonSize), + ] + + constraints.append(contentsOf: headerConstraints) + } + + // MARK: Connection Status Header Setup + private func setupConnectionHeaderView() { + connectionDetailsLabelsContainer.addArrangedSubview(connectionDetailsTitleLabel) + connectionDetailsLabelsContainer.addArrangedSubview(connectionDetailsStatusLabel) + connectionDetailsContentView.addSubviews(foxStatusImage, connectionDetailsLabelsContainer) + connectionDetailsHeaderView.addSubview(connectionDetailsContentView) + + baseView.addSubviews(connectionDetailsHeaderView) + let connectionHeaderConstraints = [ + // Section + connectionDetailsHeaderView.leadingAnchor.constraint( + equalTo: view.leadingAnchor, + constant: TPMenuUX.UX.horizontalMargin + ), + connectionDetailsHeaderView.trailingAnchor.constraint( + equalTo: view.trailingAnchor, + constant: -TPMenuUX.UX.horizontalMargin + ), + connectionDetailsHeaderView.topAnchor.constraint(equalTo: headerContainer.bottomAnchor, + constant: 0), + // Content + connectionDetailsContentView.leadingAnchor.constraint( + equalTo: connectionDetailsHeaderView.leadingAnchor, + constant: TPMenuUX.UX.connectionDetailsHeaderMargins + ), + connectionDetailsContentView.trailingAnchor.constraint( + equalTo: connectionDetailsHeaderView.trailingAnchor, + constant: -TPMenuUX.UX.connectionDetailsHeaderMargins + ), + connectionDetailsContentView.topAnchor.constraint(equalTo: connectionDetailsHeaderView.topAnchor, + constant: TPMenuUX.UX.connectionDetailsHeaderMargins), + connectionDetailsContentView.bottomAnchor.constraint(equalTo: connectionDetailsHeaderView.bottomAnchor, + constant: -TPMenuUX.UX.connectionDetailsHeaderMargins / 2), + // Image + foxStatusImage.leadingAnchor.constraint( + equalTo: connectionDetailsContentView.leadingAnchor, + constant: TPMenuUX.UX.horizontalMargin + ), + foxStatusImage.topAnchor.constraint( + equalTo: connectionDetailsContentView.topAnchor, + constant: TPMenuUX.UX.horizontalMargin + ), + foxStatusImage.heightAnchor.constraint(equalToConstant: TPMenuUX.UX.foxImageSize), + foxStatusImage.widthAnchor.constraint(equalToConstant: TPMenuUX.UX.foxImageSize), + + // Labels + connectionDetailsLabelsContainer.topAnchor.constraint( + equalTo: connectionDetailsContentView.topAnchor, + constant: TPMenuUX.UX.horizontalMargin + ), + connectionDetailsLabelsContainer.bottomAnchor.constraint( + equalTo: connectionDetailsContentView.bottomAnchor, + constant: -TPMenuUX.UX.connectionDetailsLabelBottomSpacing / 2 + ), + connectionDetailsLabelsContainer.leadingAnchor.constraint(equalTo: foxStatusImage.trailingAnchor, + constant: TPMenuUX.UX.siteDomainLabelsVerticalSpacing), + connectionDetailsLabelsContainer.trailingAnchor.constraint(equalTo: + connectionDetailsContentView.trailingAnchor, + constant: -TPMenuUX.UX.horizontalMargin), + connectionDetailsLabelsContainer.heightAnchor.constraint(greaterThanOrEqualToConstant: TPMenuUX.UX.foxImageSize), + ] + + constraints.append(contentsOf: connectionHeaderConstraints) + } + + // MARK: Blocked Trackers Setup + private func setupBlockedTrackersView() { + trackersView.addSubviews(shieldImage, trackersLabel, trackersDetailArrow, trackersButton, trackersHorizontalLine) + baseView.addSubview(trackersView) + view.bringSubviewToFront(trackersView) + + shieldImageHeightConstraint = shieldImage.heightAnchor.constraint(equalToConstant: TPMenuUX.UX.iconSize) + trackersArrowHeightConstraint = trackersDetailArrow.heightAnchor.constraint( + equalToConstant: TPMenuUX.UX.iconSize + ) + + let blockedTrackersConstraints = [ + trackersView.leadingAnchor.constraint( + equalTo: view.leadingAnchor, + constant: TPMenuUX.UX.horizontalMargin + ), + trackersView.trailingAnchor.constraint( + equalTo: view.trailingAnchor, + constant: -TPMenuUX.UX.horizontalMargin + ), + trackersView.topAnchor.constraint(equalTo: connectionDetailsHeaderView.bottomAnchor, constant: 0), + + shieldImage.leadingAnchor.constraint( + equalTo: trackersView.leadingAnchor, + constant: TPMenuUX.UX.horizontalMargin + ), + shieldImage.centerYAnchor.constraint(equalTo: trackersView.centerYAnchor), + shieldImage.heightAnchor.constraint(equalTo: shieldImage.widthAnchor), + shieldImageHeightConstraint!, + trackersLabel.leadingAnchor.constraint( + equalTo: shieldImage.trailingAnchor, + constant: TPMenuUX.UX.horizontalMargin + ), + trackersLabel.topAnchor.constraint(equalTo: trackersView.topAnchor, constant: 11), + trackersLabel.bottomAnchor.constraint(equalTo: trackersView.bottomAnchor, constant: -11), + trackersLabel.trailingAnchor.constraint( + equalTo: trackersDetailArrow.leadingAnchor, + constant: TPMenuUX.UX.horizontalMargin + ), + + trackersDetailArrow.trailingAnchor.constraint( + equalTo: connectionView.trailingAnchor, + constant: -TPMenuUX.UX.horizontalMargin + ), + trackersDetailArrow.centerYAnchor.constraint(equalTo: trackersView.centerYAnchor), + trackersArrowHeightConstraint!, + trackersDetailArrow.widthAnchor.constraint(equalTo: trackersDetailArrow.heightAnchor), + + trackersButton.leadingAnchor.constraint(equalTo: trackersView.leadingAnchor), + trackersButton.topAnchor.constraint(equalTo: trackersView.topAnchor), + trackersButton.trailingAnchor.constraint(equalTo: trackersView.trailingAnchor), + trackersButton.bottomAnchor.constraint(equalTo: trackersView.bottomAnchor), + + trackersHorizontalLine.leadingAnchor.constraint(equalTo: trackersLabel.leadingAnchor), + trackersHorizontalLine.trailingAnchor.constraint(equalTo: trackersView.trailingAnchor, + constant: -TPMenuUX.UX.connectionDetailsHeaderMargins), + trackersHorizontalLine.heightAnchor.constraint(equalToConstant: TPMenuUX.UX.Line.height), + trackersView.bottomAnchor.constraint(equalTo: trackersHorizontalLine.bottomAnchor), + ] + + constraints.append(contentsOf: blockedTrackersConstraints) + } + + // MARK: Connection Status Setup + private func setupConnectionStatusView() { + connectionView.addSubviews(connectionStatusImage, connectionStatusLabel, connectionDetailArrow) + connectionView.addSubviews(connectionButton, connectionHorizontalLine) + baseView.addSubviews(connectionView) + + lockImageHeightConstraint = connectionStatusImage.widthAnchor.constraint( + equalToConstant: TPMenuUX.UX.iconSize + ) + connectionArrowHeightConstraint = connectionDetailArrow.heightAnchor.constraint( + equalToConstant: TPMenuUX.UX.iconSize + ) + let connectionConstraints = [ + connectionView.leadingAnchor.constraint( + equalTo: view.leadingAnchor, + constant: TPMenuUX.UX.horizontalMargin + ), + connectionView.trailingAnchor.constraint( + equalTo: view.trailingAnchor, + constant: -TPMenuUX.UX.horizontalMargin + ), + connectionView.topAnchor.constraint(equalTo: trackersView.bottomAnchor, constant: 0), + + connectionStatusImage.leadingAnchor.constraint( + equalTo: connectionView.leadingAnchor, + constant: TPMenuUX.UX.horizontalMargin + ), + connectionStatusImage.centerYAnchor.constraint(equalTo: connectionView.centerYAnchor), + lockImageHeightConstraint!, + connectionStatusImage.heightAnchor.constraint(equalTo: connectionView.widthAnchor), + + connectionStatusLabel.leadingAnchor.constraint( + equalTo: connectionStatusImage.trailingAnchor, + constant: TPMenuUX.UX.horizontalMargin + ), + connectionStatusLabel.topAnchor.constraint(equalTo: connectionView.topAnchor, constant: 11), + connectionStatusLabel.bottomAnchor.constraint(equalTo: connectionView.bottomAnchor, constant: -11), + connectionStatusLabel.trailingAnchor.constraint( + equalTo: connectionDetailArrow.leadingAnchor, + constant: TPMenuUX.UX.horizontalMargin + ), + + connectionDetailArrow.trailingAnchor.constraint( + equalTo: connectionView.trailingAnchor, + constant: -TPMenuUX.UX.horizontalMargin + ), + connectionDetailArrow.centerYAnchor.constraint(equalTo: connectionView.centerYAnchor), + connectionArrowHeightConstraint!, + connectionDetailArrow.widthAnchor.constraint(equalTo: connectionDetailArrow.heightAnchor), + + connectionButton.leadingAnchor.constraint(equalTo: connectionView.leadingAnchor), + connectionButton.topAnchor.constraint(equalTo: connectionView.topAnchor), + connectionButton.trailingAnchor.constraint(equalTo: connectionView.trailingAnchor), + connectionButton.bottomAnchor.constraint(equalTo: connectionView.bottomAnchor), + + connectionHorizontalLine.leadingAnchor.constraint(equalTo: connectionView.leadingAnchor), + connectionHorizontalLine.trailingAnchor.constraint(equalTo: connectionView.trailingAnchor), + connectionHorizontalLine.heightAnchor.constraint(equalToConstant: TPMenuUX.UX.Line.height), + connectionView.bottomAnchor.constraint(equalTo: connectionHorizontalLine.bottomAnchor), + ] + + constraints.append(contentsOf: connectionConstraints) + } + + // MARK: Toggle View Setup + private func setupToggleView() { + toggleLabelsContainer.addArrangedSubview(toggleLabel) + toggleLabelsContainer.addArrangedSubview(toggleStatusLabel) + toggleView.addSubviews(toggleLabelsContainer, toggleSwitch) + baseView.addSubview(toggleView) + + let toggleConstraints = [ + toggleView.leadingAnchor.constraint(equalTo: baseView.leadingAnchor, + constant: TPMenuUX.UX.horizontalMargin), + toggleView.trailingAnchor.constraint(equalTo: baseView.trailingAnchor, + constant: -TPMenuUX.UX.horizontalMargin), + toggleView.topAnchor.constraint( + equalTo: connectionView.bottomAnchor, + constant: 0 + ), + + toggleLabelsContainer.leadingAnchor.constraint( + equalTo: toggleView.leadingAnchor, + constant: TPMenuUX.UX.horizontalMargin + ), + toggleLabelsContainer.trailingAnchor.constraint( + equalTo: toggleSwitch.leadingAnchor, + constant: -TPMenuUX.UX.horizontalMargin + ), + toggleLabelsContainer.topAnchor.constraint( + equalTo: toggleView.topAnchor, + constant: 11 + ), + toggleLabelsContainer.bottomAnchor.constraint( + equalTo: toggleView.bottomAnchor, + constant: -11 + ), + + toggleSwitch.centerYAnchor.constraint(equalTo: toggleView.centerYAnchor), + toggleSwitch.trailingAnchor.constraint( + equalTo: toggleView.trailingAnchor, + constant: -TPMenuUX.UX.horizontalMargin + ) + ] + + constraints.append(contentsOf: toggleConstraints) + toggleSwitch.actions(forTarget: self, forControlEvent: .valueChanged) + view.bringSubviewToFront(toggleSwitch) + } + + // MARK: Clear Cookies Button Setup + private func setupClearCookiesButton() { + let clearCookiesViewModel = TrackingProtectionButtonModel(title: viewModel.clearCookiesButtonTitle, + a11yIdentifier: viewModel.clearCookiesButtonA11yId) + clearCookiesButton.configure(viewModel: clearCookiesViewModel) + baseView.addSubview(clearCookiesButton) + + let clearCookiesButtonConstraints = [ + clearCookiesButton.leadingAnchor.constraint( + equalTo: baseView.leadingAnchor, + constant: TPMenuUX.UX.horizontalMargin + ), + clearCookiesButton.trailingAnchor.constraint( + equalTo: baseView.trailingAnchor, + constant: -TPMenuUX.UX.horizontalMargin + ), + clearCookiesButton.topAnchor.constraint( + equalTo: toggleView.bottomAnchor, + constant: TPMenuUX.UX.horizontalMargin + ), + clearCookiesButton.bottomAnchor.constraint( + equalTo: settingsLinkButton.topAnchor, + constant: -TPMenuUX.UX.horizontalMargin + ), + ] + constraints.append(contentsOf: clearCookiesButtonConstraints) + } + + // MARK: Settings View Setup + private func setupProtectionSettingsView() { + let settingsButtonViewModel = LinkButtonViewModel(title: viewModel.settingsButtonTitle, + a11yIdentifier: viewModel.settingsA11yId) + settingsLinkButton.configure(viewModel: settingsButtonViewModel) + baseView.addSubviews(settingsLinkButton) + + let protectionConstraints = [ + settingsLinkButton.leadingAnchor.constraint(equalTo: baseView.leadingAnchor), + settingsLinkButton.trailingAnchor.constraint(equalTo: baseView.trailingAnchor), + settingsLinkButton.bottomAnchor.constraint( + equalTo: baseView.bottomAnchor, + constant: -TPMenuUX.UX.settingsLinkButtonBottomSpacing + ), + ] + + constraints.append(contentsOf: protectionConstraints) + } + + private func updateViewDetails() { + favicon.setFavicon(FaviconImageViewModel(siteURLString: viewModel.url.absoluteString, + faviconCornerRadius: TPMenuUX.UX.faviconCornerRadius)) + + siteDomainLabel.text = viewModel.websiteTitle + siteDisplayTitleLabel.text = viewModel.displayTitle + let totalTrackerBlocked = String(viewModel.contentBlockerStats?.total ?? 0) + let trackersText = String(format: .Menu.EnhancedTrackingProtection.trackersBlockedLabel, totalTrackerBlocked) + trackersLabel.text = trackersText + shieldImage.image = UIImage(imageLiteralResourceName: StandardImageIdentifiers.Large.shield) + .withRenderingMode(.alwaysTemplate) + connectionStatusLabel.text = viewModel.connectionStatusString + toggleSwitch.isOn = viewModel.isSiteETPEnabled + toggleLabel.text = .Menu.EnhancedTrackingProtection.switchTitle + toggleStatusLabel.text = toggleSwitch.isOn ? + .Menu.EnhancedTrackingProtection.switchOnText : .Menu.EnhancedTrackingProtection.switchOffText + connectionDetailsTitleLabel.text = viewModel.connectionDetailsTitle + connectionDetailsStatusLabel.text = viewModel.connectionDetailsHeader + foxStatusImage.image = viewModel.connectionDetailsImage + } + + private func setupViewActions() { + closeButton.addTarget(self, action: #selector(closeButtonTapped), for: .touchUpInside) + connectionButton.addTarget(self, action: #selector(connectionDetailsTapped), for: .touchUpInside) + trackersButton.addTarget(self, action: #selector(blockedTrackersTapped), for: .touchUpInside) + toggleSwitch.addTarget(self, action: #selector(trackingProtectionToggleTapped), for: .valueChanged) + } + + // MARK: Notifications + func handleNotifications(_ notification: Notification) { + switch notification.name { + case .DynamicFontChanged: + adjustLayout() + default: break + } + } + + // MARK: View Transitions + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + adjustLayout() + } + + override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { + super.viewWillTransition(to: size, with: coordinator) + coordinator.animate(alongsideTransition: { _ in + self.adjustLayout() + }, completion: nil) + } + + // MARK: Accessibility + private func setupAccessibilityIdentifiers() { + foxStatusImage.accessibilityIdentifier = viewModel.foxImageA11yId + trackersDetailArrow.accessibilityIdentifier = viewModel.arrowImageA11yId + trackersLabel.accessibilityIdentifier = viewModel.trackersBlockedLabelA11yId + connectionDetailArrow.accessibilityIdentifier = viewModel.arrowImageA11yId + shieldImage.accessibilityIdentifier = viewModel.shieldImageA11yId + connectionStatusLabel.accessibilityIdentifier = viewModel.securityStatusLabelA11yId + toggleLabel.accessibilityIdentifier = viewModel.toggleViewTitleLabelA11yId + toggleStatusLabel.accessibilityIdentifier = viewModel.toggleViewBodyLabelA11yId + clearCookiesButton.accessibilityIdentifier = viewModel.clearCookiesButtonA11yId + settingsLinkButton.accessibilityIdentifier = viewModel.settingsA11yId + } + + private func adjustLayout() { + let faviconSize = TPMenuUX.UX.faviconImageSize // to avoid line length warnings + let iconSize = TPMenuUX.UX.iconSize + faviconHeightConstraint?.constant = min(UIFontMetrics.default.scaledValue(for: faviconSize), 2 * faviconSize) + faviconWidthConstraint?.constant = min(UIFontMetrics.default.scaledValue(for: faviconSize), 2 * faviconSize) + + shieldImageHeightConstraint?.constant = min(UIFontMetrics.default.scaledValue(for: iconSize), 2 * iconSize) + trackersArrowHeightConstraint?.constant = min(UIFontMetrics.default.scaledValue(for: iconSize), 2 * iconSize) + + lockImageHeightConstraint?.constant = min(UIFontMetrics.default.scaledValue(for: iconSize), 2 * iconSize) + connectionArrowHeightConstraint?.constant = min(UIFontMetrics.default.scaledValue(for: iconSize), 2 * iconSize) + + view.setNeedsLayout() + view.layoutIfNeeded() + } + + // MARK: - Button actions + @objc + func closeButtonTapped() { + enhancedTrackingProtectionMenuDelegate?.didFinish() + } + + @objc + func connectionDetailsTapped() { + // TODO: FXIOS-9198 #20366 Enhanced Tracking Protection Connection details screen + // let detailsVC = TrackingProtectionDetailsViewController(with: viewModel.getDetailsViewModel(), + // windowUUID: windowUUID) + // detailsVC.modalPresentationStyle = .pageSheet + // self.present(detailsVC, animated: true) + } + + @objc + func blockedTrackersTapped() {} + + @objc + func trackingProtectionToggleTapped() { + // site is safelisted if site ETP is disabled + viewModel.toggleSiteSafelistStatus() + toggleStatusLabel.text = toggleSwitch.isOn ? .ETPOn : .ETPOff + } + + @objc + private func didTapClearCookiesAndSiteData() { + viewModel.onTapClearCookiesAndSiteData(controller: self) + } + + @objc + func protectionSettingsTapped() { + enhancedTrackingProtectionMenuDelegate?.settingsOpenPage(settings: .contentBlocker) + } + + // MARK: - Gesture Recognizer + private func addGestureRecognizer() { + let panGesture = UIPanGestureRecognizer(target: self, action: #selector(panGestureRecognizerAction)) + view.addGestureRecognizer(panGesture) + } + + @objc + func panGestureRecognizerAction(sender: UIPanGestureRecognizer) { + let translation = sender.translation(in: view) + let originalYPosition = self.view.frame.origin.y + let originalXPosition = self.view.frame.origin.x + + // Not allowing the user to drag the view upward + guard translation.y >= 0 else { return } + + // Setting x based on window calculation because we don't want + // users to move the frame side ways, only straight up or down + view.frame.origin = CGPoint(x: originalXPosition, + y: self.pointOrigin!.y + translation.y) + + if sender.state == .ended { + let dragVelocity = sender.velocity(in: view) + if dragVelocity.y >= 1300 { + enhancedTrackingProtectionMenuDelegate?.didFinish() + } else { + // Set back to original position of the view controller + UIView.animate(withDuration: 0.3) { + self.view.frame.origin = self.pointOrigin ?? CGPoint(x: originalXPosition, y: originalYPosition) + } + } + } + } + + private func currentTheme() -> Theme { + return themeManager.getCurrentTheme(for: windowUUID) + } + + func willDismiss() { + } +} + +// MARK: - Themable +extension TrackingProtectionViewController { + func applyTheme() { + let theme = currentTheme() + overrideUserInterfaceStyle = theme.type.getInterfaceStyle() + view.backgroundColor = theme.colors.layer1 + closeButton.backgroundColor = theme.colors.layer2 + let buttonImage = UIImage(named: StandardImageIdentifiers.Medium.cross)? + .tinted(withColor: theme.colors.iconSecondary) + closeButton.setImage(buttonImage, for: .normal) + connectionDetailsHeaderView.backgroundColor = theme.colors.layer2 + connectionDetailsContentView.backgroundColor = theme.colors.layerAccentPrivateNonOpaque + trackersView.backgroundColor = theme.colors.layer2 + trackersDetailArrow.tintColor = theme.colors.iconSecondary + shieldImage.tintColor = theme.colors.iconPrimary + connectionView.backgroundColor = theme.colors.layer2 + connectionDetailArrow.tintColor = theme.colors.iconSecondary + connectionStatusImage.image = viewModel.getConnectionStatusImage(themeType: theme.type) + headerContainer.tintColor = theme.colors.layer2 + siteDomainLabel.textColor = theme.colors.textSecondary + siteDisplayTitleLabel.textColor = theme.colors.textPrimary + if viewModel.connectionSecure { + connectionStatusImage.tintColor = theme.colors.iconPrimary + } + toggleView.backgroundColor = theme.colors.layer2 + toggleSwitch.tintColor = theme.colors.actionPrimary + toggleSwitch.onTintColor = theme.colors.actionPrimary + toggleStatusLabel.textColor = theme.colors.textSecondary + + trackersHorizontalLine.backgroundColor = theme.colors.borderPrimary + connectionHorizontalLine.backgroundColor = theme.colors.borderPrimary + + clearCookiesButton.applyTheme(theme: theme) + clearCookiesButton.layer.borderColor = theme.colors.borderPrimary.cgColor + settingsLinkButton.applyTheme(theme: theme) + setNeedsStatusBarAppearanceUpdate() + } +} diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Coordinators/BrowserCoordinatorTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Coordinators/BrowserCoordinatorTests.swift index c7a39122693b..fcc02a3d046f 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Coordinators/BrowserCoordinatorTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Coordinators/BrowserCoordinatorTests.swift @@ -10,7 +10,7 @@ import XCTest @testable import Client -final class BrowserCoordinatorTests: XCTestCase { +final class BrowserCoordinatorTests: XCTestCase, FeatureFlaggable { private var mockRouter: MockRouter! private var profile: MockProfile! private var overlayModeManager: MockOverlayModeManager! @@ -200,7 +200,12 @@ final class BrowserCoordinatorTests: XCTestCase { XCTAssertEqual(subject.childCoordinators.count, 1) XCTAssertNotNil(subject.childCoordinators[0] as? EnhancedTrackingProtectionCoordinator) XCTAssertEqual(mockRouter.presentCalled, 1) - XCTAssertTrue(mockRouter.presentedViewController is EnhancedTrackingProtectionMenuVC) + + if featureFlags.isFeatureEnabled(.trackingProtectionRefactor, checking: .buildOnly) { + XCTAssertTrue(mockRouter.presentedViewController is TrackingProtectionViewController) + } else { + XCTAssertTrue(mockRouter.presentedViewController is EnhancedTrackingProtectionMenuVC) + } } func testShowShareExtension_addsShareExtensionCoordinator() { diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/TrackingProtectionTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/TrackingProtectionTests.swift index fab6baf65927..cc21e8bf1162 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/TrackingProtectionTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/TrackingProtectionTests.swift @@ -92,7 +92,7 @@ class TrackingProtectionTests: BaseTestCase { } navigator.nowAt(BrowserTab) navigator.goto(TrackingProtectionContextMenuDetails) - mozWaitForElementToExist(app.staticTexts["Connection is not secure"]) + mozWaitForElementToExist(app.staticTexts["Connection not secure"], timeout: 5) var switchValue = app.switches.firstMatch.value! // Need to make sure first the setting was not turned off previously if switchValue as! String == "0" { @@ -106,8 +106,8 @@ class TrackingProtectionTests: BaseTestCase { XCTAssertEqual(switchValueOFF as! String, "0") // Open TP Settings menu - app.buttons["Protection Settings"].tap() - mozWaitForElementToExist(app.navigationBars["Tracking Protection"]) + app.buttons["Privacy settings"].tap() + mozWaitForElementToExist(app.navigationBars["Tracking Protection"], timeout: 5) let switchSettingsValue = app.switches["prefkey.trackingprotection.normalbrowsing"].value! XCTAssertEqual(switchSettingsValue as! String, "1") app.switches["prefkey.trackingprotection.normalbrowsing"].tap() @@ -116,8 +116,10 @@ class TrackingProtectionTests: BaseTestCase { app.buttons["Done"].tap() navigator.nowAt(BrowserTab) navigator.goto(TrackingProtectionContextMenuDetails) - mozWaitForElementToExist(app.staticTexts["Connection is not secure"]) - mozWaitForElementToNotExist(app.switches.element) + mozWaitForElementToExist(app.staticTexts["Connection not secure"], timeout: 5) + // This is a workaround in order to pass the tests for the newest Tracking Protection UI + // it may be changed back to "false", after the Tracking Protection UI implementation is done + XCTAssertTrue(app.switches.element.exists) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2318742 From 69a8ea1218d30113a821b53de44be4fd64791c71 Mon Sep 17 00:00:00 2001 From: dragosb01 <134391433+dragosb01@users.noreply.github.com> Date: Thu, 1 Aug 2024 15:57:36 +0300 Subject: [PATCH 025/128] Fix MTE-3248 - TopTabsTestIphone smoke tests (#21387) --- .../firefox-ios-tests/Tests/XCUITests/TopTabsTest.swift | 6 ------ 1 file changed, 6 deletions(-) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/TopTabsTest.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/TopTabsTest.swift index 89e81bc404d5..df0a63c6be79 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/TopTabsTest.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/TopTabsTest.swift @@ -493,12 +493,6 @@ fileprivate extension BaseTestCase { } class TopTabsTestIphone: IphoneOnlyTestCase { - override func setUp() { - super.setUp() - waitForTabsButton() - mozWaitForElementToExist(app.textFields["url"]) - } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2355535 // Smoketest func testCloseTabFromLongPressTabsButton() { From 5b68d57cf4ba98be6e4a95ccea8f58b7bd3c030c Mon Sep 17 00:00:00 2001 From: Clare So <1740517+clarmso@users.noreply.github.com> Date: Thu, 1 Aug 2024 11:47:22 -0400 Subject: [PATCH 026/128] Bugfix MTE-3146 Remove override for setUp() --- .../firefox-ios-tests/Tests/XCUITests/BaseTestCase.swift | 4 ---- .../firefox-ios-tests/Tests/XCUITests/JumpBackInTests.swift | 2 -- .../firefox-ios-tests/Tests/XCUITests/NewTabSettings.swift | 6 ------ .../Tests/XCUITests/OpeningScreenTests.swift | 6 ------ .../Tests/XCUITests/PrivateBrowsingTest.swift | 6 ------ .../firefox-ios-tests/Tests/XCUITests/TabCounterTests.swift | 6 ------ .../firefox-ios-tests/Tests/XCUITests/TopTabsTest.swift | 6 ------ 7 files changed, 36 deletions(-) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/BaseTestCase.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/BaseTestCase.swift index 13d36abd3120..f16e2a470be5 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/BaseTestCase.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/BaseTestCase.swift @@ -408,8 +408,6 @@ class IpadOnlyTestCase: BaseTestCase { specificForPlatform = .pad if iPad() { super.setUp() - waitForTabsButton() - mozWaitForElementToExist(app.textFields["url"]) } } } @@ -419,8 +417,6 @@ class IphoneOnlyTestCase: BaseTestCase { specificForPlatform = .phone if !iPad() { super.setUp() - waitForTabsButton() - mozWaitForElementToExist(app.textFields["url"]) } } } diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/JumpBackInTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/JumpBackInTests.swift index cf4925ed6eb1..36c3cdaf283f 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/JumpBackInTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/JumpBackInTests.swift @@ -30,8 +30,6 @@ class JumpBackInTests: BaseTestCase { XCTAssertEqual(app.switches["Jump Back In"].value as! String, "1") navigator.goto(NewTabScreen) - waitForTabsButton() - mozWaitForElementToExist(app.textFields["url"]) } // https://testrail.stage.mozaws.net/index.php?/cases/view/2306922 diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/NewTabSettings.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/NewTabSettings.swift index 0861a512cd8d..39e9ce60de4f 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/NewTabSettings.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/NewTabSettings.swift @@ -6,12 +6,6 @@ import XCTest let websiteUrl = "www.mozilla.org" class NewTabSettingsTest: BaseTestCase { - override func setUp() { - super.setUp() - waitForTabsButton() - mozWaitForElementToExist(app.textFields["url"]) - } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307026 // Smoketest func testCheckNewTabSettingsByDefault() { diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/OpeningScreenTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/OpeningScreenTests.swift index 0685b0d49317..e8601be815be 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/OpeningScreenTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/OpeningScreenTests.swift @@ -4,12 +4,6 @@ import Foundation class OpeningScreenTests: BaseTestCase { - override func setUp() { - super.setUp() - waitForTabsButton() - mozWaitForElementToExist(app.textFields["url"]) - } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307039 func testLastOpenedTab() { // Open a web page diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/PrivateBrowsingTest.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/PrivateBrowsingTest.swift index f66e6c59c363..19af4e4999aa 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/PrivateBrowsingTest.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/PrivateBrowsingTest.swift @@ -313,12 +313,6 @@ class PrivateBrowsingTestIphone: IphoneOnlyTestCase { class PrivateBrowsingTestIpad: IpadOnlyTestCase { typealias HistoryPanelA11y = AccessibilityIdentifiers.LibraryPanels.HistoryPanel - override func setUp() { - super.setUp() - waitForTabsButton() - mozWaitForElementToExist(app.textFields["url"]) - } - // This test is only enabled for iPad. Shortcut does not exists on iPhone // https://testrail.stage.mozaws.net/index.php?/cases/view/2307008 func testClosePrivateTabsOptionClosesPrivateTabsShortCutiPad() { diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/TabCounterTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/TabCounterTests.swift index 8c1640ec4c3f..d5f878208e46 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/TabCounterTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/TabCounterTests.swift @@ -6,12 +6,6 @@ import Common import XCTest class TabCounterTests: BaseTestCase { - override func setUp() { - super.setUp() - waitForTabsButton() - mozWaitForElementToExist(app.textFields["url"]) - } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2359077 func testTabIncrement() throws { navigator.nowAt(NewTabScreen) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/TopTabsTest.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/TopTabsTest.swift index df0a63c6be79..cfb23c6ec195 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/TopTabsTest.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/TopTabsTest.swift @@ -603,12 +603,6 @@ class TopTabsTestIphone: IphoneOnlyTestCase { // Tests to check if Tab Counter is updating correctly after opening three tabs by tapping on '+' button // and closing the tabs by tapping 'x' button class TopTabsTestIpad: IpadOnlyTestCase { - override func setUp() { - super.setUp() - waitForTabsButton() - mozWaitForElementToExist(app.textFields["url"]) - } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307023 func testUpdateTabCounter() { if skipPlatform { return } From dd3febaabdbb37fe8453a565d565f2d4c61ae386 Mon Sep 17 00:00:00 2001 From: mattreaganmozilla <145381717+mattreaganmozilla@users.noreply.github.com> Date: Thu, 1 Aug 2024 12:32:13 -0700 Subject: [PATCH 027/128] Bugfix FXIOS-9736 Fix data sync crash in v129 #21409 --- .../Client/TabManagement/TabManagerImplementation.swift | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/firefox-ios/Client/TabManagement/TabManagerImplementation.swift b/firefox-ios/Client/TabManagement/TabManagerImplementation.swift index 7340243d0b3d..a7d98491966b 100644 --- a/firefox-ios/Client/TabManagement/TabManagerImplementation.swift +++ b/firefox-ios/Client/TabManagement/TabManagerImplementation.swift @@ -414,7 +414,10 @@ class TabManagerImplementation: LegacyTabManager, Notifiable, WindowSimpleTabsPr if selectedTab?.isPrivate ?? false { _selectedIndex = -1 } - privateTabs.forEach { $0.close() } + privateTabs.forEach { tab in + tab.close() + delegates.forEach { $0.get()?.tabManager(self, didRemoveTab: tab, isRestoring: false) } + } tabs = normalTabs privateConfiguration = LegacyTabManager.makeWebViewConfig(isPrivate: true, prefs: profile.prefs) From e55802bbd19211e9125dab6e4ae399ab9e3fc883 Mon Sep 17 00:00:00 2001 From: Lina Butler Date: Thu, 1 Aug 2024 13:07:50 -0700 Subject: [PATCH 028/128] Build - Run bin/nimbus-fml.sh with a clean environment (#21385) Run Script build phases inherit all Xcode build settings as environment variables, including the compiler, linker, and flags, for the target architecture. This means that, e.g., when building Firefox or Focus for an iOS device, Xcode will set build environment variables for the iOS target; when building Firefox for the Simulator, Xcode will set build variables for the Simulator target; etc. Unfortunately, this is the wrong thing to do when invoking the `nimbus-fml` script with `MOZ_APPSERVICES_LOCAL` set. In that case, the script will invoke `cargo run`, which will see the Xcode-set build variables, and try to cross-compile and run the local `nimbus-fml` for the target architecture (iOS, Simulator, etc.). Put another way, Cargo is trying (and failing) to build and run an iOS binary on a Mac. This commit fixes `bin/nimbus-fml.sh` to always run with a clean environment, except for the variables that it needs. --- firefox-ios/Client.xcodeproj/project.pbxproj | 2 +- focus-ios/Blockzilla.xcodeproj/project.pbxproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/firefox-ios/Client.xcodeproj/project.pbxproj b/firefox-ios/Client.xcodeproj/project.pbxproj index b95e775f0bad..b4c216a3bf98 100644 --- a/firefox-ios/Client.xcodeproj/project.pbxproj +++ b/firefox-ios/Client.xcodeproj/project.pbxproj @@ -14108,7 +14108,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if [ $ACTION != \"indexbuild\" ]; then\n bash $SOURCE_ROOT/bin/nimbus-fml.sh --verbose\nfi\n"; + shellScript = "if [ $ACTION != \"indexbuild\" ]; then\n /usr/bin/env -i HOME=$HOME PROJECT=$PROJECT CONFIGURATION=$CONFIGURATION SOURCE_ROOT=$SOURCE_ROOT bash $SOURCE_ROOT/bin/nimbus-fml.sh --verbose\nfi\n"; }; C874A4E327F62C5B006F54E5 /* Swiftlint */ = { isa = PBXShellScriptBuildPhase; diff --git a/focus-ios/Blockzilla.xcodeproj/project.pbxproj b/focus-ios/Blockzilla.xcodeproj/project.pbxproj index 7ca0abc7068f..8df41435c417 100644 --- a/focus-ios/Blockzilla.xcodeproj/project.pbxproj +++ b/focus-ios/Blockzilla.xcodeproj/project.pbxproj @@ -2461,7 +2461,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if [ $ACTION != \"indexbuild\" ]; then\n bash $SOURCE_ROOT/bin/nimbus-fml.sh --verbose\nfi\n"; + shellScript = "if [ $ACTION != \"indexbuild\" ]; then\n /usr/bin/env -i HOME=$HOME PROJECT=$PROJECT CONFIGURATION=$CONFIGURATION SOURCE_ROOT=$SOURCE_ROOT bash $SOURCE_ROOT/bin/nimbus-fml.sh --verbose\nfi\n"; }; D48C953D27FF411800FF8AEF /* Run Swiftlint */ = { isa = PBXShellScriptBuildPhase; From 6d16a019812b5ad7263c89e35d16bb160c73c012 Mon Sep 17 00:00:00 2001 From: Cyndi Chin Date: Thu, 1 Aug 2024 16:20:00 -0400 Subject: [PATCH 029/128] Bugfix FXIOS-9729 [Microsurvey] Fix VoiceOver focus order (#21382) * Bugfix FXIOS-9729 [Microsurvey] Fix VoiceOver focus order * update ordering for confirmation page --- .../Microsurvey/Survey/View/MicrosurveyViewController.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/firefox-ios/Client/Frontend/Microsurvey/Survey/View/MicrosurveyViewController.swift b/firefox-ios/Client/Frontend/Microsurvey/Survey/View/MicrosurveyViewController.swift index 6f72f455f7d0..805d59e694af 100644 --- a/firefox-ios/Client/Frontend/Microsurvey/Survey/View/MicrosurveyViewController.swift +++ b/firefox-ios/Client/Frontend/Microsurvey/Survey/View/MicrosurveyViewController.swift @@ -223,6 +223,7 @@ final class MicrosurveyViewController: UIViewController, scrollContainer.addArrangedSubview(containerView) scrollContainer.addArrangedSubview(submitButton) scrollContainer.addArrangedSubview(privacyPolicyButton) + scrollContainer.accessibilityElements = [containerView, submitButton, privacyPolicyButton] scrollView.addSubview(scrollContainer) @@ -331,6 +332,7 @@ final class MicrosurveyViewController: UIViewController, tableView.removeFromSuperview() submitButton.removeFromSuperview() containerView.addSubview(confirmationView) + scrollContainer.accessibilityElements = [containerView, privacyPolicyButton] NSLayoutConstraint.activate( [ confirmationView.topAnchor.constraint(equalTo: containerView.topAnchor), From 2106cf26febb12d5e16ae367ec73a92a16da26aa Mon Sep 17 00:00:00 2001 From: "roux g. buciu" <11182210+adudenamedruby@users.noreply.github.com> Date: Thu, 1 Aug 2024 16:30:29 -0400 Subject: [PATCH 030/128] Bugfix FXIOS-9717 - Add missing Learn More url to Redux action (#21410) --- .../Client/Frontend/Browser/Tabs/Views/TabDisplayPanel.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/firefox-ios/Client/Frontend/Browser/Tabs/Views/TabDisplayPanel.swift b/firefox-ios/Client/Frontend/Browser/Tabs/Views/TabDisplayPanel.swift index baa0caeef274..f9dba00db908 100644 --- a/firefox-ios/Client/Frontend/Browser/Tabs/Views/TabDisplayPanel.swift +++ b/firefox-ios/Client/Frontend/Browser/Tabs/Views/TabDisplayPanel.swift @@ -206,6 +206,7 @@ class TabDisplayPanel: UIViewController, func didTapLearnMore(urlRequest: URLRequest) { let action = TabPanelViewAction(panelType: panelType, + urlRequest: urlRequest, windowUUID: windowUUID, actionType: TabPanelViewActionType.learnMorePrivateMode) store.dispatch(action) From dadbf5b247470f57f64e0ab4590cd7f7c9c4f273 Mon Sep 17 00:00:00 2001 From: Matt Lichtenstein Date: Thu, 1 Aug 2024 16:32:50 -0400 Subject: [PATCH 031/128] Add FXIOS-9712 Data clearance button for toolbar refactor (#21383) --- .../Actions/GeneralBrowserAction.swift | 1 + ...serViewController+TabToolbarDelegate.swift | 6 +++- .../State/BrowserViewControllerState.swift | 10 ++++++ .../Views/BrowserViewController.swift | 2 ++ .../Toolbars/Redux/ToolbarMiddleware.swift | 33 ++++++++++++++++--- .../Toolbar+URLBar/TabToolbarHelper.swift | 4 +-- .../BrowserViewControllerStateTests.swift | 12 +++++++ 7 files changed, 61 insertions(+), 7 deletions(-) diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Actions/GeneralBrowserAction.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Actions/GeneralBrowserAction.swift index 9530fc61d543..60289d13c1b6 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Actions/GeneralBrowserAction.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Actions/GeneralBrowserAction.swift @@ -50,6 +50,7 @@ enum GeneralBrowserActionType: ActionType { case showShare case addNewTab case showNewTabLongPressActions + case clearData } class GeneralBrowserMiddlewareAction: Action { diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+TabToolbarDelegate.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+TabToolbarDelegate.swift index f787f544f10e..9b1d8ce717f0 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+TabToolbarDelegate.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+TabToolbarDelegate.swift @@ -42,7 +42,11 @@ extension BrowserViewController: TabToolbarDelegate, PhotonActionSheetProtocol { } // Presents alert to clear users private session data - func tabToolbarDidPressFire(_ tabToolbar: TabToolbarProtocol, button: UIButton) { + func tabToolbarDidPressDataClearance(_ tabToolbar: TabToolbarProtocol, button: UIButton) { + didTapOnDataClearance() + } + + func didTapOnDataClearance() { let alert = UIAlertController( title: .Alerts.FeltDeletion.Title, message: .Alerts.FeltDeletion.Body, diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/State/BrowserViewControllerState.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/State/BrowserViewControllerState.swift index cab6d5d7c81f..7f777009543f 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/State/BrowserViewControllerState.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/State/BrowserViewControllerState.swift @@ -28,6 +28,7 @@ struct BrowserViewControllerState: ScreenState, Equatable { case tabTray case share case newTabLongPressActions + case dataClearance } let windowUUID: WindowUUID @@ -374,6 +375,15 @@ struct BrowserViewControllerState: ScreenState, Equatable { browserViewType: state.browserViewType, displayView: .newTabLongPressActions, microsurveyState: MicrosurveyPromptState.reducer(state.microsurveyState, action)) + case GeneralBrowserActionType.clearData: + return BrowserViewControllerState( + searchScreenState: state.searchScreenState, + showDataClearanceFlow: state.showDataClearanceFlow, + fakespotState: state.fakespotState, + windowUUID: state.windowUUID, + browserViewType: state.browserViewType, + displayView: .dataClearance, + microsurveyState: MicrosurveyPromptState.reducer(state.microsurveyState, action)) default: return state } diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift index f3fd68e5f1a7..c22dcbd1fb3a 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift @@ -1926,6 +1926,8 @@ class BrowserViewController: UIViewController, didTapOnShare(from: button) case .newTabLongPressActions: presentNewTabLongPressActionSheet(from: view) + case .dataClearance: + didTapOnDataClearance() } } diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift index d5397c6731e2..9a53aa73dc35 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift @@ -85,6 +85,13 @@ class ToolbarMiddleware: FeatureFlaggable { a11yLabel: .TabToolbarSearchAccessibilityLabel, a11yId: AccessibilityIdentifiers.Toolbar.searchButton) + lazy var dataClearanceAction = ToolbarActionState( + actionType: .dataClearance, + iconName: StandardImageIdentifiers.Large.dataClearance, + isEnabled: true, + a11yLabel: .TabToolbarDataClearanceAccessibilityLabel, + a11yId: AccessibilityIdentifiers.Toolbar.fireButton) + private func resolveGeneralBrowserMiddlewareActions(action: GeneralBrowserMiddlewareAction, state: AppState) { let uuid = action.windowUUID @@ -247,6 +254,10 @@ class ToolbarMiddleware: FeatureFlaggable { TelemetryWrapper.recordEvent(category: .action, method: .tap, object: .startSearchButton) updateAddressToolbarNavigationActions(action: action, state: state, isEditing: true) + case .dataClearance: + let action = GeneralBrowserAction(windowUUID: action.windowUUID, + actionType: GeneralBrowserActionType.clearData) + store.dispatch(action) default: break } @@ -574,10 +585,7 @@ class ToolbarMiddleware: FeatureFlaggable { let isUrlChangeAction = action.actionType as? ToolbarMiddlewareActionType == .urlDidChange let url = isUrlChangeAction ? action.url : toolbarState.addressToolbar.url - let isNewTabEnabled = featureFlags.isFeatureEnabled(.toolbarOneTapNewTab, checking: .buildOnly) - let middleActionDefault = isNewTabEnabled ? newTabAction : homeAction - let middleActionHome = searchAction - let middleAction = url == nil ? middleActionHome : middleActionDefault + let middleAction = getMiddleButtonAction(url: url, isPrivateMode: toolbarState.isPrivateMode) let isShowingTopTabs = action.isShowingTopTabs ?? false @@ -604,6 +612,23 @@ class ToolbarMiddleware: FeatureFlaggable { return navToolbarModel } + private func getMiddleButtonAction(url: URL?, isPrivateMode: Bool) -> ToolbarActionState { + let isFeltPrivacyUIEnabled = featureFlags.isFeatureEnabled(.feltPrivacySimplifiedUI, checking: .buildOnly) + let isFeltPrivacyDeletionEnabled = featureFlags.isFeatureEnabled(.feltPrivacyFeltDeletion, checking: .buildOnly) + let shouldShowDataClearanceAction = isPrivateMode && isFeltPrivacyUIEnabled && + isFeltPrivacyDeletionEnabled + guard !shouldShowDataClearanceAction else { + return dataClearanceAction + } + + let isNewTabEnabled = featureFlags.isFeatureEnabled(.toolbarOneTapNewTab, checking: .buildOnly) + let middleActionDefault = isNewTabEnabled ? newTabAction : homeAction + let middleActionHome = searchAction + let middleAction = url == nil ? middleActionHome : middleActionDefault + + return middleAction + } + // MARK: - Helper private func backAction(enabled: Bool) -> ToolbarActionState { diff --git a/firefox-ios/Client/Frontend/Toolbar+URLBar/TabToolbarHelper.swift b/firefox-ios/Client/Frontend/Toolbar+URLBar/TabToolbarHelper.swift index 77bfd5b5cea0..d97023bc7f3d 100644 --- a/firefox-ios/Client/Frontend/Toolbar+URLBar/TabToolbarHelper.swift +++ b/firefox-ios/Client/Frontend/Toolbar+URLBar/TabToolbarHelper.swift @@ -35,7 +35,7 @@ protocol TabToolbarDelegate: AnyObject { func tabToolbarDidLongPressBack(_ tabToolbar: TabToolbarProtocol, button: UIButton) func tabToolbarDidLongPressForward(_ tabToolbar: TabToolbarProtocol, button: UIButton) func tabToolbarDidPressHome(_ tabToolbar: TabToolbarProtocol, button: UIButton) - func tabToolbarDidPressFire(_ tabToolbar: TabToolbarProtocol, button: UIButton) + func tabToolbarDidPressDataClearance(_ tabToolbar: TabToolbarProtocol, button: UIButton) func tabToolbarDidPressMenu(_ tabToolbar: TabToolbarProtocol, button: UIButton) func tabToolbarDidPressBookmarks(_ tabToolbar: TabToolbarProtocol, button: UIButton) func tabToolbarDidPressTabs(_ tabToolbar: TabToolbarProtocol, button: UIButton) @@ -246,7 +246,7 @@ open class TabToolbarHelper: NSObject { TelemetryWrapper.recordEvent(category: .action, method: .tap, object: .startSearchButton) toolbar.tabToolbarDelegate?.tabToolbarDidPressSearch(toolbar, button: toolbar.multiStateButton) case .fire: - toolbar.tabToolbarDelegate?.tabToolbarDidPressFire(toolbar, button: toolbar.multiStateButton) + toolbar.tabToolbarDelegate?.tabToolbarDidPressDataClearance(toolbar, button: toolbar.multiStateButton) } } } diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/BrowserViewControllerStateTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/BrowserViewControllerStateTests.swift index 7c769273288c..cc19dec30224 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/BrowserViewControllerStateTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/BrowserViewControllerStateTests.swift @@ -42,6 +42,18 @@ final class BrowserViewControllerStateTests: XCTestCase { XCTAssertEqual(newState.displayView, .newTabLongPressActions) } + func testClearDataAction() { + let initialState = createSubject() + let reducer = browserViewControllerReducer() + + XCTAssertNil(initialState.displayView) + + let action = getAction(for: .clearData) + let newState = reducer(initialState, action) + + XCTAssertEqual(newState.displayView, .dataClearance) + } + // MARK: - Private private func createSubject() -> BrowserViewControllerState { return BrowserViewControllerState(windowUUID: .XCTestDefaultUUID) From 07e1c4f12e947e7ad459afa9e8205b0e9b62528d Mon Sep 17 00:00:00 2001 From: dragosb01 <134391433+dragosb01@users.noreply.github.com> Date: Fri, 2 Aug 2024 10:02:48 +0300 Subject: [PATCH 032/128] Fix MTE-3249 - testLockIconSecureConnection test (#21424) --- .../Tests/XCUITests/TrackingProtectionTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/TrackingProtectionTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/TrackingProtectionTests.swift index cc21e8bf1162..3bb3ec0c91af 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/TrackingProtectionTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/TrackingProtectionTests.swift @@ -160,7 +160,7 @@ class TrackingProtectionTests: BaseTestCase { navigator.goto(TrackingProtectionContextMenuDetails) // A page displaying the connection is secure mozWaitForElementToExist(app.staticTexts["mozilla.org"]) - mozWaitForElementToExist(app.staticTexts["Connection is secure"]) + mozWaitForElementToExist(app.staticTexts["Secure connection"]) XCTAssertEqual( app.buttons[AccessibilityIdentifiers.Toolbar.trackingProtection].label, "Secure connection" From 744723846290f6ab76f0c6aec9e6ca6a1747610d Mon Sep 17 00:00:00 2001 From: Clare So <1740517+clarmso@users.noreply.github.com> Date: Fri, 2 Aug 2024 03:03:19 -0400 Subject: [PATCH 033/128] Bugfix MTE-3146 ReportSiteTests can be launched (#21407) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix ReportSiteTests * 🈳 Empty commit --- .../firefox-ios-tests/Tests/XCUITests/BaseTestCase.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/BaseTestCase.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/BaseTestCase.swift index f16e2a470be5..1ae4465013ca 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/BaseTestCase.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/BaseTestCase.swift @@ -86,6 +86,7 @@ class BaseTestCase: XCTestCase { app.activate() } app.launch() + mozWaitForElementToExist(app.windows.otherElements.firstMatch) } func setUpLaunchArguments() { @@ -101,8 +102,6 @@ class BaseTestCase: XCTestCase { continueAfterFailure = false setUpApp() setUpScreenGraph() - - mozWaitForElementToExist(app.windows.otherElements.firstMatch) } override func tearDown() { From f7c1d948cf417c275d3b9d7ad31348bb68357754 Mon Sep 17 00:00:00 2001 From: PARAIPAN SORIN <51127880+PARAIPAN9@users.noreply.github.com> Date: Fri, 2 Aug 2024 14:57:52 +0300 Subject: [PATCH 034/128] Add FXIOS-9522 - Fix color of menu badge (#21390) * Add mask icon and fix color of badge icon * Replace tuple with lets * Update init --- .../Sources/ToolbarKit/ToolbarButton.swift | 49 +++++++++++++------ .../Sources/ToolbarKit/ToolbarElement.swift | 6 +++ .../Views/BrowserViewController.swift | 3 ++ .../Models/AddressToolbarContainerModel.swift | 1 + .../NavigationToolbarContainerModel.swift | 1 + .../Toolbars/Redux/ToolbarAction.swift | 8 ++- .../Toolbars/Redux/ToolbarActionState.swift | 1 + .../Toolbars/Redux/ToolbarMiddleware.swift | 14 ++++-- .../Browser/Toolbars/Redux/ToolbarState.swift | 33 ++++++++----- .../AddressToolbarContainerModelTests.swift | 3 +- 10 files changed, 85 insertions(+), 34 deletions(-) diff --git a/BrowserKit/Sources/ToolbarKit/ToolbarButton.swift b/BrowserKit/Sources/ToolbarKit/ToolbarButton.swift index 9296b0dbff3e..99c92d98eacb 100644 --- a/BrowserKit/Sources/ToolbarKit/ToolbarButton.swift +++ b/BrowserKit/Sources/ToolbarKit/ToolbarButton.swift @@ -14,8 +14,6 @@ class ToolbarButton: UIButton, ThemeApplicable { private struct UX { static let verticalInset: CGFloat = 10 static let horizontalInset: CGFloat = 10 - static let badgeImageViewBorderWidth: CGFloat = 1 - static let badgeImageViewCornerRadius: CGFloat = 10 static let badgeIconSize = CGSize(width: 20, height: 20) } @@ -25,8 +23,9 @@ class ToolbarButton: UIButton, ThemeApplicable { private(set) var backgroundColorNormal: UIColor = .clear private var badgeImageView: UIImageView? - private var shouldDisplayAsHighlighted = false + private var maskImageView: UIImageView? + private var shouldDisplayAsHighlighted = false private var onLongPress: ((UIButton) -> Void)? override init(frame: CGRect) { @@ -68,6 +67,9 @@ class ToolbarButton: UIButton, ThemeApplicable { configuration = config if let badgeName = element.badgeImageName { addBadgeIcon(imageName: badgeName) + if let maskImageName = element.maskImageName { + addMaskIcon(maskImageName: maskImageName) + } } layoutIfNeeded() } @@ -99,18 +101,28 @@ class ToolbarButton: UIButton, ThemeApplicable { private func addBadgeIcon(imageName: String) { badgeImageView = UIImageView(image: UIImage(named: imageName)) guard let badgeImageView, configuration?.image != nil else { return } - - badgeImageView.layer.borderWidth = UX.badgeImageViewBorderWidth - badgeImageView.layer.cornerRadius = UX.badgeImageViewCornerRadius - badgeImageView.clipsToBounds = true badgeImageView.translatesAutoresizingMaskIntoConstraints = false imageView?.addSubview(badgeImageView) + applyBadgeConstraints(to: badgeImageView) + } + + private func addMaskIcon(maskImageName: String) { + maskImageView = UIImageView(image: UIImage(named: maskImageName)) + guard let maskImageView, let badgeImageView else { return } + maskImageView.translatesAutoresizingMaskIntoConstraints = false + + maskImageView.addSubview(badgeImageView) + imageView?.addSubview(maskImageView) + applyBadgeConstraints(to: maskImageView) + } + + private func applyBadgeConstraints(to imageView: UIImageView) { NSLayoutConstraint.activate([ - badgeImageView.widthAnchor.constraint(equalToConstant: UX.badgeIconSize.width), - badgeImageView.heightAnchor.constraint(equalToConstant: UX.badgeIconSize.height), - badgeImageView.leadingAnchor.constraint(equalTo: centerXAnchor), - badgeImageView.bottomAnchor.constraint(equalTo: centerYAnchor) + imageView.widthAnchor.constraint(equalToConstant: UX.badgeIconSize.width), + imageView.heightAnchor.constraint(equalToConstant: UX.badgeIconSize.height), + imageView.leadingAnchor.constraint(equalTo: centerXAnchor), + imageView.bottomAnchor.constraint(equalTo: centerYAnchor) ]) } @@ -148,12 +160,17 @@ class ToolbarButton: UIButton, ThemeApplicable { // MARK: - ThemeApplicable public func applyTheme(theme: Theme) { - foregroundColorNormal = theme.colors.iconPrimary - foregroundColorHighlighted = theme.colors.actionPrimary - foregroundColorDisabled = theme.colors.iconDisabled - badgeImageView?.layer.borderColor = theme.colors.layer1.cgColor - badgeImageView?.backgroundColor = theme.colors.layer1 + let colors = theme.colors + foregroundColorNormal = colors.iconPrimary + foregroundColorHighlighted = colors.actionPrimary + foregroundColorDisabled = colors.iconDisabled backgroundColorNormal = .clear + + badgeImageView?.layer.borderColor = colors.layer1.cgColor + badgeImageView?.backgroundColor = maskImageView == nil ? colors.layer1 : .clear + badgeImageView?.tintColor = maskImageView == nil ? .clear : colors.actionInfo + maskImageView?.tintColor = colors.layer1 + setNeedsUpdateConfiguration() } } diff --git a/BrowserKit/Sources/ToolbarKit/ToolbarElement.swift b/BrowserKit/Sources/ToolbarKit/ToolbarElement.swift index 4eb942705249..f83e8f71494f 100644 --- a/BrowserKit/Sources/ToolbarKit/ToolbarElement.swift +++ b/BrowserKit/Sources/ToolbarKit/ToolbarElement.swift @@ -11,6 +11,9 @@ public struct ToolbarElement: Equatable { /// Badge name of the toolbar element let badgeImageName: String? + /// Mask name of the badge's toolbar element + let maskImageName: String? + /// Number of open tabs let numberOfTabs: Int? @@ -42,6 +45,7 @@ public struct ToolbarElement: Equatable { // can therefor not be used outside of the ToolbarKit public init(iconName: String, badgeImageName: String? = nil, + maskImageName: String? = nil, numberOfTabs: Int? = nil, isEnabled: Bool, isFlippedForRTL: Bool = false, @@ -53,6 +57,7 @@ public struct ToolbarElement: Equatable { onLongPress: ((UIButton) -> Void)? = nil) { self.iconName = iconName self.badgeImageName = badgeImageName + self.maskImageName = maskImageName self.numberOfTabs = numberOfTabs self.isEnabled = isEnabled self.isFlippedForRTL = isFlippedForRTL @@ -67,6 +72,7 @@ public struct ToolbarElement: Equatable { public static func == (lhs: ToolbarElement, rhs: ToolbarElement) -> Bool { lhs.iconName == rhs.iconName && lhs.badgeImageName == rhs.badgeImageName && + lhs.maskImageName == rhs.maskImageName && lhs.numberOfTabs == rhs.numberOfTabs && lhs.isEnabled == rhs.isEnabled && lhs.isFlippedForRTL == rhs.isFlippedForRTL && diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift index c22dcbd1fb3a..2ceff60a3084 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift @@ -368,8 +368,11 @@ class BrowserViewController: UIViewController, if isToolbarRefactorEnabled { let badgeImageName = showWarningBadge ? StandardImageIdentifiers.Large.warningFill : nil + let maskImageName = showWarningBadge ? ImageIdentifiers.menuWarningMask : nil + let action = ToolbarMiddlewareAction( badgeImageName: badgeImageName, + maskImageName: maskImageName, windowUUID: windowUUID, actionType: ToolbarMiddlewareActionType.showMenuWarningBadge ) diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift index 173e54ae2913..106225238f43 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift @@ -85,6 +85,7 @@ class AddressToolbarContainerModel: Equatable { ToolbarElement( iconName: action.iconName, badgeImageName: action.badgeImageName, + maskImageName: action.maskImageName, numberOfTabs: action.numberOfTabs, isEnabled: action.isEnabled, isFlippedForRTL: action.isFlippedForRTL, diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/NavigationToolbarContainerModel.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/NavigationToolbarContainerModel.swift index 3553f323cc25..25c963647718 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/NavigationToolbarContainerModel.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/NavigationToolbarContainerModel.swift @@ -20,6 +20,7 @@ struct NavigationToolbarContainerModel: Equatable { ToolbarElement( iconName: action.iconName, badgeImageName: action.badgeImageName, + maskImageName: action.maskImageName, numberOfTabs: action.numberOfTabs, isEnabled: action.isEnabled, isFlippedForRTL: action.isFlippedForRTL, diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarAction.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarAction.swift index 155284516acd..cc45794ac9d9 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarAction.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarAction.swift @@ -6,7 +6,7 @@ import Common import Redux import ToolbarKit -class ToolbarAction: Action { +final class ToolbarAction: Action { let addressToolbarModel: AddressToolbarModel? let navigationToolbarModel: NavigationToolbarModel? let toolbarPosition: AddressToolbarPosition? @@ -14,6 +14,7 @@ class ToolbarAction: Action { let url: URL? let isPrivate: Bool? let badgeImageName: String? + let maskImageName: String? let isShowingNavigationToolbar: Bool? let isShowingTopTabs: Bool? let canGoBack: Bool? @@ -26,6 +27,7 @@ class ToolbarAction: Action { url: URL? = nil, isPrivate: Bool? = nil, badgeImageName: String? = nil, + maskImageName: String? = nil, isShowingNavigationToolbar: Bool? = nil, isShowingTopTabs: Bool? = nil, canGoBack: Bool? = nil, @@ -39,6 +41,7 @@ class ToolbarAction: Action { self.url = url self.isPrivate = isPrivate self.badgeImageName = badgeImageName + self.maskImageName = maskImageName self.isShowingNavigationToolbar = isShowingNavigationToolbar self.isShowingTopTabs = isShowingTopTabs self.canGoBack = canGoBack @@ -71,6 +74,7 @@ class ToolbarMiddlewareAction: Action { let canGoBack: Bool? let canGoForward: Bool? let badgeImageName: String? + let maskImageName: String? init(buttonType: ToolbarActionState.ActionType? = nil, buttonTapped: UIButton? = nil, @@ -84,6 +88,7 @@ class ToolbarMiddlewareAction: Action { canGoBack: Bool? = nil, canGoForward: Bool? = nil, badgeImageName: String? = nil, + maskImageName: String? = nil, windowUUID: WindowUUID, actionType: ActionType) { self.buttonType = buttonType @@ -98,6 +103,7 @@ class ToolbarMiddlewareAction: Action { self.canGoBack = canGoBack self.canGoForward = canGoForward self.badgeImageName = badgeImageName + self.maskImageName = maskImageName super.init(windowUUID: windowUUID, actionType: actionType) } } diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarActionState.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarActionState.swift index 31cbdef318aa..65a01d4605fa 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarActionState.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarActionState.swift @@ -27,6 +27,7 @@ struct ToolbarActionState: Equatable, FeatureFlaggable { var actionType: ActionType var iconName: String var badgeImageName: String? + var maskImageName: String? var numberOfTabs: Int? var isFlippedForRTL = false var isShowingTopTabs: Bool? diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift index 9a53aa73dc35..96285447ac3f 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift @@ -402,6 +402,7 @@ class ToolbarMiddleware: FeatureFlaggable { let toolbarAction = ToolbarAction(addressToolbarModel: addressToolbarModel, navigationToolbarModel: navToolbarModel, badgeImageName: action.badgeImageName, + maskImageName: action.maskImageName, windowUUID: action.windowUUID, actionType: ToolbarActionType.showMenuWarningBadge) store.dispatch(toolbarAction) @@ -449,10 +450,11 @@ class ToolbarMiddleware: FeatureFlaggable { let numberOfTabs = action.numberOfTabs ?? toolbarState.numberOfTabs let isShowMenuWarningAction = action.actionType as? ToolbarMiddlewareActionType == .showMenuWarningBadge - let menuBadgeImageName = isShowMenuWarningAction ? action.badgeImageName : toolbarState.menuWarningBadge + let menuBadgeImageName = isShowMenuWarningAction ? action.badgeImageName : toolbarState.badgeImageName + let maskImageName = isShowMenuWarningAction ? action.maskImageName : toolbarState.maskImageName actions.append(contentsOf: [tabsAction(numberOfTabs: numberOfTabs), - menuAction(badgeImageName: menuBadgeImageName)]) + menuAction(badgeImageName: menuBadgeImageName, maskImageName: maskImageName)]) return actions } @@ -594,14 +596,15 @@ class ToolbarMiddleware: FeatureFlaggable { let numberOfTabs = action.numberOfTabs ?? toolbarState.numberOfTabs let isShowMenuWarningAction = action.actionType as? ToolbarMiddlewareActionType == .showMenuWarningBadge - let menuBadgeImageName = isShowMenuWarningAction ? action.badgeImageName : toolbarState.menuWarningBadge + let menuBadgeImageName = isShowMenuWarningAction ? action.badgeImageName : toolbarState.badgeImageName + let maskImageName = isShowMenuWarningAction ? action.maskImageName : toolbarState.maskImageName let actions = [ backAction(enabled: canGoBack), forwardAction(enabled: canGoForward), middleAction, tabsAction(numberOfTabs: numberOfTabs, isShowingTopTabs: isShowingTopTabs), - menuAction(badgeImageName: menuBadgeImageName) + menuAction(badgeImageName: menuBadgeImageName, maskImageName: maskImageName) ] let displayBorder = shouldDisplayNavigationToolbarBorder(toolbarPosition: toolbarState.toolbarPosition) @@ -662,11 +665,12 @@ class ToolbarMiddleware: FeatureFlaggable { a11yId: AccessibilityIdentifiers.Toolbar.tabsButton) } - private func menuAction(badgeImageName: String? = nil) -> ToolbarActionState { + private func menuAction(badgeImageName: String? = nil, maskImageName: String? = nil) -> ToolbarActionState { return ToolbarActionState( actionType: .menu, iconName: StandardImageIdentifiers.Large.appMenu, badgeImageName: badgeImageName, + maskImageName: maskImageName, isEnabled: true, a11yLabel: .AppMenu.Toolbar.MenuButtonAccessibilityLabel, a11yId: AccessibilityIdentifiers.Toolbar.settingsMenuButton) diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarState.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarState.swift index 76fa594d4696..3d229498d26d 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarState.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarState.swift @@ -14,7 +14,8 @@ struct ToolbarState: ScreenState, Equatable { var navigationToolbar: NavigationBarState let isShowingNavigationToolbar: Bool let isShowingTopTabs: Bool - let menuWarningBadge: String? + let badgeImageName: String? + let maskImageName: String? let canGoBack: Bool let canGoForward: Bool var numberOfTabs: Int @@ -36,7 +37,8 @@ struct ToolbarState: ScreenState, Equatable { navigationToolbar: toolbarState.navigationToolbar, isShowingNavigationToolbar: toolbarState.isShowingNavigationToolbar, isShowingTopTabs: toolbarState.isShowingTopTabs, - menuWarningBadge: toolbarState.menuWarningBadge, + badgeImageName: toolbarState.badgeImageName, + maskImageName: toolbarState.maskImageName, canGoBack: toolbarState.canGoBack, canGoForward: toolbarState.canGoForward, numberOfTabs: toolbarState.numberOfTabs) @@ -51,7 +53,8 @@ struct ToolbarState: ScreenState, Equatable { navigationToolbar: NavigationBarState(windowUUID: windowUUID), isShowingNavigationToolbar: true, isShowingTopTabs: false, - menuWarningBadge: nil, + badgeImageName: nil, + maskImageName: nil, canGoBack: false, canGoForward: false, numberOfTabs: 1 @@ -66,7 +69,8 @@ struct ToolbarState: ScreenState, Equatable { navigationToolbar: NavigationBarState, isShowingNavigationToolbar: Bool, isShowingTopTabs: Bool, - menuWarningBadge: String?, + badgeImageName: String?, + maskImageName: String?, canGoBack: Bool, canGoForward: Bool, numberOfTabs: Int @@ -78,7 +82,8 @@ struct ToolbarState: ScreenState, Equatable { self.navigationToolbar = navigationToolbar self.isShowingNavigationToolbar = isShowingNavigationToolbar self.isShowingTopTabs = isShowingTopTabs - self.menuWarningBadge = menuWarningBadge + self.badgeImageName = badgeImageName + self.maskImageName = maskImageName self.canGoBack = canGoBack self.canGoForward = canGoForward self.numberOfTabs = numberOfTabs @@ -103,7 +108,8 @@ struct ToolbarState: ScreenState, Equatable { navigationToolbar: NavigationBarState.reducer(state.navigationToolbar, toolbarAction), isShowingNavigationToolbar: toolbarAction.isShowingNavigationToolbar ?? state.isShowingNavigationToolbar, isShowingTopTabs: toolbarAction.isShowingTopTabs ?? state.isShowingTopTabs, - menuWarningBadge: state.menuWarningBadge, + badgeImageName: state.badgeImageName, + maskImageName: state.maskImageName, canGoBack: toolbarAction.canGoBack ?? state.canGoBack, canGoForward: toolbarAction.canGoForward ?? state.canGoForward, numberOfTabs: state.numberOfTabs) @@ -118,7 +124,8 @@ struct ToolbarState: ScreenState, Equatable { navigationToolbar: NavigationBarState.reducer(state.navigationToolbar, toolbarAction), isShowingNavigationToolbar: toolbarAction.isShowingNavigationToolbar ?? state.isShowingNavigationToolbar, isShowingTopTabs: toolbarAction.isShowingTopTabs ?? state.isShowingTopTabs, - menuWarningBadge: toolbarAction.badgeImageName, + badgeImageName: toolbarAction.badgeImageName, + maskImageName: toolbarAction.maskImageName, canGoBack: toolbarAction.canGoBack ?? state.canGoBack, canGoForward: toolbarAction.canGoForward ?? state.canGoForward, numberOfTabs: state.numberOfTabs) @@ -133,7 +140,8 @@ struct ToolbarState: ScreenState, Equatable { navigationToolbar: NavigationBarState.reducer(state.navigationToolbar, toolbarAction), isShowingNavigationToolbar: state.isShowingNavigationToolbar, isShowingTopTabs: state.isShowingTopTabs, - menuWarningBadge: state.menuWarningBadge, + badgeImageName: state.badgeImageName, + maskImageName: state.maskImageName, canGoBack: state.canGoBack, canGoForward: state.canGoForward, numberOfTabs: toolbarAction.numberOfTabs ?? state.numberOfTabs) @@ -148,7 +156,8 @@ struct ToolbarState: ScreenState, Equatable { navigationToolbar: NavigationBarState.reducer(state.navigationToolbar, action), isShowingNavigationToolbar: state.isShowingNavigationToolbar, isShowingTopTabs: state.isShowingTopTabs, - menuWarningBadge: state.menuWarningBadge, + badgeImageName: state.badgeImageName, + maskImageName: state.maskImageName, canGoBack: state.canGoBack, canGoForward: state.canGoForward, numberOfTabs: state.numberOfTabs) @@ -163,7 +172,8 @@ struct ToolbarState: ScreenState, Equatable { navigationToolbar: NavigationBarState.reducer(state.navigationToolbar, action), isShowingNavigationToolbar: state.isShowingNavigationToolbar, isShowingTopTabs: state.isShowingTopTabs, - menuWarningBadge: state.menuWarningBadge, + badgeImageName: state.badgeImageName, + maskImageName: state.maskImageName, canGoBack: state.canGoBack, canGoForward: state.canGoForward, numberOfTabs: state.numberOfTabs) @@ -177,7 +187,8 @@ struct ToolbarState: ScreenState, Equatable { navigationToolbar: state.navigationToolbar, isShowingNavigationToolbar: state.isShowingNavigationToolbar, isShowingTopTabs: state.isShowingTopTabs, - menuWarningBadge: state.menuWarningBadge, + badgeImageName: state.badgeImageName, + maskImageName: state.maskImageName, canGoBack: state.canGoBack, canGoForward: state.canGoForward, numberOfTabs: state.numberOfTabs) diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Toolbar/AddressToolbarContainerModelTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Toolbar/AddressToolbarContainerModelTests.swift index 37247162abf8..c5bdd466d056 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Toolbar/AddressToolbarContainerModelTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Toolbar/AddressToolbarContainerModelTests.swift @@ -32,7 +32,8 @@ class AddressToolbarContainerModelTests: XCTestCase { navigationToolbar: navigationState, isShowingNavigationToolbar: true, isShowingTopTabs: true, - menuWarningBadge: nil, + badgeImageName: nil, + maskImageName: nil, canGoBack: true, canGoForward: true, numberOfTabs: 1) From 43f44fc0e2181ad6348a0c5deedad15d021083e5 Mon Sep 17 00:00:00 2001 From: OrlaM Date: Fri, 2 Aug 2024 09:54:56 -0400 Subject: [PATCH 035/128] Bugfix FXIOS-9755 Update the url bar even if there is no webview (#21431) --- .../Views/BrowserViewController.swift | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift index 2ceff60a3084..e16e20e2709e 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift @@ -3400,8 +3400,9 @@ extension BrowserViewController: TabManagerDelegate { selected?.webView?.applyTheme(theme: currentTheme()) } - if let tab = selected, let webView = tab.webView { + if let tab = selected { updateURLBarDisplayURL(tab) + if !isToolbarRefactorEnabled, urlBar.inOverlayMode, tab.url?.displayURL != nil { urlBar.leaveOverlayMode(reason: .finished, shouldCancelLoading: false) } @@ -3415,16 +3416,18 @@ extension BrowserViewController: TabManagerDelegate { scrollController.tab = tab - webView.accessibilityLabel = .WebViewAccessibilityLabel - webView.accessibilityIdentifier = "contentView" - webView.accessibilityElementsHidden = false + if let webView = tab.webView { + webView.accessibilityLabel = .WebViewAccessibilityLabel + webView.accessibilityIdentifier = "contentView" + webView.accessibilityElementsHidden = false - browserDelegate?.show(webView: webView) + browserDelegate?.show(webView: webView) - if webView.url == nil { - // The web view can go gray if it was zombified due to memory pressure. - // When this happens, the URL is nil, so try restoring the page upon selection. - tab.reload() + if webView.url == nil { + // The web view can go gray if it was zombified due to memory pressure. + // When this happens, the URL is nil, so try restoring the page upon selection. + tab.reload() + } } // Update Fakespot sidebar if necessary From 5173df1728d2ce5725f9bf17e82b1356dea908c4 Mon Sep 17 00:00:00 2001 From: PARAIPAN SORIN <51127880+PARAIPAN9@users.noreply.github.com> Date: Fri, 2 Aug 2024 18:04:22 +0300 Subject: [PATCH 036/128] Add FXIOS-9504 - Add reader mode button to address toolbar (#21321) * Add reader mode view * Hide lock icon image when in reader mode * Extract code in method, improve indentation * Rename function and add logic check --- .../LocationView/LocationView.swift | 15 ++++- .../LocationView/LocationViewState.swift | 4 +- .../Sources/ToolbarKit/ToolbarButton.swift | 8 +-- .../Actions/GeneralBrowserAction.swift | 1 + .../BrowserViewController+ReaderMode.swift | 8 +-- ...BrowserViewController+URLBarDelegate.swift | 15 +---- ...owserViewController+WebViewDelegates.swift | 7 +-- .../State/BrowserViewControllerState.swift | 11 ++++ .../Views/BrowserViewController.swift | 59 +++++++++++++++---- .../Models/AddressToolbarContainerModel.swift | 3 +- .../NavigationToolbarContainerModel.swift | 1 + .../Toolbars/Redux/AddressBarState.swift | 6 +- .../Toolbars/Redux/ToolbarAction.swift | 8 +++ .../Toolbars/Redux/ToolbarActionState.swift | 1 + .../Toolbars/Redux/ToolbarMiddleware.swift | 37 +++++++++--- .../Browser/Toolbars/Redux/ToolbarState.swift | 11 ++++ .../AddressToolbarContainerModelTests.swift | 1 + 17 files changed, 140 insertions(+), 56 deletions(-) diff --git a/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationView.swift b/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationView.swift index 64940bdb67d7..4782ae9a3498 100644 --- a/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationView.swift +++ b/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationView.swift @@ -49,6 +49,7 @@ final class LocationView: UIView, UITextFieldDelegate, ThemeApplicable, Accessib private var clearButtonWidthConstraint: NSLayoutConstraint? private var urlTextFieldLeadingConstraint: NSLayoutConstraint? + private var lockIconWidthAnchor: NSLayoutConstraint? private lazy var iconContainerStackView: UIStackView = .build { view in view.axis = .horizontal @@ -235,6 +236,12 @@ final class LocationView: UIView, UITextFieldDelegate, ThemeApplicable, Accessib updateGradient() } + private func updateWidthForLockIcon(_ width: CGFloat) { + lockIconWidthAnchor?.isActive = false + lockIconWidthAnchor = lockIconButton.widthAnchor.constraint(equalToConstant: width) + lockIconWidthAnchor?.isActive = true + } + // MARK: - `urlTextField` Configuration private func configureURLTextField(_ state: LocationViewState) { urlTextField.resignFirstResponder() @@ -269,7 +276,13 @@ final class LocationView: UIView, UITextFieldDelegate, ThemeApplicable, Accessib // MARK: - `lockIconButton` Configuration private func configureLockIconButton(_ state: LocationViewState) { - let lockImage = UIImage(named: state.lockIconImageName)?.withRenderingMode(.alwaysTemplate) + guard let lockIconImageName = state.lockIconImageName else { + updateWidthForLockIcon(0) + return + } + updateWidthForLockIcon(UX.lockIconImageViewSize.width) + + let lockImage = UIImage(named: lockIconImageName)?.withRenderingMode(.alwaysTemplate) lockIconButton.setImage(lockImage, for: .normal) onTapLockIcon = state.onTapLockIcon } diff --git a/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationViewState.swift b/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationViewState.swift index c0ce76531c19..e0a9d77a90d0 100644 --- a/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationViewState.swift +++ b/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationViewState.swift @@ -16,7 +16,7 @@ public struct LocationViewState { public let urlTextFieldA11yLabel: String public let searchEngineImage: UIImage? - public let lockIconImageName: String + public let lockIconImageName: String? public let url: URL? public let searchTerm: String? public var onTapLockIcon: (() -> Void)? @@ -31,7 +31,7 @@ public struct LocationViewState { urlTextFieldA11yId: String, urlTextFieldA11yLabel: String, searchEngineImage: UIImage?, - lockIconImageName: String, + lockIconImageName: String?, url: URL?, searchTerm: String?, onTapLockIcon: (() -> Void)? = nil, diff --git a/BrowserKit/Sources/ToolbarKit/ToolbarButton.swift b/BrowserKit/Sources/ToolbarKit/ToolbarButton.swift index 99c92d98eacb..20fb087488a1 100644 --- a/BrowserKit/Sources/ToolbarKit/ToolbarButton.swift +++ b/BrowserKit/Sources/ToolbarKit/ToolbarButton.swift @@ -39,9 +39,7 @@ class ToolbarButton: UIButton, ThemeApplicable { } open func configure(element: ToolbarElement) { - guard var config = configuration else { - return - } + guard var config = configuration else { return } removeAllGestureRecognizers() configureLongPressGestureRecognizerIfNeeded(for: element) shouldDisplayAsHighlighted = element.shouldDisplayAsHighlighted @@ -79,9 +77,7 @@ class ToolbarButton: UIButton, ThemeApplicable { } override public func updateConfiguration() { - guard var updatedConfiguration = configuration else { - return - } + guard var updatedConfiguration = configuration else { return } switch state { case .highlighted: diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Actions/GeneralBrowserAction.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Actions/GeneralBrowserAction.swift index 60289d13c1b6..2ef9df2d0af3 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Actions/GeneralBrowserAction.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Actions/GeneralBrowserAction.swift @@ -48,6 +48,7 @@ enum GeneralBrowserActionType: ActionType { case stopLoadingWebsite case reloadWebsite case showShare + case showReaderMode case addNewTab case showNewTabLongPressActions case clearData diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+ReaderMode.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+ReaderMode.swift index fe5c1c73e031..0675dff407bf 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+ReaderMode.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+ReaderMode.swift @@ -4,13 +4,13 @@ import WebEngine import Shared +import Common extension BrowserViewController: ReaderModeDelegate { func readerMode(_ readerMode: ReaderMode, didChangeReaderModeState state: ReaderModeState, forTab tab: Tab) { // Update reader mode state if is the selected tab. Otherwise it will update once is active - if !isToolbarRefactorEnabled, tabManager.selectedTab === tab, !isToolbarRefactorEnabled { - urlBar.updateReaderModeState(state) - } + guard tabManager.selectedTab === tab else { return } + updateReaderModeState(for: tab, readerModeState: state) } func readerMode(_ readerMode: ReaderMode, didDisplayReaderizedContentForTab tab: Tab) { @@ -91,7 +91,7 @@ extension BrowserViewController { } func hideReaderModeBar(animated: Bool) { - guard let readerModeBar = readerModeBar else { return } + guard let readerModeBar else { return } if isBottomSearchBar { overKeyboardContainer.removeArrangedView(readerModeBar) diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+URLBarDelegate.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+URLBarDelegate.swift index ec06b200ce55..541384f66650 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+URLBarDelegate.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+URLBarDelegate.swift @@ -181,20 +181,7 @@ extension BrowserViewController: URLBarDelegate { } func urlBarDidPressReaderMode(_ urlBar: URLBarView) { - guard let tab = tabManager.selectedTab, - let readerMode = tab.getContentScript(name: "ReaderMode") as? ReaderMode - else { return } - - switch readerMode.state { - case .available: - enableReaderMode() - TelemetryWrapper.recordEvent(category: .action, method: .tap, object: .readerModeOpenButton) - case .active: - disableReaderMode() - TelemetryWrapper.recordEvent(category: .action, method: .tap, object: .readerModeCloseButton) - case .unavailable: - break - } + toggleReaderMode() } func urlBarDidLongPressReaderMode(_ urlBar: URLBarView) -> Bool { diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+WebViewDelegates.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+WebViewDelegates.swift index 50ab02b2d1c5..8d6d3f7b770a 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+WebViewDelegates.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+WebViewDelegates.swift @@ -377,10 +377,9 @@ extension BrowserViewController: WKNavigationDelegate { // are going to a about:reader page. Then we keep it on screen: it will change status // (orange color) as soon as the page has loaded. if let url = webView.url { - if !url.isReaderModeURL, !isToolbarRefactorEnabled { - urlBar.updateReaderModeState(ReaderModeState.unavailable) - hideReaderModeBar(animated: false) - } + guard !url.isReaderModeURL else { return } + updateReaderModeState(for: tabManager.selectedTab, readerModeState: .unavailable) + hideReaderModeBar(animated: false) } } diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/State/BrowserViewControllerState.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/State/BrowserViewControllerState.swift index 7f777009543f..8d306ad6c254 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/State/BrowserViewControllerState.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/State/BrowserViewControllerState.swift @@ -27,6 +27,7 @@ struct BrowserViewControllerState: ScreenState, Equatable { case reloadLongPressAction case tabTray case share + case readerMode case newTabLongPressActions case dataClearance } @@ -365,6 +366,16 @@ struct BrowserViewControllerState: ScreenState, Equatable { displayView: .share, buttonTapped: action.buttonTapped, microsurveyState: MicrosurveyPromptState.reducer(state.microsurveyState, action)) + case GeneralBrowserActionType.showReaderMode: + return BrowserViewControllerState( + searchScreenState: state.searchScreenState, + showDataClearanceFlow: state.showDataClearanceFlow, + fakespotState: state.fakespotState, + toast: state.toast, + windowUUID: state.windowUUID, + browserViewType: state.browserViewType, + displayView: .readerMode, + microsurveyState: MicrosurveyPromptState.reducer(state.microsurveyState, action)) case GeneralBrowserActionType.showNewTabLongPressActions: return BrowserViewControllerState( searchScreenState: state.searchScreenState, diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift index e16e20e2709e..75313a8c0553 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift @@ -1795,19 +1795,39 @@ class BrowserViewController: UIViewController, } } + func lockIconImageName(for tab: Tab?) -> String? { + guard let tab, let hasSecureContent = tab.webView?.hasOnlySecureContent else { return nil } + + let lockIconImageName = hasSecureContent ? + StandardImageIdentifiers.Large.lockFill : + StandardImageIdentifiers.Large.lockSlashFill + + return tab.url?.isReaderModeURL == false ? lockIconImageName : nil + } + + func updateReaderModeState(for tab: Tab?, readerModeState: ReaderModeState) { + if isToolbarRefactorEnabled { + let action = ToolbarMiddlewareAction( + lockIconImageName: lockIconImageName(for: tab), + readerModeState: readerModeState, + windowUUID: windowUUID, + actionType: ToolbarMiddlewareActionType.readerModeStateChanged + ) + store.dispatch(action) + } else { + urlBar.updateReaderModeState(readerModeState) + } + } + /// Updates the URL bar text and button states. /// Call this whenever the page URL changes. fileprivate func updateURLBarDisplayURL(_ tab: Tab) { guard !isToolbarRefactorEnabled else { - guard let hasSecureContent = tab.webView?.hasOnlySecureContent else { return } - - let lockIconImageName = hasSecureContent ? - StandardImageIdentifiers.Large.lockFill : - StandardImageIdentifiers.Large.lockSlashFill + guard tab.webView?.hasOnlySecureContent == true else { return } let action = ToolbarMiddlewareAction( isShowingNavigationToolbar: ToolbarHelper().shouldShowNavigationToolbar(for: traitCollection), - lockIconImageName: lockIconImageName, + lockIconImageName: lockIconImageName(for: tab), url: tab.url?.displayURL, canGoBack: tab.canGoBack, canGoForward: tab.canGoForward, @@ -1927,6 +1947,8 @@ class BrowserViewController: UIViewController, case .share: guard let button = state.buttonTapped else { return } didTapOnShare(from: button) + case .readerMode: + toggleReaderMode() case .newTabLongPressActions: presentNewTabLongPressActionSheet(from: view) case .dataClearance: @@ -2046,6 +2068,23 @@ class BrowserViewController: UIViewController, } } + func toggleReaderMode() { + guard let tab = tabManager.selectedTab, + let readerMode = tab.getContentScript(name: "ReaderMode") as? ReaderMode + else { return } + + switch readerMode.state { + case .available: + enableReaderMode() + TelemetryWrapper.recordEvent(category: .action, method: .tap, object: .readerModeOpenButton) + case .active: + disableReaderMode() + TelemetryWrapper.recordEvent(category: .action, method: .tap, object: .readerModeCloseButton) + case .unavailable: + break + } + } + private func showPhotonMainMenu(from button: UIButton?) { guard let button else { return } @@ -3463,18 +3502,14 @@ extension BrowserViewController: TabManagerDelegate { } if let readerMode = selected?.getContentScript(name: ReaderMode.name()) as? ReaderMode { - if !isToolbarRefactorEnabled { - urlBar.updateReaderModeState(readerMode.state) - } + updateReaderModeState(for: selected, readerModeState: readerMode.state) if readerMode.state == .active { showReaderModeBar(animated: false) } else { hideReaderModeBar(animated: false) } } else { - if !isToolbarRefactorEnabled { - urlBar.updateReaderModeState(ReaderModeState.unavailable) - } + updateReaderModeState(for: selected, readerModeState: .unavailable) } if topTabsVisible { diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift index 106225238f43..c72bbb1e9e69 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift @@ -14,7 +14,7 @@ class AddressToolbarContainerModel: Equatable { let borderPosition: AddressToolbarBorderPosition? let searchEngineImage: UIImage? let searchEngines: SearchEngines - let lockIconImageName: String + let lockIconImageName: String? let url: URL? let windowUUID: UUID @@ -89,6 +89,7 @@ class AddressToolbarContainerModel: Equatable { numberOfTabs: action.numberOfTabs, isEnabled: action.isEnabled, isFlippedForRTL: action.isFlippedForRTL, + shouldDisplayAsHighlighted: action.shouldDisplayAsHighlighted, a11yLabel: action.a11yLabel, a11yHint: action.a11yHint, a11yId: action.a11yId, diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/NavigationToolbarContainerModel.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/NavigationToolbarContainerModel.swift index 25c963647718..839d45b8d6c8 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/NavigationToolbarContainerModel.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/NavigationToolbarContainerModel.swift @@ -24,6 +24,7 @@ struct NavigationToolbarContainerModel: Equatable { numberOfTabs: action.numberOfTabs, isEnabled: action.isEnabled, isFlippedForRTL: action.isFlippedForRTL, + shouldDisplayAsHighlighted: action.shouldDisplayAsHighlighted, a11yLabel: action.a11yLabel, a11yHint: action.a11yHint, a11yId: action.a11yId, diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/AddressBarState.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/AddressBarState.swift index 45be0c8c53f4..c80147280acf 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/AddressBarState.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/AddressBarState.swift @@ -13,7 +13,7 @@ struct AddressBarState: StateType, Equatable { var browserActions: [ToolbarActionState] var borderPosition: AddressToolbarBorderPosition? var url: URL? - var lockIconImageName: String + var lockIconImageName: String? var isEditing: Bool var isLoading: Bool @@ -35,7 +35,7 @@ struct AddressBarState: StateType, Equatable { browserActions: [ToolbarActionState], borderPosition: AddressToolbarBorderPosition?, url: URL?, - lockIconImageName: String, + lockIconImageName: String?, isEditing: Bool = false, isLoading: Bool = false) { self.windowUUID = windowUUID @@ -103,7 +103,7 @@ struct AddressBarState: StateType, Equatable { browserActions: state.browserActions, borderPosition: state.borderPosition, url: addressToolbarModel.url, - lockIconImageName: addressToolbarModel.lockIconImageName ?? state.lockIconImageName, + lockIconImageName: addressToolbarModel.lockIconImageName, isEditing: addressToolbarModel.isEditing ?? state.isEditing ) diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarAction.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarAction.swift index cc45794ac9d9..8485175b911d 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarAction.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarAction.swift @@ -19,6 +19,7 @@ final class ToolbarAction: Action { let isShowingTopTabs: Bool? let canGoBack: Bool? let canGoForward: Bool? + let readerModeState: ReaderModeState? init(addressToolbarModel: AddressToolbarModel? = nil, navigationToolbarModel: NavigationToolbarModel? = nil, @@ -32,6 +33,7 @@ final class ToolbarAction: Action { isShowingTopTabs: Bool? = nil, canGoBack: Bool? = nil, canGoForward: Bool? = nil, + readerModeState: ReaderModeState? = nil, windowUUID: WindowUUID, actionType: ActionType) { self.addressToolbarModel = addressToolbarModel @@ -46,6 +48,7 @@ final class ToolbarAction: Action { self.isShowingTopTabs = isShowingTopTabs self.canGoBack = canGoBack self.canGoForward = canGoForward + self.readerModeState = readerModeState super.init(windowUUID: windowUUID, actionType: actionType) } } @@ -59,6 +62,7 @@ enum ToolbarActionType: ActionType { case scrollOffsetChanged case toolbarPositionChanged case showMenuWarningBadge + case readerModeStateChanged } class ToolbarMiddlewareAction: Action { @@ -74,6 +78,7 @@ class ToolbarMiddlewareAction: Action { let canGoBack: Bool? let canGoForward: Bool? let badgeImageName: String? + let readerModeState: ReaderModeState? let maskImageName: String? init(buttonType: ToolbarActionState.ActionType? = nil, @@ -88,6 +93,7 @@ class ToolbarMiddlewareAction: Action { canGoBack: Bool? = nil, canGoForward: Bool? = nil, badgeImageName: String? = nil, + readerModeState: ReaderModeState? = nil, maskImageName: String? = nil, windowUUID: WindowUUID, actionType: ActionType) { @@ -103,6 +109,7 @@ class ToolbarMiddlewareAction: Action { self.canGoBack = canGoBack self.canGoForward = canGoForward self.badgeImageName = badgeImageName + self.readerModeState = readerModeState self.maskImageName = maskImageName super.init(windowUUID: windowUUID, actionType: actionType) } @@ -120,4 +127,5 @@ enum ToolbarMiddlewareActionType: ActionType { case backButtonStateChanged case forwardButtonStateChanged case showMenuWarningBadge + case readerModeStateChanged } diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarActionState.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarActionState.swift index 65a01d4605fa..9cee22e36c41 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarActionState.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarActionState.swift @@ -32,6 +32,7 @@ struct ToolbarActionState: Equatable, FeatureFlaggable { var isFlippedForRTL = false var isShowingTopTabs: Bool? var isEnabled: Bool + var shouldDisplayAsHighlighted = false var a11yLabel: String var a11yHint: String? var a11yId: String diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift index 96285447ac3f..a3b738371eb9 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift @@ -6,7 +6,7 @@ import Common import Redux import ToolbarKit -class ToolbarMiddleware: FeatureFlaggable { +final class ToolbarMiddleware: FeatureFlaggable { private let profile: Profile private let manager: ToolbarManager private let logger: Logger @@ -42,6 +42,13 @@ class ToolbarMiddleware: FeatureFlaggable { a11yHint: .TabLocationReloadAccessibilityHint, a11yId: AccessibilityIdentifiers.Toolbar.reloadButton) + private lazy var readerModeAction = ToolbarActionState( + actionType: .readerMode, + iconName: StandardImageIdentifiers.Large.readerView, + isEnabled: true, + a11yLabel: .TabLocationReaderModeAccessibilityLabel, + a11yId: AccessibilityIdentifiers.Toolbar.readerModeButton) + lazy var qrCodeScanAction = ToolbarActionState( actionType: .qrCode, iconName: StandardImageIdentifiers.Large.qrCode, @@ -126,7 +133,8 @@ class ToolbarMiddleware: FeatureFlaggable { case ToolbarMiddlewareActionType.didTapButton: resolveToolbarMiddlewareButtonTapActions(action: action, state: state) - case ToolbarMiddlewareActionType.urlDidChange: + case ToolbarMiddlewareActionType.urlDidChange, + ToolbarMiddlewareActionType.readerModeStateChanged: updateUrlAndActions(action: action, state: state) case ToolbarMiddlewareActionType.didStartEditingUrl: @@ -234,6 +242,11 @@ class ToolbarMiddleware: FeatureFlaggable { actionType: ToolbarMiddlewareActionType.cancelEdit) store.dispatch(action) + case .readerMode: + let action = GeneralBrowserAction(windowUUID: action.windowUUID, + actionType: GeneralBrowserActionType.showReaderMode) + store.dispatch(action) + case .reload: let action = GeneralBrowserAction(windowUUID: action.windowUUID, actionType: GeneralBrowserActionType.reloadWebsite) @@ -367,6 +380,7 @@ class ToolbarMiddleware: FeatureFlaggable { isShowingNavigationToolbar: action.isShowingNavigationToolbar, canGoBack: action.canGoBack, canGoForward: action.canGoForward, + readerModeState: action.readerModeState, windowUUID: action.windowUUID, actionType: ToolbarActionType.urlDidChange) store.dispatch(toolbarAction) @@ -496,16 +510,11 @@ class ToolbarMiddleware: FeatureFlaggable { private func addressToolbarPageActions( action: ToolbarMiddlewareAction, - state: AppState, + toolbarState: borrowing ToolbarState, isEditing: Bool ) -> [ToolbarActionState] { var actions = [ToolbarActionState]() - guard let toolbarState = state.screenState(ToolbarState.self, - for: .toolbar, - window: action.windowUUID) - else { return actions } - let isUrlChangeAction = action.actionType as? ToolbarMiddlewareActionType == .urlDidChange let url = isUrlChangeAction ? action.url : toolbarState.addressToolbar.url @@ -514,6 +523,16 @@ class ToolbarMiddleware: FeatureFlaggable { return [qrCodeScanAction] } + let isReaderModeAction = action.actionType as? ToolbarMiddlewareActionType == .readerModeStateChanged + let readerModeState = isReaderModeAction ? action.readerModeState : toolbarState.readerModeState + readerModeAction.shouldDisplayAsHighlighted = readerModeState == .active + + switch readerModeState { + case .active, .available: + actions.append(readerModeAction) + default: break + } + actions.append(shareAction) let isLoadingChangeAction = action.actionType as? ToolbarMiddlewareActionType == .websiteLoadingStateDidChange @@ -558,7 +577,7 @@ class ToolbarMiddleware: FeatureFlaggable { action: action, state: state, isEditing: editing) - let pageActions = addressToolbarPageActions(action: action, state: state, isEditing: editing) + let pageActions = addressToolbarPageActions(action: action, toolbarState: toolbarState, isEditing: editing) let browserActions = addressToolbarBrowserActions(action: action, state: state) let isUrlChangeAction = action.actionType as? ToolbarMiddlewareActionType == .urlDidChange let url = isUrlChangeAction ? action.url : toolbarState.addressToolbar.url diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarState.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarState.swift index 3d229498d26d..d341669cf1f7 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarState.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarState.swift @@ -14,6 +14,7 @@ struct ToolbarState: ScreenState, Equatable { var navigationToolbar: NavigationBarState let isShowingNavigationToolbar: Bool let isShowingTopTabs: Bool + let readerModeState: ReaderModeState? let badgeImageName: String? let maskImageName: String? let canGoBack: Bool @@ -37,6 +38,7 @@ struct ToolbarState: ScreenState, Equatable { navigationToolbar: toolbarState.navigationToolbar, isShowingNavigationToolbar: toolbarState.isShowingNavigationToolbar, isShowingTopTabs: toolbarState.isShowingTopTabs, + readerModeState: toolbarState.readerModeState, badgeImageName: toolbarState.badgeImageName, maskImageName: toolbarState.maskImageName, canGoBack: toolbarState.canGoBack, @@ -53,6 +55,7 @@ struct ToolbarState: ScreenState, Equatable { navigationToolbar: NavigationBarState(windowUUID: windowUUID), isShowingNavigationToolbar: true, isShowingTopTabs: false, + readerModeState: nil, badgeImageName: nil, maskImageName: nil, canGoBack: false, @@ -69,6 +72,7 @@ struct ToolbarState: ScreenState, Equatable { navigationToolbar: NavigationBarState, isShowingNavigationToolbar: Bool, isShowingTopTabs: Bool, + readerModeState: ReaderModeState?, badgeImageName: String?, maskImageName: String?, canGoBack: Bool, @@ -82,6 +86,7 @@ struct ToolbarState: ScreenState, Equatable { self.navigationToolbar = navigationToolbar self.isShowingNavigationToolbar = isShowingNavigationToolbar self.isShowingTopTabs = isShowingTopTabs + self.readerModeState = readerModeState self.badgeImageName = badgeImageName self.maskImageName = maskImageName self.canGoBack = canGoBack @@ -108,6 +113,7 @@ struct ToolbarState: ScreenState, Equatable { navigationToolbar: NavigationBarState.reducer(state.navigationToolbar, toolbarAction), isShowingNavigationToolbar: toolbarAction.isShowingNavigationToolbar ?? state.isShowingNavigationToolbar, isShowingTopTabs: toolbarAction.isShowingTopTabs ?? state.isShowingTopTabs, + readerModeState: toolbarAction.readerModeState ?? state.readerModeState, badgeImageName: state.badgeImageName, maskImageName: state.maskImageName, canGoBack: toolbarAction.canGoBack ?? state.canGoBack, @@ -124,6 +130,7 @@ struct ToolbarState: ScreenState, Equatable { navigationToolbar: NavigationBarState.reducer(state.navigationToolbar, toolbarAction), isShowingNavigationToolbar: toolbarAction.isShowingNavigationToolbar ?? state.isShowingNavigationToolbar, isShowingTopTabs: toolbarAction.isShowingTopTabs ?? state.isShowingTopTabs, + readerModeState: state.readerModeState, badgeImageName: toolbarAction.badgeImageName, maskImageName: toolbarAction.maskImageName, canGoBack: toolbarAction.canGoBack ?? state.canGoBack, @@ -140,6 +147,7 @@ struct ToolbarState: ScreenState, Equatable { navigationToolbar: NavigationBarState.reducer(state.navigationToolbar, toolbarAction), isShowingNavigationToolbar: state.isShowingNavigationToolbar, isShowingTopTabs: state.isShowingTopTabs, + readerModeState: state.readerModeState, badgeImageName: state.badgeImageName, maskImageName: state.maskImageName, canGoBack: state.canGoBack, @@ -156,6 +164,7 @@ struct ToolbarState: ScreenState, Equatable { navigationToolbar: NavigationBarState.reducer(state.navigationToolbar, action), isShowingNavigationToolbar: state.isShowingNavigationToolbar, isShowingTopTabs: state.isShowingTopTabs, + readerModeState: state.readerModeState, badgeImageName: state.badgeImageName, maskImageName: state.maskImageName, canGoBack: state.canGoBack, @@ -172,6 +181,7 @@ struct ToolbarState: ScreenState, Equatable { navigationToolbar: NavigationBarState.reducer(state.navigationToolbar, action), isShowingNavigationToolbar: state.isShowingNavigationToolbar, isShowingTopTabs: state.isShowingTopTabs, + readerModeState: state.readerModeState, badgeImageName: state.badgeImageName, maskImageName: state.maskImageName, canGoBack: state.canGoBack, @@ -187,6 +197,7 @@ struct ToolbarState: ScreenState, Equatable { navigationToolbar: state.navigationToolbar, isShowingNavigationToolbar: state.isShowingNavigationToolbar, isShowingTopTabs: state.isShowingTopTabs, + readerModeState: state.readerModeState, badgeImageName: state.badgeImageName, maskImageName: state.maskImageName, canGoBack: state.canGoBack, diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Toolbar/AddressToolbarContainerModelTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Toolbar/AddressToolbarContainerModelTests.swift index c5bdd466d056..e6b514971467 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Toolbar/AddressToolbarContainerModelTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Toolbar/AddressToolbarContainerModelTests.swift @@ -32,6 +32,7 @@ class AddressToolbarContainerModelTests: XCTestCase { navigationToolbar: navigationState, isShowingNavigationToolbar: true, isShowingTopTabs: true, + readerModeState: nil, badgeImageName: nil, maskImageName: nil, canGoBack: true, From a51737a10548b84cee433882e1bf427a4296199d Mon Sep 17 00:00:00 2001 From: Clare So <1740517+clarmso@users.noreply.github.com> Date: Fri, 2 Aug 2024 11:51:22 -0400 Subject: [PATCH 037/128] Bugfix MTE-3146 Fix junit xml file name (#21412) * Fix junit file name * Don't restart simulators to save time * Fixed combined.xml file name * Let's run all tests --- .github/workflows/firefox-ios-ui-tests.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/firefox-ios-ui-tests.yml b/.github/workflows/firefox-ios-ui-tests.yml index b3fe346fa308..437c06a105ac 100644 --- a/.github/workflows/firefox-ios-ui-tests.yml +++ b/.github/workflows/firefox-ios-ui-tests.yml @@ -168,7 +168,7 @@ jobs: python ../test-fixtures/ci/convert_junit_to_markdown.py --smoke --github --${{ env.browser }} ./combined.xml ./github.md cat github.md >> $GITHUB_STEP_SUMMARY python ../test-fixtures/ci/convert_junit_to_markdown.py --smoke --slack --${{ env.browser }} ./combined.xml ./slack.json - mv ./combined junit-smoketests-${{ matrix.ios_simulator }}-`date +"%Y-%m-%d"`.xml + mv ./combined.xml "junit-smoketests-${{ matrix.ios_simulator }}-`date +"%Y-%m-%d"`.xml" working-directory: ${{ env.browser }} - name: Upload junit files id: upload-junit @@ -232,8 +232,6 @@ jobs: - name: Run tests id: run-tests run: | - xcrun simctl shutdown all - xcrun simctl erase all xcrun simctl boot '${{ matrix.ios_simulator }}' xcodebuild \ test-without-building \ @@ -252,7 +250,7 @@ jobs: python ../test-fixtures/ci/convert_junit_to_markdown.py --github --${{ env.browser }} ./build/reports/junit.xml ./github.md cat github.md >> $GITHUB_STEP_SUMMARY python ../test-fixtures/ci/convert_junit_to_markdown.py --slack --${{ env.browser }} ./build/reports/junit.xml ./slack.json - mv ./build/reports/junit.xml junit-fullfunctional-${{ matrix.ios_simulator }}-`date +"%Y-%m-%d"`.xml + mv ./build/reports/junit.xml "junit-fullfunctional-${{ matrix.ios_simulator }}-`date +"%Y-%m-%d"`.xml" working-directory: ${{ env.browser }} - name: Upload junit files id: upload-junit From 014bcc5ce6fa7d65d2462ef2ed9499502bf5ce5f Mon Sep 17 00:00:00 2001 From: Winnie Teichmann <4530+thatswinnie@users.noreply.github.com> Date: Fri, 2 Aug 2024 17:56:36 +0200 Subject: [PATCH 038/128] Add FXIOS-9297 Implement auto complete for text field in address toolbar (#21400) * Add new layer color to theme * Move string extension from shared to common * Create Autocompletable protocol and use it in SearchLoader * Add autocomplete * Show/hide overlay mode * Fix out of bounds error * Disable drag interaction for iPhone * Paste search term correctly * Show cursor * Add cancelEdit action * Make sure overlay mode is started when we are editing and have a search term * Create file for Callback * Show toast when opening link in new tab from library panel * Show overlay mode and select text in text field when user starts editing * Select search term in edit mode correctly * Leave overlay mode when tab changes * Various bug fixes * Address PR comments --- .../Common/Extensions/StringExtension.swift | 12 + .../Sources/Common/Theming/DarkTheme.swift | 1 + .../Sources/Common/Theming/LightTheme.swift | 1 + .../Common/Theming/PrivateModeTheme.swift | 1 + .../Common/Theming/ThemeColourPalette.swift | 1 + .../AddressToolbar/AddressToolbar.swift | 2 + .../BrowserAddressToolbar.swift | 12 +- .../LocationView/Callback.swift | 19 ++ .../LocationView/LocationTextField.swift | 254 +++++++++++++++++- .../LocationView/LocationView.swift | 74 +++-- .../LocationView/LocationViewDelegate.swift | 5 +- .../LocationView/LocationViewState.swift | 6 + firefox-ios/Client.xcodeproj/project.pbxproj | 4 + ...serViewController+TabToolbarDelegate.swift | 4 +- ...BrowserViewController+URLBarDelegate.swift | 42 +-- .../Views/BrowserViewController.swift | 81 ++++-- .../Frontend/Browser/SearchLoader.swift | 10 +- .../Toolbars/AddressToolbarContainer.swift | 43 ++- .../Browser/Toolbars/Autocompletable.swift | 9 + .../Models/AddressToolbarContainerModel.swift | 16 +- .../Toolbars/Redux/AddressBarState.swift | 83 +++++- .../Toolbars/Redux/ToolbarAction.swift | 6 + .../Toolbars/Redux/ToolbarMiddleware.swift | 24 +- .../Browser/Toolbars/Redux/ToolbarState.swift | 5 +- .../Frontend/Toolbar+URLBar/URLBarView.swift | 9 +- .../PhotonActionSheetProtocol.swift | 11 +- .../Shared/Extensions/String+Extension.swift | 10 - 27 files changed, 622 insertions(+), 123 deletions(-) create mode 100644 BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/Callback.swift create mode 100644 firefox-ios/Client/Frontend/Browser/Toolbars/Autocompletable.swift diff --git a/BrowserKit/Sources/Common/Extensions/StringExtension.swift b/BrowserKit/Sources/Common/Extensions/StringExtension.swift index a2e9b0335c30..6894e206fca3 100644 --- a/BrowserKit/Sources/Common/Extensions/StringExtension.swift +++ b/BrowserKit/Sources/Common/Extensions/StringExtension.swift @@ -11,3 +11,15 @@ extension StringProtocol { return replacingOccurrences(of: target, with: "") } } + +public extension String { + /// Returns a new string made by removing the leading String characters contained + /// in a given character set. + func stringByTrimmingLeadingCharactersInSet(_ set: CharacterSet) -> String { + var trimmed = self + while trimmed.rangeOfCharacter(from: set)?.lowerBound == trimmed.startIndex { + trimmed.remove(at: trimmed.startIndex) + } + return trimmed + } +} diff --git a/BrowserKit/Sources/Common/Theming/DarkTheme.swift b/BrowserKit/Sources/Common/Theming/DarkTheme.swift index 94678d11f43d..baaeb49a092d 100644 --- a/BrowserKit/Sources/Common/Theming/DarkTheme.swift +++ b/BrowserKit/Sources/Common/Theming/DarkTheme.swift @@ -47,6 +47,7 @@ private struct DarkColourPalette: ThemeColourPalette { var layerConfirmation: UIColor = FXColors.Green80 var layerWarning: UIColor = FXColors.Yellow70.withAlphaComponent(0.77) var layerError: UIColor = FXColors.Pink80 + var layerSelectedText: UIColor = FXColors.DarkGrey05.withAlphaComponent(0.34) var layerSearch: UIColor = FXColors.DarkGrey80 var layerGradientURL = Gradient(colors: [ FXColors.DarkGrey80.withAlphaComponent(0), diff --git a/BrowserKit/Sources/Common/Theming/LightTheme.swift b/BrowserKit/Sources/Common/Theming/LightTheme.swift index 5f69658b0435..e12d4a554d78 100644 --- a/BrowserKit/Sources/Common/Theming/LightTheme.swift +++ b/BrowserKit/Sources/Common/Theming/LightTheme.swift @@ -36,6 +36,7 @@ private struct LightColourPalette: ThemeColourPalette { var layerConfirmation: UIColor = FXColors.Green20 var layerWarning: UIColor = FXColors.Yellow20 var layerError: UIColor = FXColors.Red10 + var layerSelectedText: UIColor = FXColors.DarkGrey05.withAlphaComponent(0.73) var layerSearch: UIColor = FXColors.LightGrey30 var layerGradientURL = Gradient(colors: [ FXColors.LightGrey30.withAlphaComponent(0), diff --git a/BrowserKit/Sources/Common/Theming/PrivateModeTheme.swift b/BrowserKit/Sources/Common/Theming/PrivateModeTheme.swift index fd3fa90d0e7b..38d3d1d25426 100644 --- a/BrowserKit/Sources/Common/Theming/PrivateModeTheme.swift +++ b/BrowserKit/Sources/Common/Theming/PrivateModeTheme.swift @@ -38,6 +38,7 @@ private struct PrivateModeColorPalette: ThemeColourPalette { var layerConfirmation: UIColor = FXColors.Green80 var layerWarning: UIColor = FXColors.Yellow70.withAlphaComponent(0.77) var layerError: UIColor = FXColors.Pink80 + var layerSelectedText: UIColor = FXColors.Violet60 var layerSearch: UIColor = FXColors.Ink90 var layerGradientURL = Gradient(colors: [ FXColors.Ink90.withAlphaComponent(0), diff --git a/BrowserKit/Sources/Common/Theming/ThemeColourPalette.swift b/BrowserKit/Sources/Common/Theming/ThemeColourPalette.swift index 9ecb5da8aecc..c627c495ec95 100644 --- a/BrowserKit/Sources/Common/Theming/ThemeColourPalette.swift +++ b/BrowserKit/Sources/Common/Theming/ThemeColourPalette.swift @@ -27,6 +27,7 @@ public protocol ThemeColourPalette { var layerConfirmation: UIColor { get } var layerWarning: UIColor { get } var layerError: UIColor { get } + var layerSelectedText: UIColor { get } var layerSearch: UIColor { get } var layerGradientURL: Gradient { get } diff --git a/BrowserKit/Sources/ToolbarKit/AddressToolbar/AddressToolbar.swift b/BrowserKit/Sources/ToolbarKit/AddressToolbar/AddressToolbar.swift index 6a9ad4848c3e..96ac8d355525 100644 --- a/BrowserKit/Sources/ToolbarKit/AddressToolbar/AddressToolbar.swift +++ b/BrowserKit/Sources/ToolbarKit/AddressToolbar/AddressToolbar.swift @@ -10,4 +10,6 @@ public protocol AddressToolbar { toolbarDelegate: AddressToolbarDelegate, leadingSpace: CGFloat?, trailingSpace: CGFloat?) + + func setAutocompleteSuggestion(_ suggestion: String?) } diff --git a/BrowserKit/Sources/ToolbarKit/AddressToolbar/BrowserAddressToolbar.swift b/BrowserKit/Sources/ToolbarKit/AddressToolbar/BrowserAddressToolbar.swift index 0bcdfb5b28ae..a072e7dee72e 100644 --- a/BrowserKit/Sources/ToolbarKit/AddressToolbar/BrowserAddressToolbar.swift +++ b/BrowserKit/Sources/ToolbarKit/AddressToolbar/BrowserAddressToolbar.swift @@ -79,6 +79,10 @@ public class BrowserAddressToolbar: UIView, AddressToolbar, ThemeApplicable, Loc layoutIfNeeded() } + public func setAutocompleteSuggestion(_ suggestion: String?) { + locationView.setAutocompleteSuggestion(suggestion) + } + override public func becomeFirstResponder() -> Bool { return locationView.becomeFirstResponder() } @@ -247,6 +251,10 @@ public class BrowserAddressToolbar: UIView, AddressToolbar, ThemeApplicable, Loc } // MARK: - LocationViewDelegate + func locationViewDidRestoreSearchTerm(_ text: String) { + toolbarDelegate?.openSuggestions(searchTerm: text) + } + func locationViewDidEnterText(_ text: String) { toolbarDelegate?.searchSuggestions(searchTerm: text) } @@ -255,7 +263,7 @@ public class BrowserAddressToolbar: UIView, AddressToolbar, ThemeApplicable, Loc toolbarDelegate?.openSuggestions(searchTerm: text.lowercased()) } - func locationViewShouldSearchFor(_ text: String) { + func locationViewDidSubmitText(_ text: String) { guard !text.isEmpty else { return } toolbarDelegate?.openBrowser(searchTerm: text.lowercased()) @@ -265,6 +273,8 @@ public class BrowserAddressToolbar: UIView, AddressToolbar, ThemeApplicable, Loc toolbarDelegate?.addressToolbarAccessibilityActions() } + func locationViewDidCancelEditing() {} + // MARK: - ThemeApplicable public func applyTheme(theme: Theme) { backgroundColor = theme.colors.layer1 diff --git a/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/Callback.swift b/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/Callback.swift new file mode 100644 index 000000000000..416c44b5ed72 --- /dev/null +++ b/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/Callback.swift @@ -0,0 +1,19 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/ + +import Foundation + +// Encapsulate a callback in a way that we can use it with NSTimer. +final class Callback { + private let handler: () -> Void + + init(handler: @escaping () -> Void) { + self.handler = handler + } + + @objc + func go() { + handler() + } +} diff --git a/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationTextField.swift b/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationTextField.swift index f785e9634040..ae874290ec20 100644 --- a/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationTextField.swift +++ b/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationTextField.swift @@ -5,14 +5,67 @@ import Common import UIKit -class LocationTextField: UITextField, ThemeApplicable { +/// Delegate for the text field events. Since LocationTextField owns the UITextFieldDelegate, +/// callers must use this instead. +protocol LocationTextFieldDelegate: AnyObject { + func locationTextField(_ textField: LocationTextField, didEnterText text: String) + func locationTextFieldShouldReturn(_ textField: LocationTextField) -> Bool + func locationTextFieldShouldClear(_ textField: LocationTextField) -> Bool + func locationTextFieldDidCancel(_ textField: LocationTextField) + func locationPasteAndGo(_ textField: LocationTextField) + func locationTextFieldDidBeginEditing(_ textField: UITextField) + func locationTextFieldDidEndEditing(_ textField: UITextField) +} + +class LocationTextField: UITextField, UITextFieldDelegate, ThemeApplicable { private var tintedClearImage: UIImage? private var clearButtonTintColor: UIColor? + var autocompleteDelegate: LocationTextFieldDelegate? + + // This variable is a solution to get the right behaviour for refocusing + // the LocationTextField. The initial transition into Overlay Mode + // doesn't involve the user interacting with LocationTextField. + // Thus, we update shouldApplyCompletion in touchesBegin() to reflect whether + // the highlight is active and then the text field is updated accordingly + // in touchesEnd() (eg. applyCompletion() is called or not) + private var notifyTextChanged: (() -> Void)? + + // The last string used as a replacement in shouldChangeCharactersInRange. + private var lastReplacement: String? + private var hideCursor = false + private var isSettingMarkedText = false + + private let copyShortcutKey = "c" + // MARK: - Init override init(frame: CGRect) { super.init(frame: .zero) + super.addTarget(self, action: #selector(LocationTextField.textDidChange), for: .editingChanged) + + font = UIFont.preferredFont(forTextStyle: .body) + adjustsFontForContentSizeCategory = true clearButtonMode = .whileEditing + keyboardType = .webSearch + autocorrectionType = .no + autocapitalizationType = .none + returnKeyType = .go + delegate = self + + // Disable dragging urls on iPhones because it conflicts with editing the text + if UIDevice.current.userInterfaceIdiom != .pad { + textDragInteraction?.isEnabled = false + } + + notifyTextChanged = debounce(0.1, + action: { + if self.isEditing { + self.autocompleteDelegate?.locationTextField( + self, + didEnterText: self.normalizeString(self.textWithoutSuggestion() ?? "") + ) + } + }) } required init?(coder: NSCoder) { @@ -49,10 +102,207 @@ class LocationTextField: UITextField, ThemeApplicable { } } + override func deleteBackward() { + lastReplacement = nil + hideCursor = false + + guard markedTextRange == nil else { + // If we have an active completion, delete it without deleting any user-typed characters. + removeCompletion() + forceResetCursor() + return + } + + super.deleteBackward() + } + + override func touchesBegan(_ touches: Set, with event: UIEvent?) { + applyCompletion() + super.touchesBegan(touches, with: event) + } + + override open func caretRect(for position: UITextPosition) -> CGRect { + return hideCursor ? CGRect.zero : super.caretRect(for: position) + } + + override open func setMarkedText(_ markedText: String?, selectedRange: NSRange) { + isSettingMarkedText = true + removeCompletion() + super.setMarkedText(markedText, selectedRange: selectedRange) + isSettingMarkedText = false + } + + func setAutocompleteSuggestion(_ suggestion: String?) { + let searchText = text ?? "" + + guard let suggestion = suggestion, isEditing && markedTextRange == nil else { + hideCursor = false + return + } + + let normalized = normalizeString(searchText) + guard suggestion.hasPrefix(normalized) && normalized.count < suggestion.count else { + hideCursor = false + return + } + + let suggestionText = String(suggestion.dropFirst(normalized.count)) + setMarkedText(suggestionText, selectedRange: NSRange()) + + // Only call forceResetCursor() if `hideCursor` changes. + // Because forceResetCursor() auto accept iOS user's text replacement + // (e.g. mu->μ) which makes user unable to type "mu". + if !hideCursor { + hideCursor = true + forceResetCursor() + } + } + // MARK: - ThemeApplicable func applyTheme(theme: Theme) { let colors = theme.colors clearButtonTintColor = colors.iconPrimary - textColor = colors.textPrimary + markedTextStyle = [NSAttributedString.Key.backgroundColor: colors.layerSelectedText] + } + + // MARK: - Private + @objc + private func textDidChange(_ textField: UITextField) { + // When marked text (autocomplete suggestion) is set this method is called + // in this case we don't need to + guard !isSettingMarkedText else { return } + + hideCursor = markedTextRange != nil + removeCompletion() + + let isKeyboardReplacingText = lastReplacement != nil + if isKeyboardReplacingText, markedTextRange == nil { + notifyTextChanged?() + } else { + hideCursor = false + } + } + + /// Commits the completion by setting the text and removing the highlight. + private func applyCompletion() { + // Clear the current completion, then set the text without the attributed style. + let text = (self.text ?? "") + let didRemoveCompletion = removeCompletion() + self.text = text + hideCursor = false + + // Move the cursor to the end of the completion. + if didRemoveCompletion { + selectedTextRange = textRange(from: endOfDocument, to: endOfDocument) + } + } + + /// Removes the autocomplete-highlighted. Returns true if a completion was actually removed + @objc + @discardableResult + private func removeCompletion() -> Bool { + guard markedTextRange != nil else { return false } + + text = textWithoutSuggestion() + return true + } + + private func textWithoutSuggestion() -> String? { + guard let markedTextRange else { return text } + + let location = offset(from: beginningOfDocument, to: markedTextRange.start) + let length = offset(from: markedTextRange.start, to: markedTextRange.end) + let range = NSRange(location: location, length: length) + return (text as NSString?)?.replacingCharacters(in: range, with: "") + } + + @objc + private func clear() { + text = "" + removeCompletion() + autocompleteDelegate?.locationTextField(self, didEnterText: "") + } + + private func normalizeString(_ string: String) -> String { + return string.lowercased().stringByTrimmingLeadingCharactersInSet(CharacterSet.whitespaces) + } + + // Reset the cursor to the end of the text field. + // This forces `caretRect(for position: UITextPosition)` to be called which will decide if we should show the cursor + // This exists because `caretRect(for position: UITextPosition)` is not called after we apply an autocompletion. + private func forceResetCursor() { + selectedTextRange = nil + selectedTextRange = textRange(from: endOfDocument, to: endOfDocument) + } + + // MARK: - UITextFieldDelegate + public func textFieldDidBeginEditing(_ textField: UITextField) { + autocompleteDelegate?.locationTextFieldDidBeginEditing(self) + } + + func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { + applyCompletion() + return true } + + public func textFieldDidEndEditing(_ textField: UITextField) { + lastReplacement = nil + autocompleteDelegate?.locationTextFieldDidEndEditing(self) + } + + // `shouldChangeCharactersInRange` is called before the text changes, and textDidChange is called after. + // Since the text has changed, remove the completion here, and textDidChange will fire the callback to + // get the new autocompletion. + func textField( + _ textField: UITextField, + shouldChangeCharactersIn range: NSRange, + replacementString string: String + ) -> Bool { + // This happens when you begin typing overtop the old highlighted + // text immediately after focusing the text field. We need to trigger + // a `didEnterText` that looks like a `clear()` so that the SearchLoader + // can reset itself since it will only lookup results if the new text is + // longer than the previous text. + if lastReplacement == nil { + autocompleteDelegate?.locationTextField(self, didEnterText: "") + } + + lastReplacement = string + return true + } + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + applyCompletion() + return autocompleteDelegate?.locationTextFieldShouldReturn(self) ?? true + } + + func textFieldShouldClear(_ textField: UITextField) -> Bool { + removeCompletion() + return autocompleteDelegate?.locationTextFieldShouldClear(self) ?? true + } + + // MARK: - Debounce + /** + * Taken from http://stackoverflow.com/questions/27116684/how-can-i-debounce-a-method-call + * Allows creating a block that will fire after a delay. Resets the timer if called again before the delay expires. + **/ + private func debounce(_ delay: TimeInterval, action: @escaping () -> Void) -> () -> Void { + let callback = Callback(handler: action) + var timer: Timer? + + return { + // If calling again, invalidate the last timer. + if let timer = timer { + timer.invalidate() + } + timer = Timer( + timeInterval: delay, + target: callback, + selector: #selector(Callback.go), + userInfo: nil, + repeats: false + ) + RunLoop.current.add(timer!, forMode: RunLoop.Mode.default) + } + } } diff --git a/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationView.swift b/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationView.swift index 4782ae9a3498..6c83ed1e152c 100644 --- a/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationView.swift +++ b/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationView.swift @@ -5,7 +5,7 @@ import UIKit import Common -final class LocationView: UIView, UITextFieldDelegate, ThemeApplicable, AccessibilityActionsSource { +final class LocationView: UIView, LocationTextFieldDelegate, ThemeApplicable, AccessibilityActionsSource { // MARK: - Properties private enum UX { static let horizontalSpace: CGFloat = 8 @@ -74,7 +74,7 @@ final class LocationView: UIView, UITextFieldDelegate, ThemeApplicable, Accessib urlTextField.backgroundColor = .clear urlTextField.font = FXFontStyles.Regular.body.scaledFont() urlTextField.adjustsFontForContentSizeCategory = true - urlTextField.delegate = self + urlTextField.autocompleteDelegate = self urlTextField.accessibilityActionsSource = self } @@ -121,6 +121,10 @@ final class LocationView: UIView, UITextFieldDelegate, ThemeApplicable, Accessib onLongPress = state.onLongPress } + func setAutocompleteSuggestion(_ suggestion: String?) { + urlTextField.setAutocompleteSuggestion(suggestion) + } + // MARK: - Layout override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) @@ -244,13 +248,28 @@ final class LocationView: UIView, UITextFieldDelegate, ThemeApplicable, Accessib // MARK: - `urlTextField` Configuration private func configureURLTextField(_ state: LocationViewState) { - urlTextField.resignFirstResponder() - urlTextField.text = state.url?.absoluteString + if state.isEditing { + urlTextField.text = (state.searchTerm != nil) ? state.searchTerm : state.url?.absoluteString + } else { + urlTextField.text = state.url?.absoluteString + } + urlTextField.placeholder = state.urlTextFieldPlaceholder - urlAbsolutePath = urlTextField.text + urlAbsolutePath = state.url?.absoluteString + + _ = state.isEditing ? becomeFirstResponder() : resignFirstResponder() + + // Start overlay mode & select text when in edit mode with a search term + if state.isEditing, state.shouldSelectSearchTerm { + DispatchQueue.main.async { + self.urlTextField.selectAll(nil) + } + } } private func formatAndTruncateURLTextField() { + guard !urlTextField.isEditing else { return } + let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineBreakMode = .byTruncatingHead @@ -311,20 +330,49 @@ final class LocationView: UIView, UITextFieldDelegate, ThemeApplicable, Accessib } } - // MARK: - UITextFieldDelegate - public func textFieldDidBeginEditing(_ textField: UITextField) { + // MARK: - LocationTextFieldDelegate + func locationTextField(_ textField: LocationTextField, didEnterText text: String) { + delegate?.locationViewDidEnterText(text) + } + + func locationTextFieldShouldReturn(_ textField: LocationTextField) -> Bool { + guard let text = textField.text else { return true } + if !text.trimmingCharacters(in: .whitespaces).isEmpty { + delegate?.locationViewDidSubmitText(text) + textField.resignFirstResponder() + return true + } else { + return false + } + } + + func locationTextFieldShouldClear(_ textField: LocationTextField) -> Bool { + delegate?.locationViewDidEnterText("") + return true + } + + func locationTextFieldDidCancel(_ textField: LocationTextField) { + delegate?.locationViewDidCancelEditing() + } + + func locationPasteAndGo(_ textField: LocationTextField) { + if let pasteboardContents = UIPasteboard.general.string { + delegate?.locationViewDidSubmitText(pasteboardContents) + } + } + + func locationTextFieldDidBeginEditing(_ textField: UITextField) { updateUIForSearchEngineDisplay() DispatchQueue.main.async { [self] in // `attributedText` property is set to nil to remove all formatting and truncation set before. textField.attributedText = nil textField.text = searchTerm != nil ? searchTerm : urlAbsolutePath - textField.selectAll(nil) } delegate?.locationViewDidBeginEditing(textField.text ?? "") } - public func textFieldDidEndEditing(_ textField: UITextField) { + func locationTextFieldDidEndEditing(_ textField: UITextField) { formatAndTruncateURLTextField() if isURLTextFieldEmpty { updateGradient() @@ -333,14 +381,6 @@ final class LocationView: UIView, UITextFieldDelegate, ThemeApplicable, Accessib } } - public func textFieldShouldReturn(_ textField: UITextField) -> Bool { - guard let searchText = textField.text?.lowercased(), !searchText.isEmpty else { return false } - - delegate?.locationViewShouldSearchFor(searchText) - textField.resignFirstResponder() - return true - } - // MARK: - Accessibility private func configureA11y(_ state: LocationViewState) { lockIconButton.accessibilityIdentifier = state.lockIconButtonA11yId diff --git a/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationViewDelegate.swift b/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationViewDelegate.swift index efeb791701f2..e78e8cd8354a 100644 --- a/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationViewDelegate.swift +++ b/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationViewDelegate.swift @@ -21,11 +21,14 @@ protocol LocationViewDelegate: AnyObject { /// Called when the location view should perform a search based on the entered text. /// /// - Parameter text: The text for which the location view should search. - func locationViewShouldSearchFor(_ text: String) + func locationViewDidSubmitText(_ text: String) /// Called when requesting custom accessibility actions to be performed on the location view. /// /// - Returns: An optional array of `UIAccessibilityCustomAction` objects. /// Return `nil` if no custom actions are provided. func locationViewAccessibilityActions() -> [UIAccessibilityCustomAction]? + + /// Called when the user cancels entering text into the location view. + func locationViewDidCancelEditing() } diff --git a/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationViewState.swift b/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationViewState.swift index e0a9d77a90d0..2d5a8bf6810c 100644 --- a/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationViewState.swift +++ b/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationViewState.swift @@ -19,6 +19,8 @@ public struct LocationViewState { public let lockIconImageName: String? public let url: URL? public let searchTerm: String? + public let isEditing: Bool + public let shouldSelectSearchTerm: Bool public var onTapLockIcon: (() -> Void)? public var onLongPress: (() -> Void)? @@ -34,6 +36,8 @@ public struct LocationViewState { lockIconImageName: String?, url: URL?, searchTerm: String?, + isEditing: Bool, + shouldSelectSearchTerm: Bool, onTapLockIcon: (() -> Void)? = nil, onLongPress: (() -> Void)? = nil ) { @@ -48,6 +52,8 @@ public struct LocationViewState { self.lockIconImageName = lockIconImageName self.url = url self.searchTerm = searchTerm + self.isEditing = isEditing + self.shouldSelectSearchTerm = shouldSelectSearchTerm self.onTapLockIcon = onTapLockIcon self.onLongPress = onLongPress } diff --git a/firefox-ios/Client.xcodeproj/project.pbxproj b/firefox-ios/Client.xcodeproj/project.pbxproj index b4c216a3bf98..186d539a48cd 100644 --- a/firefox-ios/Client.xcodeproj/project.pbxproj +++ b/firefox-ios/Client.xcodeproj/project.pbxproj @@ -1518,6 +1518,7 @@ E15DE7C4293A7B0F00B32667 /* PhotonActionSheetTitleHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E15DE7C3293A7B0F00B32667 /* PhotonActionSheetTitleHeaderView.swift */; }; E16258EF2A83BE0800522742 /* FakespotLoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E16258EE2A83BE0800522742 /* FakespotLoadingView.swift */; }; E16941B42C4E4A2E00FF5F4E /* BrowserViewControllerStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E16941B32C4E4A2E00FF5F4E /* BrowserViewControllerStateTests.swift */; }; + E16941B82C5119A200FF5F4E /* Autocompletable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E16941B72C5119A200FF5F4E /* Autocompletable.swift */; }; E169C6E82979CA0E0017B8D7 /* URLMailTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E169C6E72979CA0E0017B8D7 /* URLMailTests.swift */; }; E16AD22C2A8A7AE800F0AA58 /* FakespotHighlightsCardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E16AD22B2A8A7AE800F0AA58 /* FakespotHighlightsCardView.swift */; }; E16C76812ABDC0DB00172DB5 /* FakespotHighlightsCardViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E16C76802ABDC0DB00172DB5 /* FakespotHighlightsCardViewModelTests.swift */; }; @@ -8126,6 +8127,7 @@ E16258EE2A83BE0800522742 /* FakespotLoadingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FakespotLoadingView.swift; sourceTree = ""; }; E1634E1AB9F05311CD6C8C6C /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/AuthenticationManager.strings; sourceTree = ""; }; E16941B32C4E4A2E00FF5F4E /* BrowserViewControllerStateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserViewControllerStateTests.swift; sourceTree = ""; }; + E16941B72C5119A200FF5F4E /* Autocompletable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Autocompletable.swift; sourceTree = ""; }; E169C6E72979CA0E0017B8D7 /* URLMailTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLMailTests.swift; sourceTree = ""; }; E16AD22B2A8A7AE800F0AA58 /* FakespotHighlightsCardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FakespotHighlightsCardView.swift; sourceTree = ""; }; E16C76802ABDC0DB00172DB5 /* FakespotHighlightsCardViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FakespotHighlightsCardViewModelTests.swift; sourceTree = ""; }; @@ -12045,6 +12047,7 @@ E17798972BD6B44B00F6F0EB /* AddressToolbarContainer.swift */, E18CE8D92BDA3F6B00EE2BCD /* NavigationToolbarContainer.swift */, E14792A22C2C5C660058211C /* ToolbarHelper.swift */, + E16941B72C5119A200FF5F4E /* Autocompletable.swift */, ); path = Toolbars; sourceTree = ""; @@ -15050,6 +15053,7 @@ 3BB50E201D627539004B33DF /* HomepageViewController.swift in Sources */, C82A94F3269F68F300624AA7 /* CoreFlaggableFeature.swift in Sources */, F84B22241A09122500AAB793 /* LibraryViewController.swift in Sources */, + E16941B82C5119A200FF5F4E /* Autocompletable.swift in Sources */, 39455F771FC83F430088A22C /* TabEventHandler.swift in Sources */, 8A36BE2929EDBC6900AC1C5C /* ContentContainer.swift in Sources */, 215B458227DA420400E5E800 /* LegacyTabMetadataManager.swift in Sources */, diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+TabToolbarDelegate.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+TabToolbarDelegate.swift index 9b1d8ce717f0..a7082fc687db 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+TabToolbarDelegate.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+TabToolbarDelegate.swift @@ -118,7 +118,9 @@ extension BrowserViewController: TabToolbarDelegate, PhotonActionSheetProtocol { } func dismissUrlBar() { - if !isToolbarRefactorEnabled, urlBar.inOverlayMode { + if isToolbarRefactorEnabled, addressToolbarContainer.inOverlayMode { + addressToolbarContainer.leaveOverlayMode(reason: .finished, shouldCancelLoading: false) + } else if !isToolbarRefactorEnabled, urlBar.inOverlayMode { urlBar.leaveOverlayMode(reason: .finished, shouldCancelLoading: false) } } diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+URLBarDelegate.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+URLBarDelegate.swift index 541384f66650..b4c66477462b 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+URLBarDelegate.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+URLBarDelegate.swift @@ -274,20 +274,11 @@ extension BrowserViewController: URLBarDelegate { } func urlBar(_ urlBar: URLBarView, didEnterText text: String) { - if text.isEmpty { - hideSearchController() - } else { - configureOverlayView() - } + searchSuggestions(searchTerm: text) urlBar.locationTextField?.applyUIMode( isPrivate: tabManager.selectedTab?.isPrivate ?? false, theme: self.currentTheme() ) - searchController?.viewModel.searchQuery = text - searchController?.searchTelemetry?.searchQuery = text - searchController?.searchTelemetry?.clearVisibleResults() - searchLoader?.query = text - searchController?.searchTelemetry?.determineInteractionType() } func urlBar(_ urlBar: URLBarView, didSubmitText text: String) { @@ -322,38 +313,11 @@ extension BrowserViewController: URLBarDelegate { func urlBarDidEnterOverlayMode(_ urlBar: URLBarView) { urlBar.searchEnginesDidUpdate() - guard let profile = profile as? BrowserProfile else { return } - - if .blankPage == NewTabAccessors.getNewTabPage(profile.prefs) { - UIAccessibility.post( - notification: UIAccessibility.Notification.screenChanged, - argument: UIAccessibility.Notification.screenChanged - ) - } else { - if let toast = clipboardBarDisplayHandler?.clipboardToast { - toast.removeFromSuperview() - } - - showEmbeddedHomepage(inline: false, isPrivate: tabManager.selectedTab?.isPrivate ?? false) - } - - urlBar.applyTheme(theme: currentTheme()) + addressToolbarDidEnterOverlayMode(urlBar) } func urlBar(_ urlBar: URLBarView, didLeaveOverlayModeForReason reason: URLBarLeaveOverlayModeReason) { - if searchSessionState == .active { - // This delegate method may be called even if the user isn't - // currently searching, but we only want to update the search - // session state if they are. - searchSessionState = switch reason { - case .finished: .engaged - case .cancelled: .abandoned - } - } - destroySearchController() - updateInContentHomePanel(tabManager.selectedTab?.url as URL?) - - urlBar.applyTheme(theme: currentTheme()) + addressToolbar(urlBar, didLeaveOverlayModeForReason: reason) } func urlBarDidBeginDragInteraction(_ urlBar: URLBarView) { diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift index 75313a8c0553..dd7c5ba7722d 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift @@ -707,9 +707,7 @@ class BrowserViewController: UIViewController, // Awesomebar Location Telemetry SearchBarSettingsViewModel.recordLocationTelemetry(for: isBottomSearchBar ? .bottom : .top) - if !isToolbarRefactorEnabled { - overlayManager.setURLBar(urlBarView: urlBar) - } + overlayManager.setURLBar(urlBarView: isToolbarRefactorEnabled ? addressToolbarContainer : urlBar) // Update theme of already existing views let theme = currentTheme() @@ -1442,11 +1440,11 @@ class BrowserViewController: UIViewController, searchViewModel.searchEngines = profile.searchEngines searchController.searchDelegate = self - if !isToolbarRefactorEnabled { - let searchLoader = SearchLoader(profile: profile, urlBar: urlBar) - searchLoader.addListener(searchViewModel) - self.searchLoader = searchLoader - } + let searchLoader = SearchLoader( + profile: profile, + autocompleteView: isToolbarRefactorEnabled ? addressToolbarContainer : urlBar) + searchLoader.addListener(searchViewModel) + self.searchLoader = searchLoader self.searchController = searchController self.searchSessionState = .active @@ -1836,6 +1834,7 @@ class BrowserViewController: UIViewController, store.dispatch(action) return } + if tab == tabManager.selectedTab, let displayUrl = tab.url?.displayURL, urlBar.currentURL != displayUrl { let searchData = tab.metadataManager?.tabGroupData ?? LegacyTabGroupData() searchData.tabAssociatedNextUrl = displayUrl.absoluteString @@ -1844,13 +1843,11 @@ class BrowserViewController: UIViewController, searchData: searchData, isPrivate: tab.isPrivate) } + urlBar.currentURL = tab.url?.displayURL urlBar.locationView.updateShoppingButtonVisibility(for: tab) let isPage = tab.url?.displayURL?.isWebPage() ?? false - - if !isToolbarRefactorEnabled { - navigationToolbar.updatePageStatus(isPage) - } + navigationToolbar.updatePageStatus(isPage) } func didSubmitSearchText(_ text: String) { @@ -2871,9 +2868,10 @@ class BrowserViewController: UIViewController, afterTab: self.tabManager.selectedTab, isPrivate: isPrivate ) + let toolbar: URLBarViewProtocol = isToolbarRefactorEnabled ? addressToolbarContainer : urlBar // If we are showing toptabs a user can just use the top tab bar // If in overlay mode switching doesnt correctly dismiss the homepanels - guard !isToolbarRefactorEnabled, !topTabsVisible, !self.urlBar.inOverlayMode else { return } + guard !topTabsVisible, !toolbar.inOverlayMode else { return } // We're not showing the top tabs; show a toast to quick switch to the fresh new tab. let viewModel = ButtonToastViewModel(labelText: .ContextMenuButtonToastNewTabOpenedLabelText, buttonText: .ContextMenuButtonToastNewTabOpenedButtonText) @@ -2949,17 +2947,65 @@ class BrowserViewController: UIViewController, } // MARK: - AddressToolbarContainerDelegate - func searchSuggestions(searchTerm: String) {} + func searchSuggestions(searchTerm: String) { + openSuggestions(searchTerm: searchTerm) + searchLoader?.query = searchTerm + } func openBrowser(searchTerm: String) { didSubmitSearchText(searchTerm) } - func openSuggestions(searchTerm: String) {} + func openSuggestions(searchTerm: String) { + if searchTerm.isEmpty { + hideSearchController() + } else { + configureOverlayView() + } + searchController?.viewModel.searchQuery = searchTerm + searchController?.searchTelemetry?.searchQuery = searchTerm + searchController?.searchTelemetry?.clearVisibleResults() + searchController?.searchTelemetry?.determineInteractionType() + } func addressToolbarContainerAccessibilityActions() -> [UIAccessibilityCustomAction]? { locationActionsForURLBar().map { $0.accessibilityCustomAction } } + + func addressToolbarDidEnterOverlayMode(_ view: UIView) { + guard let profile = profile as? BrowserProfile else { return } + + if .blankPage == NewTabAccessors.getNewTabPage(profile.prefs) { + UIAccessibility.post( + notification: UIAccessibility.Notification.screenChanged, + argument: UIAccessibility.Notification.screenChanged + ) + } else { + if let toast = clipboardBarDisplayHandler?.clipboardToast { + toast.removeFromSuperview() + } + + showEmbeddedHomepage(inline: false, isPrivate: tabManager.selectedTab?.isPrivate ?? false) + } + + (view as? ThemeApplicable)?.applyTheme(theme: currentTheme()) + } + + func addressToolbar(_ view: UIView, didLeaveOverlayModeForReason reason: URLBarLeaveOverlayModeReason) { + if searchSessionState == .active { + // This delegate method may be called even if the user isn't + // currently searching, but we only want to update the search + // session state if they are. + searchSessionState = switch reason { + case .finished: .engaged + case .cancelled: .abandoned + } + } + destroySearchController() + updateInContentHomePanel(tabManager.selectedTab?.url as URL?) + + (view as? ThemeApplicable)?.applyTheme(theme: currentTheme()) + } } extension BrowserViewController: ClipboardBarDisplayHandlerDelegate { @@ -3441,8 +3487,9 @@ extension BrowserViewController: TabManagerDelegate { if let tab = selected { updateURLBarDisplayURL(tab) - - if !isToolbarRefactorEnabled, urlBar.inOverlayMode, tab.url?.displayURL != nil { + if isToolbarRefactorEnabled, addressToolbarContainer.inOverlayMode, tab.url?.displayURL != nil { + addressToolbarContainer.leaveOverlayMode(reason: .finished, shouldCancelLoading: false) + } else if !isToolbarRefactorEnabled, urlBar.inOverlayMode, tab.url?.displayURL != nil { urlBar.leaveOverlayMode(reason: .finished, shouldCancelLoading: false) } diff --git a/firefox-ios/Client/Frontend/Browser/SearchLoader.swift b/firefox-ios/Client/Frontend/Browser/SearchLoader.swift index eb6acb105f77..cda2d17e2bad 100644 --- a/firefox-ios/Client/Frontend/Browser/SearchLoader.swift +++ b/firefox-ios/Client/Frontend/Browser/SearchLoader.swift @@ -16,14 +16,14 @@ private let URLBeforePathRegex = try? NSRegularExpression(pattern: "^https?://([ */ class SearchLoader: Loader, SearchViewModel>, FeatureFlaggable { fileprivate let profile: Profile - fileprivate let urlBar: URLBarView + fileprivate let autocompleteView: Autocompletable private let logger: Logger private var skipNextAutocomplete: Bool - init(profile: Profile, urlBar: URLBarView, logger: Logger = DefaultLogger.shared) { + init(profile: Profile, autocompleteView: Autocompletable, logger: Logger = DefaultLogger.shared) { self.profile = profile - self.urlBar = urlBar + self.autocompleteView = autocompleteView self.skipNextAutocomplete = false self.logger = logger @@ -144,7 +144,7 @@ class SearchLoader: Loader, SearchViewModel>, FeatureFlaggable { // First, see if the query matches any URLs from the user's search history. for site in combinedSites { if let completion = self.completionForURL(site.url) { - self.urlBar.setAutocompleteSuggestion(completion) + self.autocompleteView.setAutocompleteSuggestion(completion) return } } @@ -153,7 +153,7 @@ class SearchLoader: Loader, SearchViewModel>, FeatureFlaggable { if let topDomains = self.topDomains { for domain in topDomains { if let completion = self.completionForDomain(domain) { - self.urlBar.setAutocompleteSuggestion(completion) + self.autocompleteView.setAutocompleteSuggestion(completion) return } } diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/AddressToolbarContainer.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/AddressToolbarContainer.swift index 1b10f11047a7..207a5820a837 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/AddressToolbarContainer.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/AddressToolbarContainer.swift @@ -12,6 +12,8 @@ protocol AddressToolbarContainerDelegate: AnyObject { func openBrowser(searchTerm: String) func openSuggestions(searchTerm: String) func addressToolbarContainerAccessibilityActions() -> [UIAccessibilityCustomAction]? + func addressToolbarDidEnterOverlayMode(_ view: UIView) + func addressToolbar(_ view: UIView, didLeaveOverlayModeForReason: URLBarLeaveOverlayModeReason) } final class AddressToolbarContainer: UIView, @@ -20,7 +22,9 @@ final class AddressToolbarContainer: UIView, AlphaDimmable, StoreSubscriber, AddressToolbarDelegate, - MenuHelperURLBarInterface { + MenuHelperURLBarInterface, + Autocompletable, + URLBarViewProtocol { private enum UX { static let compactLeadingEdgeEditing: CGFloat = 8 static let compactLeadingEdgeDisplay: CGFloat = 16 @@ -102,6 +106,10 @@ final class AddressToolbarContainer: UIView, } } + /// Overlay mode is the state where the lock/reader icons are hidden, the home panels are shown, + /// and the Cancel button is visible (allowing the user to leave overlay mode). + var inOverlayMode = false + override init(frame: CGRect) { super.init(frame: .zero) setupLayout() @@ -205,7 +213,11 @@ final class AddressToolbarContainer: UIView, leadingSpace: leadingToolbarSpace, trailingSpace: trailingToolbarSpace) - _ = toolbarState.addressToolbar.isEditing ? becomeFirstResponder() : resignFirstResponder() + // Dismiss overlay mode when not editing to fix overlay mode staying open + // on iPad when switching tabs using top tabs + if !toolbarState.addressToolbar.isEditing { + leaveOverlayMode(reason: .cancelled, shouldCancelLoading: false) + } } } @@ -292,4 +304,31 @@ final class AddressToolbarContainer: UIView, guard let pasteboardContents = UIPasteboard.general.string else { return } delegate?.openBrowser(searchTerm: pasteboardContents) } + + // MARK: - Autocompletable + func setAutocompleteSuggestion(_ suggestion: String?) { + toolbar.setAutocompleteSuggestion(suggestion) + } + + // MARK: - Overlay Mode + func enterOverlayMode(_ locationText: String?, pasted: Bool, search: Bool) { + guard let windowUUID else { return } + inOverlayMode = true + delegate?.addressToolbarDidEnterOverlayMode(self) + + if pasted { + let action = ToolbarAction( + searchTerm: locationText, + windowUUID: windowUUID, + actionType: ToolbarActionType.didPasteSearchTerm + ) + store.dispatch(action) + } + } + + func leaveOverlayMode(reason: URLBarLeaveOverlayModeReason, shouldCancelLoading cancel: Bool) { + _ = toolbar.resignFirstResponder() + inOverlayMode = false + delegate?.addressToolbar(self, didLeaveOverlayModeForReason: reason) + } } diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Autocompletable.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Autocompletable.swift new file mode 100644 index 000000000000..5a7721af3dd2 --- /dev/null +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Autocompletable.swift @@ -0,0 +1,9 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/ + +import Foundation + +protocol Autocompletable: UIView { + func setAutocompleteSuggestion(_ suggestion: String?) +} diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift index c72bbb1e9e69..9490514e17d6 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift @@ -16,10 +16,15 @@ class AddressToolbarContainerModel: Equatable { let searchEngines: SearchEngines let lockIconImageName: String? let url: URL? + let searchTerm: String? + let isEditing: Bool + let shouldSelectSearchTerm: Bool let windowUUID: UUID var addressToolbarState: AddressToolbarState { + let term = searchTerm ?? searchTermFromURL(url, searchEngines: searchEngines) + let locationViewState = LocationViewState( searchEngineImageViewA11yId: AccessibilityIdentifiers.Browser.AddressToolbar.searchEngine, searchEngineImageViewA11yLabel: .AddressToolbar.PrivacyAndSecuritySettingsA11yLabel, @@ -31,7 +36,9 @@ class AddressToolbarContainerModel: Equatable { searchEngineImage: searchEngineImage, lockIconImageName: lockIconImageName, url: url, - searchTerm: searchTermFromURL(url, searchEngines: searchEngines), + searchTerm: term, + isEditing: isEditing, + shouldSelectSearchTerm: shouldSelectSearchTerm, onTapLockIcon: { let action = ToolbarMiddlewareAction(buttonType: .trackingProtection, gestureType: .tap, @@ -67,6 +74,9 @@ class AddressToolbarContainerModel: Equatable { self.searchEngines = profile.searchEngines self.lockIconImageName = state.addressToolbar.lockIconImageName self.url = state.addressToolbar.url + self.searchTerm = state.addressToolbar.searchTerm + self.isEditing = state.addressToolbar.isEditing + self.shouldSelectSearchTerm = state.addressToolbar.shouldSelectSearchTerm } func searchTermFromURL(_ url: URL?, searchEngines: SearchEngines) -> String? { @@ -118,8 +128,10 @@ class AddressToolbarContainerModel: Equatable { lhs.browserActions == rhs.browserActions && lhs.borderPosition == rhs.borderPosition && lhs.searchEngineImage == rhs.searchEngineImage && - lhs.url == rhs.url && lhs.lockIconImageName == rhs.lockIconImageName && + lhs.url == rhs.url && + lhs.searchTerm == rhs.searchTerm && + lhs.isEditing == rhs.isEditing && lhs.windowUUID == rhs.windowUUID } } diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/AddressBarState.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/AddressBarState.swift index c80147280acf..12c9df104ac0 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/AddressBarState.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/AddressBarState.swift @@ -13,8 +13,10 @@ struct AddressBarState: StateType, Equatable { var browserActions: [ToolbarActionState] var borderPosition: AddressToolbarBorderPosition? var url: URL? + var searchTerm: String? var lockIconImageName: String? var isEditing: Bool + var shouldSelectSearchTerm: Bool var isLoading: Bool init(windowUUID: WindowUUID) { @@ -24,8 +26,10 @@ struct AddressBarState: StateType, Equatable { browserActions: [], borderPosition: nil, url: nil, + searchTerm: nil, lockIconImageName: "", isEditing: false, + shouldSelectSearchTerm: true, isLoading: false) } @@ -35,8 +39,10 @@ struct AddressBarState: StateType, Equatable { browserActions: [ToolbarActionState], borderPosition: AddressToolbarBorderPosition?, url: URL?, + searchTerm: String? = nil, lockIconImageName: String?, isEditing: Bool = false, + shouldSelectSearchTerm: Bool = true, isLoading: Bool = false) { self.windowUUID = windowUUID self.navigationActions = navigationActions @@ -44,8 +50,10 @@ struct AddressBarState: StateType, Equatable { self.browserActions = browserActions self.borderPosition = borderPosition self.url = url + self.searchTerm = searchTerm self.lockIconImageName = lockIconImageName self.isEditing = isEditing + self.shouldSelectSearchTerm = shouldSelectSearchTerm self.isLoading = isLoading } @@ -63,7 +71,9 @@ struct AddressBarState: StateType, Equatable { browserActions: model.browserActions ?? state.browserActions, borderPosition: model.borderPosition ?? state.borderPosition, url: model.url, - lockIconImageName: model.lockIconImageName ?? state.lockIconImageName + searchTerm: state.searchTerm, + lockIconImageName: model.lockIconImageName ?? state.lockIconImageName, + isEditing: state.isEditing ) case ToolbarActionType.numberOfTabsChanged: @@ -76,7 +86,9 @@ struct AddressBarState: StateType, Equatable { browserActions: addressToolbarModel.browserActions ?? state.browserActions, borderPosition: state.borderPosition, url: state.url, - lockIconImageName: state.lockIconImageName + searchTerm: state.searchTerm, + lockIconImageName: state.lockIconImageName, + isEditing: state.isEditing ) case ToolbarActionType.addressToolbarActionsDidChange: @@ -89,6 +101,7 @@ struct AddressBarState: StateType, Equatable { browserActions: addressToolbarModel.browserActions ?? state.browserActions, borderPosition: state.borderPosition, url: state.url, + searchTerm: state.searchTerm, lockIconImageName: state.lockIconImageName, isEditing: addressToolbarModel.isEditing ?? state.isEditing ) @@ -103,7 +116,8 @@ struct AddressBarState: StateType, Equatable { browserActions: state.browserActions, borderPosition: state.borderPosition, url: addressToolbarModel.url, - lockIconImageName: addressToolbarModel.lockIconImageName, + searchTerm: nil, + lockIconImageName: addressToolbarModel.lockIconImageName ?? state.lockIconImageName, isEditing: addressToolbarModel.isEditing ?? state.isEditing ) @@ -118,7 +132,9 @@ struct AddressBarState: StateType, Equatable { browserActions: state.browserActions, borderPosition: state.borderPosition, url: state.url, - lockIconImageName: state.lockIconImageName + searchTerm: nil, + lockIconImageName: state.lockIconImageName, + isEditing: state.isEditing ) case ToolbarActionType.showMenuWarningBadge: @@ -131,7 +147,9 @@ struct AddressBarState: StateType, Equatable { browserActions: browserActions ?? state.browserActions, borderPosition: state.borderPosition, url: state.url, - lockIconImageName: state.lockIconImageName + searchTerm: state.searchTerm, + lockIconImageName: state.lockIconImageName, + isEditing: state.isEditing ) case ToolbarActionType.scrollOffsetChanged, @@ -145,7 +163,56 @@ struct AddressBarState: StateType, Equatable { browserActions: state.browserActions, borderPosition: borderPosition, url: state.url, - lockIconImageName: state.lockIconImageName + searchTerm: state.searchTerm, + lockIconImageName: state.lockIconImageName, + isEditing: state.isEditing + ) + + case ToolbarActionType.didPasteSearchTerm: + guard let toolbarAction = action as? ToolbarAction else { return state } + + return AddressBarState( + windowUUID: state.windowUUID, + navigationActions: state.navigationActions, + pageActions: state.pageActions, + browserActions: state.browserActions, + borderPosition: state.borderPosition, + url: state.url, + searchTerm: toolbarAction.searchTerm, + lockIconImageName: state.lockIconImageName, + isEditing: true, + shouldSelectSearchTerm: false + ) + + case ToolbarActionType.didStartEditingUrl: + guard let addressToolbarModel = (action as? ToolbarAction)?.addressToolbarModel else { return state } + + return AddressBarState( + windowUUID: state.windowUUID, + navigationActions: addressToolbarModel.navigationActions ?? state.navigationActions, + pageActions: addressToolbarModel.pageActions ?? state.pageActions, + browserActions: addressToolbarModel.browserActions ?? state.browserActions, + borderPosition: state.borderPosition, + url: state.url, + searchTerm: state.searchTerm, + lockIconImageName: state.lockIconImageName, + isEditing: addressToolbarModel.isEditing ?? state.isEditing, + shouldSelectSearchTerm: state.shouldSelectSearchTerm + ) + + case ToolbarActionType.cancelEdit: + guard let addressToolbarModel = (action as? ToolbarAction)?.addressToolbarModel else { return state } + + return AddressBarState( + windowUUID: state.windowUUID, + navigationActions: addressToolbarModel.navigationActions ?? state.navigationActions, + pageActions: addressToolbarModel.pageActions ?? state.pageActions, + browserActions: addressToolbarModel.browserActions ?? state.browserActions, + borderPosition: state.borderPosition, + url: state.url, + searchTerm: nil, + lockIconImageName: state.lockIconImageName, + isEditing: addressToolbarModel.isEditing ?? state.isEditing ) default: @@ -156,7 +223,9 @@ struct AddressBarState: StateType, Equatable { browserActions: state.browserActions, borderPosition: state.borderPosition, url: state.url, - lockIconImageName: state.lockIconImageName + searchTerm: state.searchTerm, + lockIconImageName: state.lockIconImageName, + isEditing: state.isEditing ) } } diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarAction.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarAction.swift index 8485175b911d..0b72bfce2289 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarAction.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarAction.swift @@ -12,6 +12,7 @@ final class ToolbarAction: Action { let toolbarPosition: AddressToolbarPosition? let numberOfTabs: Int? let url: URL? + let searchTerm: String? let isPrivate: Bool? let badgeImageName: String? let maskImageName: String? @@ -26,6 +27,7 @@ final class ToolbarAction: Action { toolbarPosition: AddressToolbarPosition? = nil, numberOfTabs: Int? = nil, url: URL? = nil, + searchTerm: String? = nil, isPrivate: Bool? = nil, badgeImageName: String? = nil, maskImageName: String? = nil, @@ -41,6 +43,7 @@ final class ToolbarAction: Action { self.toolbarPosition = toolbarPosition self.numberOfTabs = numberOfTabs self.url = url + self.searchTerm = searchTerm self.isPrivate = isPrivate self.badgeImageName = badgeImageName self.maskImageName = maskImageName @@ -62,6 +65,9 @@ enum ToolbarActionType: ActionType { case scrollOffsetChanged case toolbarPositionChanged case showMenuWarningBadge + case didPasteSearchTerm + case didStartEditingUrl + case cancelEdit case readerModeStateChanged } diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift index a3b738371eb9..8614054cd53e 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift @@ -138,13 +138,21 @@ final class ToolbarMiddleware: FeatureFlaggable { updateUrlAndActions(action: action, state: state) case ToolbarMiddlewareActionType.didStartEditingUrl: - updateAddressToolbarNavigationActions(action: action, state: state, isEditing: true) + updateAddressToolbarNavigationActions(action: action, + state: state, + isEditing: true, + dispatchActionType: ToolbarActionType.didStartEditingUrl) - case ToolbarMiddlewareActionType.cancelEdit, - ToolbarMiddlewareActionType.websiteLoadingStateDidChange, + case ToolbarMiddlewareActionType.websiteLoadingStateDidChange, ToolbarMiddlewareActionType.searchEngineDidChange: updateAddressToolbarNavigationActions(action: action, state: state, isEditing: false) + case ToolbarMiddlewareActionType.cancelEdit: + updateAddressToolbarNavigationActions(action: action, + state: state, + isEditing: false, + dispatchActionType: ToolbarActionType.cancelEdit) + case ToolbarMiddlewareActionType.traitCollectionDidChange: updateAddressToolbarNavigationActions(action: action, state: state) @@ -547,9 +555,11 @@ final class ToolbarMiddleware: FeatureFlaggable { return actions } - private func updateAddressToolbarNavigationActions(action: ToolbarMiddlewareAction, - state: AppState, - isEditing: Bool? = nil) { + private func updateAddressToolbarNavigationActions( + action: ToolbarMiddlewareAction, + state: AppState, + isEditing: Bool? = nil, + dispatchActionType: ToolbarActionType = ToolbarActionType.addressToolbarActionsDidChange) { guard let toolbarState = state.screenState(ToolbarState.self, for: .toolbar, window: action.windowUUID), let addressToolbarModel = generateAddressToolbarActions(action: action, state: state, @@ -559,7 +569,7 @@ final class ToolbarMiddleware: FeatureFlaggable { let toolbarAction = ToolbarAction(addressToolbarModel: addressToolbarModel, isShowingTopTabs: action.isShowingTopTabs ?? toolbarState.isShowingTopTabs, windowUUID: action.windowUUID, - actionType: ToolbarActionType.addressToolbarActionsDidChange) + actionType: dispatchActionType) store.dispatch(toolbarAction) } diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarState.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarState.swift index d341669cf1f7..803b4b77bcf5 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarState.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarState.swift @@ -103,7 +103,10 @@ struct ToolbarState: ScreenState, Equatable { ToolbarActionType.addressToolbarActionsDidChange, ToolbarActionType.backForwardButtonStatesChanged, ToolbarActionType.scrollOffsetChanged, - ToolbarActionType.urlDidChange: + ToolbarActionType.urlDidChange, + ToolbarActionType.didPasteSearchTerm, + ToolbarActionType.didStartEditingUrl, + ToolbarActionType.cancelEdit: guard let toolbarAction = action as? ToolbarAction else { return state } return ToolbarState( windowUUID: state.windowUUID, diff --git a/firefox-ios/Client/Frontend/Toolbar+URLBar/URLBarView.swift b/firefox-ios/Client/Frontend/Toolbar+URLBar/URLBarView.swift index 9575237c7c4b..f5db4e4875b1 100644 --- a/firefox-ios/Client/Frontend/Toolbar+URLBar/URLBarView.swift +++ b/firefox-ios/Client/Frontend/Toolbar+URLBar/URLBarView.swift @@ -65,8 +65,13 @@ protocol URLBarViewProtocol { func leaveOverlayMode(reason: URLBarLeaveOverlayModeReason, shouldCancelLoading cancel: Bool) } -class URLBarView: UIView, URLBarViewProtocol, AlphaDimmable, TopBottomInterchangeable, - SearchEngineDelegate, SearchBarLocationProvider { +class URLBarView: UIView, + URLBarViewProtocol, + AlphaDimmable, + TopBottomInterchangeable, + SearchEngineDelegate, + SearchBarLocationProvider, + Autocompletable { // Additional UIAppearance-configurable properties @objc dynamic lazy var locationBorderColor: UIColor = .clear { didSet { diff --git a/firefox-ios/Client/Frontend/Widgets/PhotonActionSheet/PhotonActionSheetProtocol.swift b/firefox-ios/Client/Frontend/Widgets/PhotonActionSheet/PhotonActionSheetProtocol.swift index 25d152fb0283..0a0dbace0814 100644 --- a/firefox-ios/Client/Frontend/Widgets/PhotonActionSheet/PhotonActionSheetProtocol.swift +++ b/firefox-ios/Client/Frontend/Widgets/PhotonActionSheet/PhotonActionSheetProtocol.swift @@ -64,15 +64,8 @@ extension PhotonActionSheetProtocol { if let pasteboardContents = UIPasteboard.general.string { if let urlBar = view as? URLBarView { urlBar.enterOverlayMode(pasteboardContents, pasted: true, search: true) - } else if view is AddressToolbarContainer { - guard let uuid = view.currentWindowUUID else { return } - - let action = ToolbarAction( - url: URL(string: pasteboardContents), - windowUUID: uuid, - actionType: ToolbarActionType.urlDidChange - ) - store.dispatch(action) + } else if let toolbar = view as? AddressToolbarContainer { + toolbar.enterOverlayMode(pasteboardContents, pasted: true, search: true) } } } diff --git a/firefox-ios/Shared/Extensions/String+Extension.swift b/firefox-ios/Shared/Extensions/String+Extension.swift index 96b6b6beee3b..934c06532b5e 100644 --- a/firefox-ios/Shared/Extensions/String+Extension.swift +++ b/firefox-ios/Shared/Extensions/String+Extension.swift @@ -52,16 +52,6 @@ public extension String { return self.removingPercentEncoding } - /// Returns a new string made by removing the leading String characters contained - /// in a given character set. - func stringByTrimmingLeadingCharactersInSet(_ set: CharacterSet) -> String { - var trimmed = self - while trimmed.rangeOfCharacter(from: set)?.lowerBound == trimmed.startIndex { - trimmed.remove(at: trimmed.startIndex) - } - return trimmed - } - /// Adds a newline at the closest space from the middle of a string. /// Example turning "Mark as Read" into "Mark as\n Read" func stringSplitWithNewline() -> String { From 1cb7f5ccd6faec3f07c5ca086e4f881db903f6a2 Mon Sep 17 00:00:00 2001 From: mattreaganmozilla <145381717+mattreaganmozilla@users.noreply.github.com> Date: Fri, 2 Aug 2024 13:42:15 -0700 Subject: [PATCH 039/128] Refactor FXIOS-9732 Cleanup: remove WindowManager.activeWindow (#21380) * [9732] Remove activeWindow from WindowManager, as it is not currently used meaningfully * [9732] Unit test fix * [9732] Fix unit tests --- .../Client/Application/WindowManager.swift | 43 +------------------ .../Middleware/TabManagerMiddleware.swift | 6 +-- .../Frontend/Reader/ReadabilityService.swift | 3 +- .../DownloadContentScript.swift | 3 +- .../ClientTests/Mocks/MockWindowManager.swift | 5 --- .../TabManagement/TabManagerTests.swift | 3 +- .../ClientTests/WindowManagerTests.swift | 24 +++-------- 7 files changed, 13 insertions(+), 74 deletions(-) diff --git a/firefox-ios/Client/Application/WindowManager.swift b/firefox-ios/Client/Application/WindowManager.swift index 4825cf4b8c2b..3ed5d022b560 100644 --- a/firefox-ios/Client/Application/WindowManager.swift +++ b/firefox-ios/Client/Application/WindowManager.swift @@ -24,10 +24,6 @@ enum MultiWindowAction { /// General window management class that provides some basic coordination and /// state management for multiple windows shared across a single running app. protocol WindowManager { - /// The UUID of the active window (there is always at least 1, except in - /// the earliest stages of app startup lifecycle) - var activeWindow: WindowUUID { get set } - /// A collection of all open windows and their related metadata. var windows: [WindowUUID: AppWindowInfo] { get } @@ -98,14 +94,9 @@ final class WindowManagerImplementation: WindowManager, WindowTabsSyncCoordinato // process of initial configuration. private var reservedUUIDs: [WindowUUID] = [] - var activeWindow: WindowUUID { - get { return uuidForActiveWindow() } - set { _activeWindowUUID = newValue } - } private let logger: Logger private let tabDataStore: TabDataStore private let defaults: UserDefaultsInterface - private var _activeWindowUUID: WindowUUID? private let tabSyncCoordinator = WindowTabsSyncCoordinator() private let widgetSimpleTabsCoordinator = WindowSimpleTabsCoordinator() @@ -145,7 +136,7 @@ final class WindowManagerImplementation: WindowManager, WindowTabsSyncCoordinato guard let tabManager = window(for: windowUUID)?.tabManager else { assertionFailure("Tab Manager unavailable for requested UUID: \(windowUUID). This is a client error.") logger.log("No tab manager for window UUID.", level: .fatal, category: .window) - return window(for: activeWindow)?.tabManager ?? windows.first!.value.tabManager! + return windows.first!.value.tabManager! } return tabManager @@ -345,38 +336,6 @@ final class WindowManagerImplementation: WindowManager, WindowTabsSyncCoordinato private func updateWindow(_ info: AppWindowInfo?, for uuid: WindowUUID) { windows[uuid] = info - didUpdateWindow(uuid) - } - - /// Called internally when a window is updated (or removed). - /// - Parameter uuid: the UUID of the window that changed. - private func didUpdateWindow(_ uuid: WindowUUID) { - // Convenience. If the client has successfully configured - // a window and it is the only window in the app, we can - // be sure we automatically set it as the active window. - if windows.count == 1 { - activeWindow = windows.keys.first! - } - } - - private func uuidForActiveWindow() -> WindowUUID { - guard !windows.isEmpty else { - // No app windows. Unsupported state; can't recover gracefully. - fatalError() - } - - guard windows.count > 1 else { - // For apps with only 1 window we can always safely return it as the active window. - return windows.keys.first! - } - - guard let uuid = _activeWindowUUID else { - let message = "App has multiple windows but no active window UUID. This is a client error." - logger.log(message, level: .fatal, category: .window) - assertionFailure(message) - return windows.keys.first! - } - return uuid } private func window(for windowUUID: WindowUUID, createIfNeeded: Bool = false) -> AppWindowInfo? { diff --git a/firefox-ios/Client/Frontend/Browser/Tabs/Middleware/TabManagerMiddleware.swift b/firefox-ios/Client/Frontend/Browser/Tabs/Middleware/TabManagerMiddleware.swift index d1471cc00fa0..cc25c054cd41 100644 --- a/firefox-ios/Client/Frontend/Browser/Tabs/Middleware/TabManagerMiddleware.swift +++ b/firefox-ios/Client/Frontend/Browser/Tabs/Middleware/TabManagerMiddleware.swift @@ -509,10 +509,8 @@ class TabManagerMiddleware { let windowManager: WindowManager = AppContainer.shared.resolve() guard uuid != .unavailable else { assertionFailure() - logger.log("Unexpected or unavailable UUID for TabManager. Returning active window tab manager by default.", - level: .warning, - category: .tabs) - return windowManager.tabManager(for: windowManager.activeWindow) + logger.log("Unexpected or unavailable window UUID for requested TabManager.", level: .fatal, category: .tabs) + return windowManager.allWindowTabManagers().first! } return windowManager.tabManager(for: uuid) diff --git a/firefox-ios/Client/Frontend/Reader/ReadabilityService.swift b/firefox-ios/Client/Frontend/Reader/ReadabilityService.swift index 72c79906751e..7fca23dae9a3 100644 --- a/firefox-ios/Client/Frontend/Reader/ReadabilityService.swift +++ b/firefox-ios/Client/Frontend/Reader/ReadabilityService.swift @@ -49,7 +49,8 @@ class ReadabilityOperation: Operation { // TODO: To resolve profile from DI container let windowManager: WindowManager = AppContainer.shared.resolve() - let tab = Tab(profile: self.profile, configuration: configuration, windowUUID: windowManager.activeWindow) + let defaultUUID = windowManager.windows.first?.key ?? .unavailable + let tab = Tab(profile: self.profile, configuration: configuration, windowUUID: defaultUUID) self.tab = tab tab.createWebview() tab.navigationDelegate = self diff --git a/firefox-ios/Client/Frontend/TabContentsScripts/DownloadContentScript.swift b/firefox-ios/Client/Frontend/TabContentsScripts/DownloadContentScript.swift index 05ab1c79208c..501cf4626b95 100644 --- a/firefox-ios/Client/Frontend/TabContentsScripts/DownloadContentScript.swift +++ b/firefox-ios/Client/Frontend/TabContentsScripts/DownloadContentScript.swift @@ -64,7 +64,8 @@ class DownloadContentScript: TabContentScript { let data = Bytes.decodeBase64(base64String) else { return } - let windowUUID = tab?.windowUUID ?? (AppContainer.shared.resolve() as WindowManager).activeWindow + let windowManager: WindowManager = AppContainer.shared.resolve() + let windowUUID = tab?.windowUUID ?? windowManager.windows.first?.key ?? .unavailable defer { notificationCenter.post(name: .PendingBlobDownloadAddedToQueue, withObject: nil) DownloadContentScript.blobUrlForDownload = nil diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockWindowManager.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockWindowManager.swift index 96dfb2acd201..036ba392fff4 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockWindowManager.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockWindowManager.swift @@ -18,11 +18,6 @@ final class MockWindowManager: WindowManager { // MARK: - WindowManager Protocol - var activeWindow: WindowUUID { - get { wrappedManager.activeWindow } - set { wrappedManager.activeWindow = newValue } - } - var windows: [WindowUUID: AppWindowInfo] { wrappedManager.windows } diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/TabManagement/TabManagerTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/TabManagement/TabManagerTests.swift index 3bd77bd03f36..bd952d909176 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/TabManagement/TabManagerTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/TabManagement/TabManagerTests.swift @@ -26,8 +26,7 @@ class TabManagerTests: XCTestCase { DependencyHelperMock().bootstrapDependencies() LegacyFeatureFlagsManager.shared.initializeDeveloperFeatures(with: MockProfile()) // For this test suite, use a consistent window UUID for all test cases - let windowManager: WindowManager = AppContainer.shared.resolve() - let uuid = windowManager.activeWindow + let uuid: WindowUUID = .XCTestDefaultUUID tabWindowUUID = uuid mockProfile = MockProfile() diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/WindowManagerTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/WindowManagerTests.swift index 5c24a078391e..7ccffe9b65f9 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/WindowManagerTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/WindowManagerTests.swift @@ -35,7 +35,7 @@ class WindowManagerTests: XCTestCase { // Expect 1 app window is now configured XCTAssertEqual(1, subject.windows.count) // Expect that window is now active window - XCTAssertEqual(uuid, subject.activeWindow) + // XCTAssertEqual(uuid, subject.activeWindow) // Expect our previous tab manager is associated with that window XCTAssert(tabManager === subject.tabManager(for: uuid)) XCTAssertEqual(tabManager.windowUUID, uuid) @@ -57,7 +57,7 @@ class WindowManagerTests: XCTestCase { // Expect 2 app windows are now configured XCTAssertEqual(2, subject.windows.count) // Expect that our first window is still the active window - XCTAssertEqual(firstWindowUUID, subject.activeWindow) + // XCTAssertEqual(firstWindowUUID, subject.activeWindow) // Check for expected tab manager references for each window XCTAssert(tabManager === subject.tabManager(for: firstWindowUUID)) @@ -66,20 +66,6 @@ class WindowManagerTests: XCTestCase { XCTAssertEqual(secondTabManager.windowUUID, secondWindowUUID) } - func testChangingActiveWindow() { - var subject = createSubject() - - // Configure two app windows - let firstWindowUUID = tabManager.windowUUID - let secondWindowUUID = secondTabManager.windowUUID - subject.newBrowserWindowConfigured(AppWindowInfo(tabManager: tabManager), uuid: firstWindowUUID) - subject.newBrowserWindowConfigured(AppWindowInfo(tabManager: secondTabManager), uuid: secondWindowUUID) - - XCTAssertEqual(subject.activeWindow, firstWindowUUID) - subject.activeWindow = secondWindowUUID - XCTAssertEqual(subject.activeWindow, secondWindowUUID) - } - func testOpeningMultipleWindowsAndClosingTheFirstWindow() { let subject = createSubject() @@ -90,8 +76,8 @@ class WindowManagerTests: XCTestCase { subject.newBrowserWindowConfigured(AppWindowInfo(tabManager: secondTabManager), uuid: secondWindowUUID) // Check that first window is the active window - XCTAssertEqual(2, subject.windows.count) - XCTAssertEqual(firstWindowUUID, subject.activeWindow) + // XCTAssertEqual(2, subject.windows.count) + // XCTAssertEqual(firstWindowUUID, subject.activeWindow) // Close the first window subject.windowWillClose(uuid: firstWindowUUID) @@ -100,7 +86,7 @@ class WindowManagerTests: XCTestCase { XCTAssertEqual(1, subject.windows.count) XCTAssertEqual(secondWindowUUID, subject.windows.keys.first!) // Check that the second window is now automatically our "active" window - XCTAssertEqual(secondWindowUUID, subject.activeWindow) + // XCTAssertEqual(secondWindowUUID, subject.activeWindow) } func testNextAvailableUUIDWhenNoTabDataIsSaved() { From 27f9550288c8b7c229e9732bcd7cb1b1e23e5b67 Mon Sep 17 00:00:00 2001 From: dicarobinho <61138287+dicarobinho@users.noreply.github.com> Date: Mon, 5 Aug 2024 09:50:03 +0300 Subject: [PATCH 040/128] =?UTF-8?q?Bugfix=20FXIOS-9320=20=E2=81=83=20Copy?= =?UTF-8?q?=20option=20is=20missing=20from=20share=20menu=20(#21189)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * FXIOS-9320 #20649 ⁃ Copy option is missing from share menu Removed duplicated Copy option, when sharing a link --- firefox-ios/Client/Frontend/Share/ShareExtensionHelper.swift | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/firefox-ios/Client/Frontend/Share/ShareExtensionHelper.swift b/firefox-ios/Client/Frontend/Share/ShareExtensionHelper.swift index c183c2370c36..15b9cc74be6e 100644 --- a/firefox-ios/Client/Frontend/Share/ShareExtensionHelper.swift +++ b/firefox-ios/Client/Frontend/Share/ShareExtensionHelper.swift @@ -18,8 +18,7 @@ class ShareExtensionHelper: NSObject, FeatureFlaggable { private let pocketActionExtension = "com.ideashower.ReadItLaterPro.Action-Extension" private var excludingActivities: [UIActivity.ActivityType] { - return [UIActivity.ActivityType.addToReadingList, - UIActivity.ActivityType.copyToPasteboard] + return [UIActivity.ActivityType.addToReadingList] } // Can be a file:// or http(s):// url @@ -104,8 +103,6 @@ class ShareExtensionHelper: NSObject, FeatureFlaggable { private func getApplicationActivities() -> [UIActivity] { var appActivities = [UIActivity]() - let copyLinkActivity = CopyLinkActivity(activityType: .copyLink, url: url) - appActivities.append(copyLinkActivity) let sendToDeviceActivity = SendToDeviceActivity(activityType: .sendToDevice, url: url) appActivities.append(sendToDeviceActivity) From 0d217c1a7e3fb6d291495d91ce7ba03711f7def2 Mon Sep 17 00:00:00 2001 From: dragosb01 <134391433+dragosb01@users.noreply.github.com> Date: Mon, 5 Aug 2024 13:45:32 +0300 Subject: [PATCH 041/128] Update MTE-3264 - downloads tests (#21454) --- .../firefox-ios-tests/Tests/XCUITests/DownloadsTests.swift | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/DownloadsTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/DownloadsTests.swift index 22a23835b382..7ac22aaac235 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/DownloadsTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/DownloadsTests.swift @@ -123,6 +123,8 @@ class DownloadsTests: BaseTestCase { mozWaitForElementToExist(app.tables["DownloadsTable"].staticTexts[testFileNameDownloadPanel]) if #available(iOS 16, *) { mozWaitForElementToExist(app.collectionViews.cells["Copy"]) + mozWaitForElementToExist(app.collectionViews.cells["Add Tags"]) + mozWaitForElementToExist(app.collectionViews.cells["Save to Files"]) } else { mozWaitForElementToExist(app.collectionViews.buttons["Copy"]) } @@ -146,9 +148,10 @@ class DownloadsTests: BaseTestCase { app.tables.cells.staticTexts[testFileNameDownloadPanel].press(forDuration: 2) mozWaitForElementToExist(app.otherElements["ActivityListView"]) mozWaitForElementToExist(app.tables["DownloadsTable"].staticTexts[testFileNameDownloadPanel]) - /* if #available(iOS 16, *) { mozWaitForElementToExist(app.collectionViews.cells["Copy"]) + mozWaitForElementToExist(app.collectionViews.cells["Add Tags"]) + mozWaitForElementToExist(app.collectionViews.cells["Save to Files"]) } else { mozWaitForElementToExist(app.collectionViews.buttons["Copy"]) } @@ -159,7 +162,6 @@ class DownloadsTests: BaseTestCase { // XCUITest does not allow me to click the greyed out portion of the app without the force option. app.buttons["Done"].tap(force: true) } - */ } private func downloadFile(fileName: String, numberOfDownloads: Int) { From 796a266b67541589b364b63a328d46372e035149 Mon Sep 17 00:00:00 2001 From: dicarobinho <61138287+dicarobinho@users.noreply.github.com> Date: Mon, 5 Aug 2024 15:52:33 +0300 Subject: [PATCH 042/128] =?UTF-8?q?Add=20FXIOS-9197=20=E2=81=83=20Enhanced?= =?UTF-8?q?=20Tracking=20Protection=20design=20when=20the=20feature=20is?= =?UTF-8?q?=20turned=20off=20(#21391)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * FXIOS-9197 #20365 ⁃ Enhanced Tracking Protection design when the feature is turned off Did some changes after PR review --- .../TrackingProtectionModel.swift | 13 ++-- .../TrackingProtectionViewController.swift | 62 ++++++++++++++++--- 2 files changed, 64 insertions(+), 11 deletions(-) diff --git a/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionModel.swift b/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionModel.swift index d5212ba61c85..cf9b9d45197a 100644 --- a/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionModel.swift +++ b/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionModel.swift @@ -53,6 +53,10 @@ class TrackingProtectionModel { return url.baseDomain ?? "" } + private var isSecuredAndProtected: Bool { + return connectionSecure && isProtectionEnabled + } + let secureStatusString = String.Menu.EnhancedTrackingProtection.connectionSecureLabel let unsecureStatusString = String.Menu.EnhancedTrackingProtection.connectionUnsecureLabel var connectionStatusString: String { @@ -61,19 +65,20 @@ class TrackingProtectionModel { var connectionDetailsTitle: String { let titleOn = String(format: String.Menu.EnhancedTrackingProtection.onTitle, AppName.shortName.rawValue) - return connectionSecure ? titleOn : .Menu.EnhancedTrackingProtection.offTitle + return isSecuredAndProtected ? titleOn : .Menu.EnhancedTrackingProtection.offTitle } let protectionOnHeaderString = String.Menu.EnhancedTrackingProtection.onHeader - let protectionOffHeaderString = String.Menu.EnhancedTrackingProtection.offHeader + let protectionOffHeaderString = String(format: .Menu.EnhancedTrackingProtection.offHeader, AppName.shortName.rawValue) var connectionDetailsHeader: String { - return connectionSecure ? protectionOnHeaderString : protectionOffHeaderString + return isSecuredAndProtected ? protectionOnHeaderString : protectionOffHeaderString } let protectionOnImage = UIImage(named: ImageIdentifiers.TrackingProtection.protectionOn) let protectionOffImage = UIImage(named: ImageIdentifiers.TrackingProtection.protectionOff) + var isProtectionEnabled = false var connectionDetailsImage: UIImage? { - return connectionSecure ? protectionOnImage : protectionOffImage + return isSecuredAndProtected ? protectionOnImage : protectionOffImage } var isSiteETPEnabled: Bool { diff --git a/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionViewController.swift b/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionViewController.swift index 037015272164..64b5c5f80f5e 100644 --- a/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionViewController.swift +++ b/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionViewController.swift @@ -34,6 +34,8 @@ struct TPMenuUX { static let faviconCornerRadius: CGFloat = 5 static let scrollContentHorizontalPadding: CGFloat = 16 + static let trackersLabelConstraintConstant = 11.0 + static let clearDataButtonCornerRadius: CGFloat = 12 static let clearDataButtonBorderWidth: CGFloat = 1 static let settingsLinkButtonBottomSpacing: CGFloat = 32 @@ -75,6 +77,8 @@ class TrackingProtectionViewController: UIViewController, Themeable, Notifiable, private var foxImageHeightConstraint: NSLayoutConstraint? private var shieldImageHeightConstraint: NSLayoutConstraint? private var lockImageHeightConstraint: NSLayoutConstraint? + private var trackersLabelTopConstraint: NSLayoutConstraint? + private var trackersLabelBottomConstraint: NSLayoutConstraint? private var trackersArrowHeightConstraint: NSLayoutConstraint? private var connectionArrowHeightConstraint: NSLayoutConstraint? @@ -160,6 +164,13 @@ class TrackingProtectionViewController: UIViewController, Themeable, Notifiable, } // MARK: Blocked Trackers View + private var trackersConnectionContainer: UIStackView = .build { stack in + stack.backgroundColor = .clear + stack.distribution = .fillProportionally + stack.alignment = .leading + stack.axis = .vertical + } + private let trackersView: UIView = .build { view in view.backgroundColor = .clear } @@ -319,6 +330,7 @@ class TrackingProtectionViewController: UIViewController, Themeable, Notifiable, override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) updateViewDetails() + updateProtectionViewStatus() applyTheme() } @@ -492,14 +504,21 @@ class TrackingProtectionViewController: UIViewController, Themeable, Notifiable, // MARK: Blocked Trackers Setup private func setupBlockedTrackersView() { trackersView.addSubviews(shieldImage, trackersLabel, trackersDetailArrow, trackersButton, trackersHorizontalLine) - baseView.addSubview(trackersView) - view.bringSubviewToFront(trackersView) + baseView.addSubview(trackersConnectionContainer) + trackersConnectionContainer.addArrangedSubview(trackersView) shieldImageHeightConstraint = shieldImage.heightAnchor.constraint(equalToConstant: TPMenuUX.UX.iconSize) trackersArrowHeightConstraint = trackersDetailArrow.heightAnchor.constraint( equalToConstant: TPMenuUX.UX.iconSize ) + trackersLabelTopConstraint = trackersLabel.topAnchor.constraint( + equalTo: trackersView.topAnchor, + constant: TPMenuUX.UX.trackersLabelConstraintConstant) + trackersLabelBottomConstraint = trackersLabel.bottomAnchor.constraint( + equalTo: trackersView.bottomAnchor, + constant: -TPMenuUX.UX.trackersLabelConstraintConstant) + let blockedTrackersConstraints = [ trackersView.leadingAnchor.constraint( equalTo: view.leadingAnchor, @@ -522,8 +541,6 @@ class TrackingProtectionViewController: UIViewController, Themeable, Notifiable, equalTo: shieldImage.trailingAnchor, constant: TPMenuUX.UX.horizontalMargin ), - trackersLabel.topAnchor.constraint(equalTo: trackersView.topAnchor, constant: 11), - trackersLabel.bottomAnchor.constraint(equalTo: trackersView.bottomAnchor, constant: -11), trackersLabel.trailingAnchor.constraint( equalTo: trackersDetailArrow.leadingAnchor, constant: TPMenuUX.UX.horizontalMargin @@ -549,6 +566,11 @@ class TrackingProtectionViewController: UIViewController, Themeable, Notifiable, trackersView.bottomAnchor.constraint(equalTo: trackersHorizontalLine.bottomAnchor), ] + if let trackersLabelTopConstraint, let trackersLabelBottomConstraint { + constraints.append(trackersLabelTopConstraint) + constraints.append(trackersLabelBottomConstraint) + } + constraints.append(contentsOf: blockedTrackersConstraints) } @@ -556,7 +578,7 @@ class TrackingProtectionViewController: UIViewController, Themeable, Notifiable, private func setupConnectionStatusView() { connectionView.addSubviews(connectionStatusImage, connectionStatusLabel, connectionDetailArrow) connectionView.addSubviews(connectionButton, connectionHorizontalLine) - baseView.addSubviews(connectionView) + trackersConnectionContainer.addArrangedSubview(connectionView) lockImageHeightConstraint = connectionStatusImage.widthAnchor.constraint( equalToConstant: TPMenuUX.UX.iconSize @@ -722,6 +744,7 @@ class TrackingProtectionViewController: UIViewController, Themeable, Notifiable, .withRenderingMode(.alwaysTemplate) connectionStatusLabel.text = viewModel.connectionStatusString toggleSwitch.isOn = viewModel.isSiteETPEnabled + viewModel.isProtectionEnabled = toggleSwitch.isOn toggleLabel.text = .Menu.EnhancedTrackingProtection.switchTitle toggleStatusLabel.text = toggleSwitch.isOn ? .Menu.EnhancedTrackingProtection.switchOnText : .Menu.EnhancedTrackingProtection.switchOffText @@ -811,7 +834,7 @@ class TrackingProtectionViewController: UIViewController, Themeable, Notifiable, func trackingProtectionToggleTapped() { // site is safelisted if site ETP is disabled viewModel.toggleSiteSafelistStatus() - toggleStatusLabel.text = toggleSwitch.isOn ? .ETPOn : .ETPOff + updateProtectionViewStatus() } @objc @@ -863,6 +886,30 @@ class TrackingProtectionViewController: UIViewController, Themeable, Notifiable, func willDismiss() { } + + // MARK: - Update Views + private func updateProtectionViewStatus() { + if toggleSwitch.isOn { + // TODO: FXIOS-9195 #20363 Enhanced Tracking Protection screen status enabled design + toggleStatusLabel.text = .Menu.EnhancedTrackingProtection.switchOnText + trackersView.isHidden = false + trackersLabelTopConstraint?.constant = TPMenuUX.UX.trackersLabelConstraintConstant + trackersLabelBottomConstraint?.constant = -TPMenuUX.UX.trackersLabelConstraintConstant + viewModel.isProtectionEnabled = true + foxStatusImage.image = viewModel.protectionOnImage + connectionDetailsContentView.backgroundColor = currentTheme().colors.layerAccentPrivateNonOpaque + } else { + toggleStatusLabel.text = .Menu.EnhancedTrackingProtection.switchOffText + trackersView.isHidden = true + trackersLabelTopConstraint?.constant = 0 + trackersLabelBottomConstraint?.constant = 0 + viewModel.isProtectionEnabled = false + foxStatusImage.image = viewModel.protectionOffImage + connectionDetailsContentView.backgroundColor = currentTheme().colors.layer3 + } + connectionDetailsTitleLabel.text = viewModel.connectionDetailsTitle + connectionDetailsStatusLabel.text = viewModel.connectionDetailsHeader + } } // MARK: - Themable @@ -876,13 +923,14 @@ extension TrackingProtectionViewController { .tinted(withColor: theme.colors.iconSecondary) closeButton.setImage(buttonImage, for: .normal) connectionDetailsHeaderView.backgroundColor = theme.colors.layer2 - connectionDetailsContentView.backgroundColor = theme.colors.layerAccentPrivateNonOpaque trackersView.backgroundColor = theme.colors.layer2 trackersDetailArrow.tintColor = theme.colors.iconSecondary shieldImage.tintColor = theme.colors.iconPrimary connectionView.backgroundColor = theme.colors.layer2 connectionDetailArrow.tintColor = theme.colors.iconSecondary connectionStatusImage.image = viewModel.getConnectionStatusImage(themeType: theme.type) + connectionDetailsContentView.backgroundColor = toggleSwitch.isOn ? + currentTheme().colors.layerAccentPrivateNonOpaque : theme.colors.layer3 headerContainer.tintColor = theme.colors.layer2 siteDomainLabel.textColor = theme.colors.textSecondary siteDisplayTitleLabel.textColor = theme.colors.textPrimary From 2d67ddfc6409c5724e5a29f3539af99d5f74f3db Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 5 Aug 2024 08:55:05 -0400 Subject: [PATCH 043/128] Localize [v130] String import 2024-08-05 (#21455) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- firefox-ios/Client.xcodeproj/project.pbxproj | 46 ++++++ .../br.lproj/EditAddress.strings | 24 +++ .../EnhancedTrackingProtection.strings | 3 + .../br.lproj/Microsurvey.strings | 6 + .../Supporting Files/br.lproj/Toolbar.strings | 3 + .../bs.lproj/Microsurvey.strings | 3 + .../Supporting Files/bs.lproj/Toolbar.strings | 3 + .../ca.lproj/EditAddress.strings | 3 + .../ca.lproj/Microsurvey.strings | 3 + .../Supporting Files/ca.lproj/Toolbar.strings | 6 + .../cs.lproj/Microsurvey.strings | 3 + .../Supporting Files/cs.lproj/Toolbar.strings | 3 + .../cy.lproj/Microsurvey.strings | 3 + .../Supporting Files/cy.lproj/Toolbar.strings | 6 + .../de.lproj/Microsurvey.strings | 3 + .../Supporting Files/de.lproj/Toolbar.strings | 3 + .../Supporting Files/dsb.lproj/Alerts.strings | 2 +- .../dsb.lproj/Microsurvey.strings | 3 + .../dsb.lproj/TabsTray.strings | 2 +- .../dsb.lproj/Toolbar.strings | 3 + .../el.lproj/Microsurvey.strings | 3 + .../Supporting Files/el.lproj/Toolbar.strings | 3 + .../en-GB.lproj/Microsurvey.strings | 3 + .../en-GB.lproj/Toolbar.strings | 3 + .../en-US.lproj/Microsurvey.strings | 3 + .../en-US.lproj/Toolbar.strings | 3 + .../es-AR.lproj/Microsurvey.strings | 3 + .../es-AR.lproj/Toolbar.strings | 3 + .../es-CL.lproj/Microsurvey.strings | 3 + .../es-CL.lproj/Toolbar.strings | 3 + .../Supporting Files/fi.lproj/Toolbar.strings | 3 + .../fr.lproj/Microsurvey.strings | 3 + .../Supporting Files/fr.lproj/Toolbar.strings | 3 + .../he.lproj/Microsurvey.strings | 3 + .../Supporting Files/he.lproj/Toolbar.strings | 3 + .../hr.lproj/ActivityStream.strings | 6 + .../hr.lproj/AddressToolbar.strings | 12 ++ .../Supporting Files/hr.lproj/Alert.strings | 6 + .../Supporting Files/hr.lproj/Alerts.strings | 15 ++ .../hr.lproj/BiometricAuthentication.strings | 6 + .../hr.lproj/BottomSheet.strings | 3 + .../hr.lproj/CredentialProvider.strings | 3 + .../hr.lproj/CustomizeFirefoxHome.strings | 3 + .../hr.lproj/Edit Card.strings | 2 +- .../hr.lproj/EditAddress.strings | 141 ++++++++++++++++++ .../hr.lproj/EditCard.strings | 6 + .../hr.lproj/EngagementNotification.strings | 6 + .../EnhancedTrackingProtection.strings | 46 ++++++ .../hr.lproj/FirefoxHomepage.strings | 6 + .../hr.lproj/FirefoxLogins.strings | 18 +++ .../hr.lproj/FirefoxSync.strings | 8 +- .../Supporting Files/hr.lproj/Footer.strings | 3 + .../hr.lproj/JumpBackIn.strings | 6 + .../hr.lproj/KeyboardAccessory.strings | 6 + .../hr.lproj/LoginsHelper.strings | 9 ++ .../hr.lproj/Microsurvey.strings | 69 +++++++++ .../hr.lproj/Notification.strings | 3 + .../hr.lproj/Onboarding.strings | 96 ++++++++++++ .../hr.lproj/Settings.strings | 108 ++++++++++++++ .../hr.lproj/Shopping.strings | 126 ++++++++++++++++ .../hr.lproj/SnackBar.strings | 3 + .../hr.lproj/TabLocation.strings | 36 +++++ .../hr.lproj/TabsTray.strings | 6 + .../Supporting Files/hr.lproj/Toolbar.strings | 3 + .../hr.lproj/UpdateCard.strings | 9 ++ .../hr.lproj/ZoomPageBar.strings | 12 ++ .../hsb.lproj/Microsurvey.strings | 3 + .../hsb.lproj/Toolbar.strings | 3 + .../hy-AM.lproj/Microsurvey.strings | 3 + .../hy-AM.lproj/Toolbar.strings | 3 + .../ia.lproj/Microsurvey.strings | 3 + .../Supporting Files/ia.lproj/Toolbar.strings | 3 + .../is.lproj/Microsurvey.strings | 3 + .../Supporting Files/is.lproj/Toolbar.strings | 3 + .../it.lproj/Microsurvey.strings | 3 + .../Supporting Files/it.lproj/Toolbar.strings | 3 + .../ja.lproj/Microsurvey.strings | 3 + .../Supporting Files/ja.lproj/Toolbar.strings | 3 + .../kk.lproj/Microsurvey.strings | 3 + .../Supporting Files/kk.lproj/Toolbar.strings | 3 + .../ko.lproj/Microsurvey.strings | 3 + .../Supporting Files/ko.lproj/Toolbar.strings | 3 + .../nb.lproj/EditAddress.strings | 15 ++ .../EnhancedTrackingProtection.strings | 12 ++ .../nb.lproj/Microsurvey.strings | 9 ++ .../nb.lproj/PasswordAutofill.strings | 3 + .../nb.lproj/ScanQRCode.strings | 9 ++ .../Supporting Files/nb.lproj/Toolbar.strings | 6 + .../nl.lproj/Microsurvey.strings | 3 + .../Supporting Files/nl.lproj/Toolbar.strings | 3 + .../nn.lproj/Microsurvey.strings | 3 + .../Supporting Files/nn.lproj/Toolbar.strings | 3 + .../pa-IN.lproj/Microsurvey.strings | 3 + .../pa-IN.lproj/Toolbar.strings | 3 + .../pt-BR.lproj/Microsurvey.strings | 3 + .../pt-BR.lproj/Toolbar.strings | 3 + .../pt-PT.lproj/Microsurvey.strings | 3 + .../pt-PT.lproj/Toolbar.strings | 3 + .../ru.lproj/Microsurvey.strings | 3 + .../Supporting Files/ru.lproj/Toolbar.strings | 3 + .../sk.lproj/Microsurvey.strings | 3 + .../Supporting Files/sk.lproj/Toolbar.strings | 3 + .../sv.lproj/Microsurvey.strings | 3 + .../Supporting Files/sv.lproj/Toolbar.strings | 3 + .../tr.lproj/Microsurvey.strings | 3 + .../Supporting Files/tr.lproj/Toolbar.strings | 3 + .../ug.lproj/Microsurvey.strings | 3 + .../Supporting Files/ug.lproj/Toolbar.strings | 3 + .../vi.lproj/Microsurvey.strings | 3 + .../Supporting Files/vi.lproj/Toolbar.strings | 3 + .../zh-CN.lproj/Footer.strings | 2 +- .../zh-TW.lproj/Microsurvey.strings | 3 + .../zh-TW.lproj/Toolbar.strings | 3 + .../Shared/dsb.lproj/Localizable.strings | 2 +- firefox-ios/Shared/dsb.lproj/Today.strings | 4 +- .../Shared/hr.lproj/Localizable.strings | 33 ++++ .../Shared/hr.lproj/LoginManager.strings | 18 +++ firefox-ios/Shared/hr.lproj/Menu.strings | 6 + firefox-ios/Shared/hr.lproj/Search.strings | 3 + .../zh-CN.lproj/PrivateBrowsing.strings | 2 +- 120 files changed, 1193 insertions(+), 9 deletions(-) create mode 100644 firefox-ios/Shared/Supporting Files/br.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/ca.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/cy.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/hr.lproj/ActivityStream.strings create mode 100644 firefox-ios/Shared/Supporting Files/hr.lproj/AddressToolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/hr.lproj/BiometricAuthentication.strings create mode 100644 firefox-ios/Shared/Supporting Files/hr.lproj/BottomSheet.strings create mode 100644 firefox-ios/Shared/Supporting Files/hr.lproj/CredentialProvider.strings create mode 100644 firefox-ios/Shared/Supporting Files/hr.lproj/EditAddress.strings create mode 100644 firefox-ios/Shared/Supporting Files/hr.lproj/EnhancedTrackingProtection.strings create mode 100644 firefox-ios/Shared/Supporting Files/hr.lproj/FirefoxHomepage.strings create mode 100644 firefox-ios/Shared/Supporting Files/hr.lproj/FirefoxLogins.strings create mode 100644 firefox-ios/Shared/Supporting Files/hr.lproj/JumpBackIn.strings create mode 100644 firefox-ios/Shared/Supporting Files/hr.lproj/KeyboardAccessory.strings create mode 100644 firefox-ios/Shared/Supporting Files/hr.lproj/LoginsHelper.strings create mode 100644 firefox-ios/Shared/Supporting Files/hr.lproj/Microsurvey.strings create mode 100644 firefox-ios/Shared/Supporting Files/hr.lproj/Notification.strings create mode 100644 firefox-ios/Shared/Supporting Files/hr.lproj/Shopping.strings create mode 100644 firefox-ios/Shared/Supporting Files/hr.lproj/TabLocation.strings create mode 100644 firefox-ios/Shared/Supporting Files/hr.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/hr.lproj/ZoomPageBar.strings create mode 100644 firefox-ios/Shared/Supporting Files/nb.lproj/ScanQRCode.strings create mode 100644 firefox-ios/Shared/Supporting Files/nb.lproj/Toolbar.strings diff --git a/firefox-ios/Client.xcodeproj/project.pbxproj b/firefox-ios/Client.xcodeproj/project.pbxproj index 186d539a48cd..b5811336f3d8 100644 --- a/firefox-ios/Client.xcodeproj/project.pbxproj +++ b/firefox-ios/Client.xcodeproj/project.pbxproj @@ -2950,6 +2950,7 @@ 43045C9C29E428A800B5BD9B /* si */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = si; path = si.lproj/ResearchSurface.strings; sourceTree = ""; }; 43045C9D29E428A800B5BD9B /* si */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = si; path = si.lproj/Settings.strings; sourceTree = ""; }; 43045C9E29E428A800B5BD9B /* si */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = si; path = si.lproj/SnackBar.strings; sourceTree = ""; }; + 4304EDF32C60EABA00F3C9DE /* cy */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cy; path = cy.lproj/Toolbar.strings; sourceTree = ""; }; 43050A002ACAE09E002684A4 /* pa-IN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pa-IN"; path = "pa-IN.lproj/Share.strings"; sourceTree = ""; }; 430514F52AD4195A00188114 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/Share.strings; sourceTree = ""; }; 430514F62AD4195A00188114 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/TabLocation.strings; sourceTree = ""; }; @@ -3563,6 +3564,8 @@ 433D51742C3C0478005D19E3 /* ug */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ug; path = ug.lproj/EditAddress.strings; sourceTree = ""; }; 433D51752C3C0478005D19E3 /* ug */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ug; path = ug.lproj/ScanQRCode.strings; sourceTree = ""; }; 433D53CB2B0B798700F5786C /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/FirefoxHomepage.strings; sourceTree = ""; }; + 433D64C62C60EE1100CEC389 /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/ScanQRCode.strings; sourceTree = ""; }; + 433D64C72C60EE1100CEC389 /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/Toolbar.strings; sourceTree = ""; }; 433DD5FB2AEFC6EB00C80D13 /* eu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eu; path = eu.lproj/Shopping.strings; sourceTree = ""; }; 433E0DEC26FCE37C00B78CC5 /* ne-NP */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ne-NP"; path = "ne-NP.lproj/Default Browser.strings"; sourceTree = ""; }; 433E11402A124A2C00B4C650 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/FirefoxSync.strings; sourceTree = ""; }; @@ -4158,6 +4161,7 @@ 4374AB3C2C205468004C030B /* su */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = su; path = su.lproj/QRCode.strings; sourceTree = ""; }; 4374AC0128B39AE700BE4998 /* bo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bo; path = bo.lproj/BookmarkPanel.strings; sourceTree = ""; }; 4374C6AF2AEFC75A00907BB4 /* hsb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hsb; path = hsb.lproj/Shopping.strings; sourceTree = ""; }; + 437511122C60EA6E001E649A /* br */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = br; path = br.lproj/Toolbar.strings; sourceTree = ""; }; 437579372B0B773B005F2178 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/FirefoxHomepage.strings; sourceTree = ""; }; 437582642BE8F37A006F43C6 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Microsurvey.strings; sourceTree = ""; }; 43758DC32B0B78E300DA928C /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/FirefoxHomepage.strings; sourceTree = ""; }; @@ -4473,6 +4477,7 @@ 43914B522B4C115A0028781C /* nn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nn; path = nn.lproj/ContextualHints.strings; sourceTree = ""; }; 43914B532B4C115B0028781C /* nn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nn; path = nn.lproj/Credentials.strings; sourceTree = ""; }; 43914B542B4C115B0028781C /* nn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nn; path = nn.lproj/FirefoxHomepage.strings; sourceTree = ""; }; + 4391631F2C60EA8C00263662 /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/Toolbar.strings; sourceTree = ""; }; 43922AF72BCD4442000D4B12 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/BottomSheet.strings; sourceTree = ""; }; 4392732B2A6E95B50014E253 /* su */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = su; path = su.lproj/Alert.strings; sourceTree = ""; }; 4392732C2A6E95B50014E253 /* su */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = su; path = su.lproj/DisplayCard.strings; sourceTree = ""; }; @@ -5326,6 +5331,24 @@ 43DF9459292258C300590FE3 /* be */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = be; path = be.lproj/SearchHeaderTitle.strings; sourceTree = ""; }; 43DF990828B39FE2009A5541 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/JumpBackIn.strings; sourceTree = ""; }; 43DF990928B39FE2009A5541 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/ToolbarLocation.strings; sourceTree = ""; }; + 43E0BE322C60EC4B004FED65 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/ActivityStream.strings; sourceTree = ""; }; + 43E0BE332C60EC4B004FED65 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/AddressToolbar.strings; sourceTree = ""; }; + 43E0BE342C60EC4B004FED65 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/BiometricAuthentication.strings; sourceTree = ""; }; + 43E0BE352C60EC4B004FED65 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/BottomSheet.strings; sourceTree = ""; }; + 43E0BE362C60EC4B004FED65 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/CredentialProvider.strings; sourceTree = ""; }; + 43E0BE372C60EC4B004FED65 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/EditAddress.strings; sourceTree = ""; }; + 43E0BE382C60EC4B004FED65 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/EnhancedTrackingProtection.strings; sourceTree = ""; }; + 43E0BE392C60EC4B004FED65 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/FirefoxHomepage.strings; sourceTree = ""; }; + 43E0BE3A2C60EC4C004FED65 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/FirefoxLogins.strings; sourceTree = ""; }; + 43E0BE3B2C60EC4C004FED65 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/JumpBackIn.strings; sourceTree = ""; }; + 43E0BE3C2C60EC4C004FED65 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/KeyboardAccessory.strings; sourceTree = ""; }; + 43E0BE3D2C60EC4C004FED65 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/LoginsHelper.strings; sourceTree = ""; }; + 43E0BE3E2C60EC4C004FED65 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/Microsurvey.strings; sourceTree = ""; }; + 43E0BE3F2C60EC4C004FED65 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/Notification.strings; sourceTree = ""; }; + 43E0BE402C60EC4C004FED65 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/Shopping.strings; sourceTree = ""; }; + 43E0BE412C60EC4C004FED65 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/TabLocation.strings; sourceTree = ""; }; + 43E0BE422C60EC4C004FED65 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/Toolbar.strings; sourceTree = ""; }; + 43E0BE432C60EC4C004FED65 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/ZoomPageBar.strings; sourceTree = ""; }; 43E0E9D728B39CA3002E264A /* gl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = gl; path = gl.lproj/BookmarkPanel.strings; sourceTree = ""; }; 43E129A929BA6A480084C419 /* ia */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ia; path = ia.lproj/EngagementNotification.strings; sourceTree = ""; }; 43E129AA29BA6A480084C419 /* ia */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ia; path = ia.lproj/Onboarding.strings; sourceTree = ""; }; @@ -16492,6 +16515,7 @@ 43EB5FAC2B2728080063D23E /* ug */, 439E22242C04A5620061A923 /* su */, 4300B0DF2C57B06E00F609C1 /* es-MX */, + 43E0BE412C60EC4C004FED65 /* hr */, ); name = TabLocation.strings; sourceTree = ""; @@ -16554,6 +16578,7 @@ 439E22202C04A5610061A923 /* su */, 43CCB4D42C32C527001F2EBB /* ca */, 43EC79AA2C3C00BF00519D98 /* es-MX */, + 43E0BE3C2C60EC4C004FED65 /* hr */, ); name = KeyboardAccessory.strings; sourceTree = ""; @@ -16622,6 +16647,7 @@ 43D2F8B72A8A45570095D4EB /* su */, 4364EA842B1DE9FA003A1240 /* bs */, 43EB5F982B2728070063D23E /* ug */, + 43E0BE342C60EC4B004FED65 /* hr */, ); name = BiometricAuthentication.strings; sourceTree = ""; @@ -16756,6 +16782,7 @@ 43EB5FAA2B2728080063D23E /* ug */, 4357B4942C168FF1003518CF /* su */, 43EC79AE2C3C00BF00519D98 /* es-MX */, + 43E0BE402C60EC4C004FED65 /* hr */, ); name = Shopping.strings; sourceTree = ""; @@ -16825,6 +16852,7 @@ 4397616F2A0BCB850062C60C /* gl */, 4364EA8F2B1DE9FB003A1240 /* bs */, 43EB5FA12B2728080063D23E /* ug */, + 43E0BE3B2C60EC4C004FED65 /* hr */, ); name = JumpBackIn.strings; sourceTree = ""; @@ -16959,6 +16987,7 @@ 432792682BB192FD001707B5 /* en-CA */, 439E221E2C04A5610061A923 /* su */, 43B890FF2C32C60B0049F033 /* es-MX */, + 43E0BE392C60EC4B004FED65 /* hr */, ); name = FirefoxHomepage.strings; sourceTree = ""; @@ -17023,6 +17052,7 @@ 43CCB4CE2C32C526001F2EBB /* ca */, 43B890F92C32C60A0049F033 /* es-MX */, 4361DF292C453DB200CE1295 /* sat-Olck */, + 43E0BE352C60EC4B004FED65 /* hr */, ); name = BottomSheet.strings; sourceTree = ""; @@ -17296,6 +17326,7 @@ 4375F0E12C453BC4001F3A55 /* hu */, 4300B0D92C57B06E00F609C1 /* es-MX */, 437E67412C57B4AB00A8791A /* th */, + 43E0BE322C60EC4B004FED65 /* hr */, ); name = ActivityStream.strings; sourceTree = ""; @@ -17356,6 +17387,7 @@ 431B95F72C453A89003B17BF /* en-CA */, 4375F0E22C453BC4001F3A55 /* hu */, 437E67422C57B4AB00A8791A /* th */, + 43E0BE332C60EC4B004FED65 /* hr */, ); name = AddressToolbar.strings; sourceTree = ""; @@ -17417,6 +17449,7 @@ 4375F0E42C453BC4001F3A55 /* hu */, 4300B0DB2C57B06E00F609C1 /* es-MX */, 437E67442C57B4AB00A8791A /* th */, + 43E0BE382C60EC4B004FED65 /* hr */, ); name = EnhancedTrackingProtection.strings; sourceTree = ""; @@ -17753,6 +17786,7 @@ 4364EA902B1DE9FB003A1240 /* bs */, 43EB5FA22B2728080063D23E /* ug */, 439E22232C04A5620061A923 /* su */, + 43E0BE3F2C60EC4C004FED65 /* hr */, ); name = Notification.strings; sourceTree = ""; @@ -17821,6 +17855,7 @@ 439CB65F2AE68F1F00A19D54 /* sq */, 4364EA9F2B1DE9FB003A1240 /* bs */, 43EB5FB12B2728090063D23E /* ug */, + 43E0BE432C60EC4C004FED65 /* hr */, ); name = ZoomPageBar.strings; sourceTree = ""; @@ -18222,6 +18257,7 @@ 43CCB4D02C32C526001F2EBB /* ca */, 43B890FB2C32C60A0049F033 /* es-MX */, 4361DF2B2C453DB200CE1295 /* sat-Olck */, + 43E0BE362C60EC4B004FED65 /* hr */, ); name = CredentialProvider.strings; sourceTree = ""; @@ -18350,6 +18386,7 @@ 439E221F2C04A5610061A923 /* su */, 43CCB4D32C32C527001F2EBB /* ca */, 43B891002C32C60B0049F033 /* es-MX */, + 43E0BE3A2C60EC4C004FED65 /* hr */, ); name = FirefoxLogins.strings; sourceTree = ""; @@ -18415,6 +18452,7 @@ 4300B70C2C298D9C0099DEEC /* lo */, 43CCB4D52C32C527001F2EBB /* ca */, 43B891022C32C60B0049F033 /* es-MX */, + 43E0BE3D2C60EC4C004FED65 /* hr */, ); name = LoginsHelper.strings; sourceTree = ""; @@ -18532,6 +18570,7 @@ 438B16432C57B39C007BD1A3 /* pl */, 43B3869C2C57B446007728B6 /* sl */, 437E67462C57B4AB00A8791A /* th */, + 433D64C62C60EE1100CEC389 /* nb */, ); name = ScanQRCode.strings; sourceTree = ""; @@ -18594,6 +18633,7 @@ 43B68F092C1690270012DAE2 /* th */, 43CCB4D62C32C527001F2EBB /* ca */, 4300B0DC2C57B06E00F609C1 /* es-MX */, + 43E0BE3E2C60EC4C004FED65 /* hr */, ); name = Microsurvey.strings; sourceTree = ""; @@ -18794,6 +18834,7 @@ 433020F82C57B40700AF5EE2 /* sat-Olck */, 4396C29A2C57B42700837488 /* si */, 437E67432C57B4AB00A8791A /* th */, + 43E0BE372C60EC4B004FED65 /* hr */, ); name = EditAddress.strings; sourceTree = ""; @@ -19049,6 +19090,11 @@ 43571C312C57B52200A2DD89 /* vi */, 43BFE5BA2C57B54100CFB4C5 /* zh-CN */, 43CE9F3D2C57B5500069B3AF /* zh-TW */, + 437511122C60EA6E001E649A /* br */, + 4391631F2C60EA8C00263662 /* ca */, + 4304EDF32C60EABA00F3C9DE /* cy */, + 43E0BE422C60EC4C004FED65 /* hr */, + 433D64C72C60EE1100CEC389 /* nb */, ); name = Toolbar.strings; sourceTree = ""; diff --git a/firefox-ios/Shared/Supporting Files/br.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/br.lproj/EditAddress.strings index fb3053dfe7cb..22792a67b605 100644 --- a/firefox-ios/Shared/Supporting Files/br.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/br.lproj/EditAddress.strings @@ -112,3 +112,27 @@ /* Button label for closing the view where user can view their address info. */ "Addresses.EditAddress.CloseNavBarButtonLabel.v129" = "Serriñ"; +/* Button label for editing the address details shown in the form. */ +"Addresses.EditAddress.EditNavBarButtonLabel.v129" = "Aozañ"; + +/* Title for button that offers the user the option to remove an address. */ +"Addresses.EditAddress.RemoveAddressButtonTitle.v129" = "Dilemel ar chomlec’h"; + +/* Toast message confirming that an address has been successfully removed. */ +"Addresses.Toast.AddressRemovedConfirmation.v129" = "Chomlec’h dilamet"; + +/* Toast message confirming that an address has been successfully saved. */ +"Addresses.Toast.AddressSavedConfirmation.v129" = "Chomlec’h enrollet"; + +/* Toast message indicating an error occurred while trying to save an address. */ +"Addresses.Toast.AddressSaveError.v129" = "N’haller ket enrollañ ar chomlec’h"; + +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "N’haller ket dilemel ar chomlec’h"; + +/* Suggestion to try again after an error occurred while trying to save an address. */ +"Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Klask en-dro"; + +/* Toast message confirming that an address has been successfully updated. */ +"Addresses.Toast.AddressUpdatedConfirmation.v129" = "Titouroù ar chomlec’h hizivaet"; + diff --git a/firefox-ios/Shared/Supporting Files/br.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/br.lproj/EnhancedTrackingProtection.strings index baadd7c377bb..2756b91f74d0 100644 --- a/firefox-ios/Shared/Supporting Files/br.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/br.lproj/EnhancedTrackingProtection.strings @@ -13,3 +13,6 @@ /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ "Menu.EnhancedTrackingProtection.Details.Verifier.v128" = "Gwiriet gant %@"; +/* Title for the switch to enable/disable enhanced tracking protection inside the menu. */ +"Menu.EnhancedTrackingProtection.Switch.Title.v128" = "Gwarez araokaet a-enep d’an heulierien"; + diff --git a/firefox-ios/Shared/Supporting Files/br.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/br.lproj/Microsurvey.strings index 2006e81e9dc8..3cd23de664b8 100644 --- a/firefox-ios/Shared/Supporting Files/br.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/br.lproj/Microsurvey.strings @@ -22,9 +22,15 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the logo image that appears on the bottom sheet that informs the user that it is coming from the app specifically. Placeholder is for the app name. */ "Microsurvey.Survey.LogoImage.AccessibilityLabel.v129" = "Logo %@"; +/* On the microsurvey, this is the title for one of the options that the user can select to answer the survey. */ +"Microsurvey.Survey.Options.LikertScaleOption2.v127" = "Plijet"; + /* On the microsurvey, this is the title for one of the options that the user can select to answer the survey. */ "Microsurvey.Survey.Options.LikertScaleOption3.v127" = "Ali ebet"; +/* On the microsurvey, this is the title for one of the options that the user can select to answer the survey. */ +"Microsurvey.Survey.Options.LikertScaleOption4.v127" = "Displijet"; + /* On the microsurvey, this is the title for one of the options that the user can select to answer the survey. It indicates that the user has not use the feature that the survey is inquiring about. */ "Microsurvey.Survey.Options.LikertScaleOption6.v129" = "Ne ran ket gantañ"; diff --git a/firefox-ios/Shared/Supporting Files/br.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/br.lproj/Toolbar.strings new file mode 100644 index 000000000000..1edb08859831 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/br.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Ivinell nevez"; + diff --git a/firefox-ios/Shared/Supporting Files/bs.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/bs.lproj/Microsurvey.strings index 3020ba9f936c..5c0c5823f232 100644 --- a/firefox-ios/Shared/Supporting Files/bs.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/bs.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Neodabrano"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Anketa"; + diff --git a/firefox-ios/Shared/Supporting Files/bs.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/bs.lproj/Toolbar.strings index e7731c0e434e..c51d262fa1b2 100644 --- a/firefox-ios/Shared/Supporting Files/bs.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/bs.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Novi tab"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Zatvori ovaj tab"; + diff --git a/firefox-ios/Shared/Supporting Files/ca.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/ca.lproj/EditAddress.strings index 3843d1a22ae0..ed1b0621f088 100644 --- a/firefox-ios/Shared/Supporting Files/ca.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/ca.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "No s’ha pogut desar l’adreça"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "No s’ha pogut eliminar l’adreça"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Torna-ho a provar"; diff --git a/firefox-ios/Shared/Supporting Files/ca.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/ca.lproj/Microsurvey.strings index 762267c48a92..14dc36419596 100644 --- a/firefox-ios/Shared/Supporting Files/ca.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/ca.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "No seleccionat"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Enquesta"; + diff --git a/firefox-ios/Shared/Supporting Files/ca.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/ca.lproj/Toolbar.strings new file mode 100644 index 000000000000..457be81c97d9 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/ca.lproj/Toolbar.strings @@ -0,0 +1,6 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Pestanya nova"; + +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Tanca aquesta pestanya"; + diff --git a/firefox-ios/Shared/Supporting Files/cs.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/cs.lproj/Microsurvey.strings index d0cd2f26635a..16d909566053 100644 --- a/firefox-ios/Shared/Supporting Files/cs.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/cs.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Výběr zrušen"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Dotazník"; + diff --git a/firefox-ios/Shared/Supporting Files/cs.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/cs.lproj/Toolbar.strings index 4eec7ea2d40d..9992c9ce23a7 100644 --- a/firefox-ios/Shared/Supporting Files/cs.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/cs.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Nový panel"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Zavřít tento panel"; + diff --git a/firefox-ios/Shared/Supporting Files/cy.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/cy.lproj/Microsurvey.strings index 23e7cc6373f9..93df06f91f49 100644 --- a/firefox-ios/Shared/Supporting Files/cy.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/cy.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Heb ei ddewis"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Arolwg"; + diff --git a/firefox-ios/Shared/Supporting Files/cy.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/cy.lproj/Toolbar.strings new file mode 100644 index 000000000000..c1cb28c213eb --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/cy.lproj/Toolbar.strings @@ -0,0 +1,6 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Tab Newydd"; + +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Cau'r Tab Hwn"; + diff --git a/firefox-ios/Shared/Supporting Files/de.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/de.lproj/Microsurvey.strings index 70d3dc058305..59e408965701 100644 --- a/firefox-ios/Shared/Supporting Files/de.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/de.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Auswahl aufgehoben"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Umfrage"; + diff --git a/firefox-ios/Shared/Supporting Files/de.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/de.lproj/Toolbar.strings index f25301eed189..f051d3add7fa 100644 --- a/firefox-ios/Shared/Supporting Files/de.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/de.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Neuer Tab"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Diesen Tab schließen"; + diff --git a/firefox-ios/Shared/Supporting Files/dsb.lproj/Alerts.strings b/firefox-ios/Shared/Supporting Files/dsb.lproj/Alerts.strings index fccbb9aa17fe..c5ac5fcb5e47 100644 --- a/firefox-ios/Shared/Supporting Files/dsb.lproj/Alerts.strings +++ b/firefox-ios/Shared/Supporting Files/dsb.lproj/Alerts.strings @@ -14,7 +14,7 @@ "Alerts.RestoreTabs.Button.No.v109" = "Ně"; /* The title for the affirmative action of the restore tabs pop-up alert. This alert shows when opening up Firefox after it crashed, and will restore existing tabs. */ -"Alerts.RestoreTabs.Button.Yes.v109" = "Rejtarki wótnowiś"; +"Alerts.RestoreTabs.Button.Yes.v109" = "Rejtariki wótnowiś"; /* The body of the restore tabs pop-up alert. This alert shows when opening up Firefox after it crashed. */ "Alerts.RestoreTabs.Message.v109" = "Wódajśo. Wótnowśo rejtariki, aby tam pókšacował, źož sćo pśestał."; diff --git a/firefox-ios/Shared/Supporting Files/dsb.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/dsb.lproj/Microsurvey.strings index 8cf591593f0f..8354c6297db9 100644 --- a/firefox-ios/Shared/Supporting Files/dsb.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/dsb.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Njewubrany"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Napšašowanje"; + diff --git a/firefox-ios/Shared/Supporting Files/dsb.lproj/TabsTray.strings b/firefox-ios/Shared/Supporting Files/dsb.lproj/TabsTray.strings index 597858e8b78a..9a5ed98a62a5 100644 --- a/firefox-ios/Shared/Supporting Files/dsb.lproj/TabsTray.strings +++ b/firefox-ios/Shared/Supporting Files/dsb.lproj/TabsTray.strings @@ -11,7 +11,7 @@ "InactiveTabs.TabTray.CloseSwipeActionTitle.v115" = "Zacyniś"; /* Users can disable syncing tabs from other devices. In the Sync Tabs panel of the Tab Tray, we inform the user tab syncing can be switched back on to view those tabs. */ -"TabsTray.Sync.SyncTabsDisabled.v116" = "Synchronizěrowanje rejtarkow zašaltowaś, aby se lisćina rejtarkow z drugich rědow pokazała."; +"TabsTray.Sync.SyncTabsDisabled.v116" = "Synchronizěrowanje rejtarikow zašaltowaś, aby se lisćina rejtarikow z drugich rědow pokazała."; /* Button label to sync tabs in your account */ "TabsTray.SyncTabs.SyncTabsButton.Title.v119" = "Rejtariki synchronizěrowaś"; diff --git a/firefox-ios/Shared/Supporting Files/dsb.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/dsb.lproj/Toolbar.strings index 889d0875fbdd..08c904127532 100644 --- a/firefox-ios/Shared/Supporting Files/dsb.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/dsb.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Nowy rejtarik"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Toś ten rejtarik zacyniś"; + diff --git a/firefox-ios/Shared/Supporting Files/el.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/el.lproj/Microsurvey.strings index b003273d4abd..afe1130c8f09 100644 --- a/firefox-ios/Shared/Supporting Files/el.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/el.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Μη επιλεγμένο"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Έρευνα"; + diff --git a/firefox-ios/Shared/Supporting Files/el.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/el.lproj/Toolbar.strings index 935028033f07..2192fbfbfbba 100644 --- a/firefox-ios/Shared/Supporting Files/el.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/el.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Νέα καρτέλα"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Κλείσιμο καρτέλας"; + diff --git a/firefox-ios/Shared/Supporting Files/en-GB.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/en-GB.lproj/Microsurvey.strings index 9806c1dfb754..aa8a84e71e1f 100644 --- a/firefox-ios/Shared/Supporting Files/en-GB.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/en-GB.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Unselected"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Survey"; + diff --git a/firefox-ios/Shared/Supporting Files/en-GB.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/en-GB.lproj/Toolbar.strings index 7784884c18f8..e3c35a24ad4b 100644 --- a/firefox-ios/Shared/Supporting Files/en-GB.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/en-GB.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "New Tab"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Close This Tab"; + diff --git a/firefox-ios/Shared/Supporting Files/en-US.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/en-US.lproj/Microsurvey.strings index 9806c1dfb754..aa8a84e71e1f 100644 --- a/firefox-ios/Shared/Supporting Files/en-US.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/en-US.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Unselected"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Survey"; + diff --git a/firefox-ios/Shared/Supporting Files/en-US.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/en-US.lproj/Toolbar.strings index 7784884c18f8..e3c35a24ad4b 100644 --- a/firefox-ios/Shared/Supporting Files/en-US.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/en-US.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "New Tab"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Close This Tab"; + diff --git a/firefox-ios/Shared/Supporting Files/es-AR.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/es-AR.lproj/Microsurvey.strings index 12afef94e2ee..327fd9ee17ca 100644 --- a/firefox-ios/Shared/Supporting Files/es-AR.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/es-AR.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "No seleccionada"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Encuesta"; + diff --git a/firefox-ios/Shared/Supporting Files/es-AR.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/es-AR.lproj/Toolbar.strings index f5b1dc1cc2e1..c0cd65c91f77 100644 --- a/firefox-ios/Shared/Supporting Files/es-AR.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/es-AR.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Nueva pestaña"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Cerrar esta pestaña"; + diff --git a/firefox-ios/Shared/Supporting Files/es-CL.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/es-CL.lproj/Microsurvey.strings index 6109a1b108d4..dafd983ad832 100644 --- a/firefox-ios/Shared/Supporting Files/es-CL.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/es-CL.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Deseleccionado"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Encuesta"; + diff --git a/firefox-ios/Shared/Supporting Files/es-CL.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/es-CL.lproj/Toolbar.strings index f5b1dc1cc2e1..c0cd65c91f77 100644 --- a/firefox-ios/Shared/Supporting Files/es-CL.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/es-CL.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Nueva pestaña"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Cerrar esta pestaña"; + diff --git a/firefox-ios/Shared/Supporting Files/fi.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/fi.lproj/Toolbar.strings index d39f497a4442..a2e3c28afc86 100644 --- a/firefox-ios/Shared/Supporting Files/fi.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/fi.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Uusi välilehti"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Sulje välilehti"; + diff --git a/firefox-ios/Shared/Supporting Files/fr.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/fr.lproj/Microsurvey.strings index 4f5902df0a75..12949ac75452 100644 --- a/firefox-ios/Shared/Supporting Files/fr.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/fr.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Désélectionné"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Enquête"; + diff --git a/firefox-ios/Shared/Supporting Files/fr.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/fr.lproj/Toolbar.strings index 451c964e1463..f61b85056401 100644 --- a/firefox-ios/Shared/Supporting Files/fr.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/fr.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Nouvel onglet"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Fermer cet onglet"; + diff --git a/firefox-ios/Shared/Supporting Files/he.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/he.lproj/Microsurvey.strings index 88c16a6ab7a5..61d47bc69d7e 100644 --- a/firefox-ios/Shared/Supporting Files/he.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/he.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "לא נבחר"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "סקר"; + diff --git a/firefox-ios/Shared/Supporting Files/he.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/he.lproj/Toolbar.strings index fe5da6b97990..f36854ab5918 100644 --- a/firefox-ios/Shared/Supporting Files/he.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/he.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "לשונית חדשה"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "סגירת לשונית זו"; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/ActivityStream.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/ActivityStream.strings new file mode 100644 index 000000000000..d64f37e12e1b --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/ActivityStream.strings @@ -0,0 +1,6 @@ +/* String used in the section title of the Bookmarks section on Home Screen. */ +"ActivityStream.Bookmarks.Title.v128" = "Zabilješke"; + +/* Show all button text for Bookmarks items on the home page, which opens the Bookmarks panel when tapped. */ +"Bookmarks.Actions.More.v128" = "Prikaži sve"; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/AddressToolbar.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/AddressToolbar.strings new file mode 100644 index 000000000000..5c80c5e72b6e --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/AddressToolbar.strings @@ -0,0 +1,12 @@ +/* Accessibility label for the address field in the address toolbar. */ +"AddressToolbar.Location.A11y.Label.v128" = "Traži ili upiši adresu"; + +/* Placeholder for the address field in the address toolbar. */ +"AddressToolbar.Location.Placeholder.v128" = "Traži ili upiši adresu"; + +/* Accessibility label for the lock icon button in the address field of the address toolbar, responsible with Privacy & Security Settings. */ +"AddressToolbar.PrivacyAndSecuriySettings.A11y.Label.v128" = "Postavke privatnosti i sigurnosti"; + +/* Accessibility label for the search engine icon in the address field of the address toolbar. The placeholder is getting replaced with the name of the search engine (e.g. Google). */ +"AddressToolbar.SearchEngine.A11y.Label.v128" = "Tražilica: %@"; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/Alert.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/Alert.strings index ea9a09cd56c3..84e05b0d6c47 100644 --- a/firefox-ios/Shared/Supporting Files/hr.lproj/Alert.strings +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/Alert.strings @@ -1,6 +1,12 @@ /* Button text to dismiss the dialog box that gets presented as a confirmation to remove card and cancel the operation. */ "CreditCard.SnackBar.CancelRemoveCardButton.v112" = "Odustani"; +/* Sub label for the dialog box that gets presented as a confirmation to ask user if they would like to remove the saved credit card from local as well as all their synced devices */ +"CreditCard.SnackBar.RemoveCardSublabel.v112" = "Ovo će ukloniti kreditnu karticu sa svih tvojih sinkroniziranih uređaja."; + +/* Title label for the dialog box that gets presented as a confirmation to ask user if they would like to remove the saved credit card */ +"CreditCard.SnackBar.RemoveCardTitle.v122" = "Ukloniti kreditnu karticu?"; + /* Button text to dismiss the dialog box that gets presented as a confirmation to remove card and perform the operation of removing the credit card. */ "CreditCard.SnackBar.RemovedCardButton.v112" = "Ukloni"; diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/Alerts.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/Alerts.strings index 5ad4c442a802..e98c744c04b3 100644 --- a/firefox-ios/Shared/Supporting Files/hr.lproj/Alerts.strings +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/Alerts.strings @@ -1,6 +1,21 @@ +/* When tapping the fire icon in private mode, an alert comes up asking to confirm if you want to delete all browsing data and end your private session. This is the body text for the alert. */ +"Alerts.FeltDeletion.Body.v122" = "Zatvori sve privatne kartice i izbriši povijest, kolačiće i sve ostale podatke web stranica."; + +/* When tapping the fire icon in private mode, an alert comes up asking to confirm if you want to delete all browsing data and end your private session. This is the cancel action for the alert, cancelling ending your session. */ +"Alerts.FeltDeletion.Button.Cancel.v122" = "Odustani"; + +/* When tapping the fire icon in private mode, an alert comes up asking to confirm if you want to delete all browsing data and end your private session. This is the affirmative action for the alert, confirming that you do want to do that. */ +"Alerts.FeltDeletion.Button.Confirm.v122" = "Izbriši podatke sesije"; + +/* When tapping the fire icon in private mode, an alert comes up asking to confirm if you want to delete all browsing data and end your private session. This is the title for the alert. */ +"Alerts.FeltDeletion.Title.v122" = "Završiti privatnu sesiju?"; + /* The title for the negative action of the restore tabs pop-up alert. This alert shows when opening up Firefox after it crashed, and will reject the action of restoring tabs. */ "Alerts.RestoreTabs.Button.No.v109" = "Ne"; /* The title for the affirmative action of the restore tabs pop-up alert. This alert shows when opening up Firefox after it crashed, and will restore existing tabs. */ "Alerts.RestoreTabs.Button.Yes.v109" = "Vrati kartice"; +/* The title of the restore tabs pop-up alert. This alert shows when opening up Firefox after it crashed. The placeholder will be the Firefox name. */ +"Alerts.RestoreTabs.Title.v109.v2" = "%@ se srušio. Želiš li vratiti tvoje kartice?"; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/BiometricAuthentication.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/BiometricAuthentication.strings new file mode 100644 index 000000000000..304c5e27d8ce --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/BiometricAuthentication.strings @@ -0,0 +1,6 @@ +/* Biometric authentication is when the system prompts users for Face ID or fingerprint before accessing protected information. This string asks the user to enter their device passcode to access the protected screen. */ +"Biometry.Screen.UniversalAuthenticationReason.v115" = "Autentificiraj se za pristup lozinkama."; + +/* Biometric authentication is when the system prompts users for Face ID or fingerprint before accessing protected information. This string asks the user to enter their device passcode to access the protected screen for logins and encrypted cards. */ +"Biometry.Screen.UniversalAuthenticationReason.v122" = "Autentificiraj se za pristup spremljenim lozinkama i načinima plaćanja."; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/BottomSheet.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/BottomSheet.strings new file mode 100644 index 000000000000..9531cf325778 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/BottomSheet.strings @@ -0,0 +1,3 @@ +/* When a user is in the process of entering an address, a screen pops up prompting the user if they want to use a saved address. This string is used as the title label of the screen. */ +"Addresses.BottomSheet.UseSavedAddressBottomSheet.v124" = "Koristiti jednu spremljenu adresu?"; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/CredentialProvider.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/CredentialProvider.strings new file mode 100644 index 000000000000..126db77a6611 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/CredentialProvider.strings @@ -0,0 +1,3 @@ +/* Placeholder text for search field in the credential provider list */ +"LoginsList.Search.Placeholder.v122" = "Traži lozinke"; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/CustomizeFirefoxHome.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/CustomizeFirefoxHome.strings index 5f2fbb8b5e63..5940f02b8d5b 100644 --- a/firefox-ios/Shared/Supporting Files/hr.lproj/CustomizeFirefoxHome.strings +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/CustomizeFirefoxHome.strings @@ -1,3 +1,6 @@ +/* In the settings menu, in the Firefox homepage customization section, this is the title for the option that allows users to toggle Bookmarks section on the Firefox homepage on or off */ +"Settings.Home.Option.Bookmarks.v128" = "Zabilješke"; + /* In the settings menu, in the Firefox homepage customization section, this is the title for the option that allows users to turn the Pocket Recommendations section on the Firefox homepage on or off */ "Settings.Home.Option.ThoughtProvokingStories.v116" = "Priče koje potiču na razmišljanje"; diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/Edit Card.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/Edit Card.strings index 465f211b6974..ef692feaddfc 100644 --- a/firefox-ios/Shared/Supporting Files/hr.lproj/Edit Card.strings +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/Edit Card.strings @@ -1,3 +1,3 @@ /* Title label for the view where user can edit their credit card info */ -"CreditCard.EditCard.EditCreditCardTitle.v113" = "Uredi kreditnu karticu"; +"CreditCard.EditCard.EditCreditCardTitle.v122" = "Uredi kreditnu karticu"; diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/EditAddress.strings new file mode 100644 index 000000000000..f18b777bab33 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/EditAddress.strings @@ -0,0 +1,141 @@ +/* Title for the cancel button in the remove address alert. */ +"Addresses.EditAddress.Alert.CancelButton.v129" = "Odustani"; + +/* Message explaining the consequences of removing an address from all synced devices. */ +"Addresses.EditAddress.Alert.Message.v129" = "Adresa će se ukloniti sa svih tvojih sinkroniziranih uređaja."; + +/* Title for the remove button in the remove address alert. */ +"Addresses.EditAddress.Alert.RemoveButton.v129" = "Ukloni"; + +/* Title for the alert indicating the action to remove an address. */ +"Addresses.EditAddress.Alert.Title.v129" = "Ukloni adresu"; + +/* Title for the interface option where users can add a new address for autofill purposes. This facilitates quicker form completion by automatically filling in the user's address information. */ +"Addresses.EditAddress.AutofillAddAddressTitle.v129" = "Dodaj adresu"; + +/* Label for the area field, allowing users to specify a particular area within a city or region. This detail can improve the specificity and accuracy of autofilled addresses. */ +"Addresses.EditAddress.AutofillAddressArea.v129" = "Područje"; + +/* Label for the field where users input the city part of their address. This information is crucial for mail delivery and service provision, ensuring accurate city identification in autofill settings. */ +"Addresses.EditAddress.AutofillAddressCity.v129" = "Grad"; + +/* Label for the field where users can specify just the country, used in contexts where full address details are not required. Simplifies autofill when only country information is necessary. */ +"Addresses.EditAddress.AutofillAddressCountryOnly.v129" = "Zemlja"; + +/* Label for the country or region field in address forms, allowing users to specify their country or territorial region. This is fundamental for international mail and services, ensuring autofill accuracy across borders. */ +"Addresses.EditAddress.AutofillAddressCountryRegion.v129" = "Zemlja ili regija"; + +/* Label for the county field, crucial for addressing in regions where county lines play a key role in postal services. Enhances autofill accuracy by including county information. */ +"Addresses.EditAddress.AutofillAddressCounty.v129" = "Županija"; + +/* Label for the department field, used in countries like France and Colombia where departments are a key administrative division. Ensures correct departmental information is autofilled. */ +"Addresses.EditAddress.AutofillAddressDepartment.v129" = "Odjel"; + +/* Label for the district field in the address form, allowing users to specify their district for more precise location identification. This aids in refining address details for accurate autofill. */ +"Addresses.EditAddress.AutofillAddressDistrict.v129" = "Okrug"; + +/* Label for the Do/Si field, pertinent to addresses in South Korea. Do/Si refers to provincial level divisions, and specifying this enhances address accuracy in autofill settings. */ +"Addresses.EditAddress.AutofillAddressDoSi.v129" = "Do/Si"; + +/* Label for the Eircode field, specific to Ireland. It's a unique postal code system that helps in precise location identification, enhancing the effectiveness of autofill. */ +"Addresses.EditAddress.AutofillAddressEircode.v129" = "Eircode"; + +/* Label for the email address field, where users input their email. Critical for digital communication and account verification, this ensures email addresses are autofilled accurately. */ +"Addresses.EditAddress.AutofillAddressEmail.v129" = "E-mail adresa"; + +/* Label for the emirate field, essential for addresses in the United Arab Emirates. Including emirate details ensures the autofill feature accurately represents user addresses. */ +"Addresses.EditAddress.AutofillAddressEmirate.v129" = "Emirat"; + +/* Label for the field where users specify the name of an island, if applicable. Important for addresses in archipelagic regions, aiding in precise location identification during autofill. */ +"Addresses.EditAddress.AutofillAddressIsland.v129" = "Otok"; + +/* Label for the field where the user inputs their full name as part of an address form. Essential for personalized form submissions and ensuring information accuracy in autofilled forms. */ +"Addresses.EditAddress.AutofillAddressName.v129" = "Ime"; + +/* Label for the field where users can input the name of their neighborhood. This detail adds precision to addresses, especially in densely populated areas, improving the accuracy of autofill. */ +"Addresses.EditAddress.AutofillAddressNeighborhood.v129" = "Susjedstvo"; + +/* Label for the oblast field, relevant for addresses in countries like Russia and Ukraine. Oblasts are a significant administrative division, and their specification aids in autofill accuracy. */ +"Addresses.EditAddress.AutofillAddressOblast.v129" = "Oblast"; + +/* Label for the input field designated for the organization's name related to the address. Helps in distinguishing addresses used for business or personal purposes in autofill settings. */ +"Addresses.EditAddress.AutofillAddressOrganization.v129" = "Organizacija"; + +/* Label for the parish field, significant in places where parishes are used for local administration and addressing. Ensures users can specify parish details for better autofill accuracy. */ +"Addresses.EditAddress.AutofillAddressParish.v129" = "Župa"; + +/* Label for the PIN (Postal Index Number) field, used in India. It's a code representing a specific area, crucial for accurate mail delivery and autofill functionality. */ +"Addresses.EditAddress.AutofillAddressPin.v129" = "Pin"; + +/* Label for the postal code field, universally used in address forms to specify the area code for mail sorting. Essential for autofill to ensure mail and services are accurately routed. */ +"Addresses.EditAddress.AutofillAddressPostalCode.v129" = "Poštanski broj"; + +/* Label for the post town field, used primarily in the UK and some other regions for mail sorting. Essential for users in applicable areas to specify for correct mail delivery through autofill. */ +"Addresses.EditAddress.AutofillAddressPostTown.v129" = "Post town"; + +/* Label for the prefecture field, essential for addresses in countries like Japan where prefectures are a major administrative division. Aids in precise location specification for autofill. */ +"Addresses.EditAddress.AutofillAddressPrefecture.v129" = "Prefektura"; + +/* Label for the province field, required in countries where provinces are a primary administrative division. Helps in pinpointing the user's location more accurately for autofill purposes. */ +"Addresses.EditAddress.AutofillAddressProvince.v129" = "Provincija"; + +/* Label for the state field, a necessary component of addresses in many countries, especially the USA. It ensures that state-specific details are correctly filled in forms using autofill. */ +"Addresses.EditAddress.AutofillAddressState.v129" = "Država"; + +/* Label for the suburb field, enabling users to add suburb details to their address. This is important for accurate delivery and services in suburban areas, enhancing autofill functionality. */ +"Addresses.EditAddress.AutofillAddressSuburb.v129" = "Predgrađe"; + +/* Label for the telephone number field, allowing users to input their contact number. This is essential for communication and service provision, ensuring contact details are autofilled correctly. */ +"Addresses.EditAddress.AutofillAddressTel.v129" = "Telefon"; + +/* Label for the input field for the townland, a specific type of land division used in rural areas. Enhances address detail for users in regions where townlands are a common addressing component. */ +"Addresses.EditAddress.AutofillAddressTownland.v129" = "Townland"; + +/* Label for the field to input the name of a village or township. This is crucial for addresses in rural areas, ensuring the autofill feature accurately captures all necessary geographical details. */ +"Addresses.EditAddress.AutofillAddressVillageTownship.v129" = "Selo ili općina"; + +/* Label for the ZIP code field, primarily used in the United States for mail sorting. Key for autofill to accurately complete addresses for shipping, billing, and service provision. */ +"Addresses.EditAddress.AutofillAddressZip.v129" = "Poštanski broj"; + +/* Label for the button to cancel the current autofill operation or exit the form without saving changes. Provides users with an option to back out of a process without making any modifications. */ +"Addresses.EditAddress.AutofillCancelButton.v129" = "Odustani"; + +/* Title for the option allowing users to edit an existing saved address. This is used within the settings for autofill, enabling users to update their address details for accurate form autofilling. */ +"Addresses.EditAddress.AutofillEditAddressTitle.v129" = "Uredi adresu"; + +/* Title for the input field where users can enter their street address. This is used within the settings for autofill, allowing users to provide their street address for accurate form autofilling. */ +"Addresses.EditAddress.AutofillEditStreetAddressTitle.v129" = "Ulica"; + +/* Label for the button to save the current address details entered or edited by the user. This action confirms the user's changes and updates their autofill settings accordingly. */ +"Addresses.EditAddress.AutofillSaveButton.v129" = "Spremi"; + +/* Title for the option allowing users to view an existing saved address. This is used within the settings for autofill, enabling users to see their address details for accurate form autofilling. */ +"Addresses.EditAddress.AutofillViewAddressTitle.v129" = "Prikaži adresu"; + +/* Button label for closing the view where user can view their address info. */ +"Addresses.EditAddress.CloseNavBarButtonLabel.v129" = "Zatvori"; + +/* Button label for editing the address details shown in the form. */ +"Addresses.EditAddress.EditNavBarButtonLabel.v129" = "Uredi"; + +/* Title for button that offers the user the option to remove an address. */ +"Addresses.EditAddress.RemoveAddressButtonTitle.v129" = "Ukloni adresu"; + +/* Toast message confirming that an address has been successfully removed. */ +"Addresses.Toast.AddressRemovedConfirmation.v129" = "Adresa je uklonjena"; + +/* Toast message confirming that an address has been successfully saved. */ +"Addresses.Toast.AddressSavedConfirmation.v129" = "Adresa spremljena"; + +/* Toast message indicating an error occurred while trying to save an address. */ +"Addresses.Toast.AddressSaveError.v129" = "Adresa se nije mogla spremiti"; + +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Adresa se nije mogla ukloniti"; + +/* Suggestion to try again after an error occurred while trying to save an address. */ +"Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Pokušaj ponovo"; + +/* Toast message confirming that an address has been successfully updated. */ +"Addresses.Toast.AddressUpdatedConfirmation.v129" = "Podaci o adresi su aktulizirani"; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/EditCard.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/EditCard.strings index 65732fb945ba..0072ab1749ea 100644 --- a/firefox-ios/Shared/Supporting Files/hr.lproj/EditCard.strings +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/EditCard.strings @@ -1,3 +1,6 @@ +/* Title label for the view where user can add their credit card info */ +"CreditCard.EditCard.AddCreditCardTitle.v122" = "Dodaj kreditnu karticu"; + /* Button label for cancelling editing of the credit card details shown in the form */ "CreditCard.EditCard.CancelNavBarButtonLabel.v113" = "Odustani"; @@ -40,6 +43,9 @@ /* Button label for saving the credit card details user entered in the form */ "CreditCard.EditCard.SaveNavBarButtonLabel.v113" = "Spremi"; +/* Title label for user to use the toggle settings to allow saving and autofilling of credit cards for webpages. */ +"CreditCard.EditCard.ToggleToAllowAutofillTitle.v122" = "Spremi i ispuni načine plaćanja"; + /* Title label for the view where user can view their credit card info */ "CreditCard.EditCard.ViewCreditCardTitle.v116" = "Prikaži karticu"; diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/EngagementNotification.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/EngagementNotification.strings index 9d3a595c3cec..ca35deffa9b6 100644 --- a/firefox-ios/Shared/Supporting Files/hr.lproj/EngagementNotification.strings +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/EngagementNotification.strings @@ -4,9 +4,15 @@ /* Title of notification send to user after inactivity to encourage them to use the search feature. */ "Engagement.Notification.Title.v112" = "Započni svoje prvo pretraživanje"; +/* Body of notification send to user after inactivity to encourage them to use the private browsing feature. Placeholder is app name. */ +"Engagement.Notification.Treatment.A.Body.v114" = "Privatno pregledavanje u %@ ne sprema tvoje podatke i blokira skrivene programe za praćenje."; + /* Title of notification send to user after inactivity to encourage them to use the private browsing feature. */ "Engagement.Notification.Treatment.A.Title.v114" = "Pretražuj bez ostavljanja traga"; +/* Body of notification send to user after inactivity to encourage them to use the private browsing feature. Placeholder is the app name. */ +"Engagement.Notification.Treatment.B.Body.v114" = "Pregledavaj bez spremljenih kolačića ili povijesti u %@."; + /* Title of notification send to user after inactivity to encourage them to use the private browsing feature. */ "Engagement.Notification.Treatment.B.Title.v114" = "Isprobaj privatno pretraživanje"; diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/EnhancedTrackingProtection.strings new file mode 100644 index 000000000000..01de5efc88b2 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/EnhancedTrackingProtection.strings @@ -0,0 +1,46 @@ +/* The text for the clear cookies and site data alert button inside the enhanced tracking protection screen. */ +"Menu.EnhancedTrackingProtection.ClearData.AlertCancelButton.v128" = "Odustani"; + +/* The text for the clear cookies and site data alert button inside the enhanced tracking protection screen. */ +"Menu.EnhancedTrackingProtection.ClearData.AlertOkButton.v128" = "Izbriši"; + +/* The title for the clear cookies and site data alert inside the enhanced tracking protection screen. */ +"Menu.EnhancedTrackingProtection.ClearData.AlertTitle.v128" = "Izbriši kolačiće i podatke stranice"; + +/* The title for the clear cookies and site data button inside the enhanced tracking protection screen. */ +"Menu.EnhancedTrackingProtection.ClearData.ButtonTitle.v128" = "Obriši kolačiće i podatke stranice"; + +/* The text for the clear cookies and site data toast that appears when the user selects to clear the cookies */ +"Menu.EnhancedTrackingProtection.ClearData.ToastMessage.v128" = "Kolačići i podaci stranice su uklonjeni"; + +/* Text to let users know that the current website is secure. */ +"Menu.EnhancedTrackingProtection.Details.ConnectionSecure.v128" = "Sigurna veza"; + +/* Text to let users know that the current website is not secure. */ +"Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Veza nije sigurna"; + +/* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Programi za praćenje društvenih mreža: %@"; + +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked + Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Blokirani programi za praćenje: %@"; + +/* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ +"Menu.EnhancedTrackingProtection.Details.Verifier.v128" = "Ovjereno od %@"; + +/* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ +"Menu.EnhancedTrackingProtection.Off.Title.v128" = "Isključio/la si zaštitu"; + +/* The title for the privacy settings button inside the enhanced tracking protection screen. */ +"Menu.EnhancedTrackingProtection.PrivacySettings.Title.v128" = "Postavke privatnosti"; + +/* Title for the switch to enable/disable enhanced tracking protection inside the menu. */ +"Menu.EnhancedTrackingProtection.Switch.Title.v128" = "Poboljšana zaštita od praćenja"; + +/* A switch to disable enhanced tracking protection inside the menu. */ +"Menu.EnhancedTrackingProtection.SwitchOff.Text.v128" = "Zaštite su ISKLJUČENE. Predlažemo da ih ponovo uključiš."; + +/* A switch to disable enhanced tracking protection inside the menu. */ +"Menu.EnhancedTrackingProtection.SwitchOff.Text.v129" = "Zaštite su ISKLJUČENE. Predlažemo da ih ponovo uključiš."; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/FirefoxHomepage.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/FirefoxHomepage.strings new file mode 100644 index 000000000000..9660fad9104c --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/FirefoxHomepage.strings @@ -0,0 +1,6 @@ +/* The link for the card that educates users about how private mode works. The link redirects to an external site for more information. The card shows up on the homepage when in the new privacy mode. */ +"FirefoxHomepage.FeltPrivacyUI.Link.v122" = "Tko bi mogao vidjeti moju aktivnost?"; + +/* The title for the card that educates users about how private mode works. The card shows up on the homepage when in the new privacy mode. */ +"FirefoxHomepage.FeltPrivacyUI.Title.v122" = "Ne ostavljaj tragove na ovom uređaju"; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/FirefoxLogins.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/FirefoxLogins.strings new file mode 100644 index 000000000000..e8a59c6f315b --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/FirefoxLogins.strings @@ -0,0 +1,18 @@ +/* Prompt for saving the username in the Save Logins prompt. */ +"LoginsHelper.PromptSaveLogin.Title.v122" = "Spremiti korisničko ime?"; + +/* Prompt for saving a password in the Save Logins prompt. */ +"LoginsHelper.PromptSavePassword.Title.v122" = "Spremiti lozinku?"; + +/* Prompt for updating the password in the Update Password prompt. */ +"LoginsHelper.PromptUpdateLogin.Title.OneArg.v122" = "Aktualizirati lozinku?"; + +/* Prompt for updating a password in the Update Password prompt. */ +"LoginsHelper.PromptUpdateLogin.Title.TwoArg.v122" = "Aktualizirati lozinku?"; + +/* Placeholder text for search box in logins list view. */ +"LoginsList.LoginsListSearchPlaceholder.v122" = "Pretraži lozinke"; + +/* Title for the list of logins saved by the app */ +"LoginsList.Title.v122" = "SPREMLJENE LOZINKE"; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/FirefoxSync.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/FirefoxSync.strings index 527f0e697fb5..949cac42bc20 100644 --- a/firefox-ios/Shared/Supporting Files/hr.lproj/FirefoxSync.strings +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/FirefoxSync.strings @@ -1,3 +1,9 @@ +/* Toggle for address autofill syncing setting */ +"FirefoxSync.AddressAutofillEngine.v124" = "Adrese"; + /* Toggle for credit cards syncing setting */ -"FirefoxSync.CreditCardsEngine.v115" = "Kreditne kartice"; +"FirefoxSync.CreditCardsEngine.v122" = "Načini plaćanja"; + +/* Toggle passwords syncing setting, in the Settings > Sync Data menu of the app. */ +"Sync.LoginsEngine.Title.v122" = "Lozinke"; diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/Footer.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/Footer.strings index 54a5796f1aa1..b3d93b99e3bd 100644 --- a/firefox-ios/Shared/Supporting Files/hr.lproj/Footer.strings +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/Footer.strings @@ -1,3 +1,6 @@ /* This is the learn more text of the Pocket footer on Firefox Homepage. */ "FirefoxHomepage.Pocket.Footer.LearnMore.v115" = "Saznaj više"; +/* This is the title of the Pocket footer on Firefox Homepage. The first placeholder is for the Pocket app name and the second placeholder for the app name */ +"FirefoxHomepage.Pocket.Footer.Title.v116" = "Pokreće %1$@. Dio %2$@ obitelji."; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/JumpBackIn.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/JumpBackIn.strings new file mode 100644 index 000000000000..c7f462672901 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/JumpBackIn.strings @@ -0,0 +1,6 @@ +/* Contextual hints are little popups that appear for the users informing them of new features. This one talks about additions to the Firefox homepage regarding a more personalized experience. */ +"ContextualHints.FirefoxHomepage.JumpBackIn.PersonalizedHome" = "Upoznaj svoju personaliziranu početnu stranicu. Ovdje će se pojaviti nedavne kartice, zabilješke i rezultati pretraživanja."; + +/* Contextual hints are little popups that appear for the users informing them of new features. When a user is logged in and has a tab synced from desktop, this popup indicates which tab that is within the Jump Back In section. */ +"ContextualHints.FirefoxHomepage.JumpBackIn.SyncedTab.v106" = "Tvoje se kartice sinkroniziraju! Nastavi gdje si stao/la na svom drugom uređaju."; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/KeyboardAccessory.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/KeyboardAccessory.strings new file mode 100644 index 000000000000..89a274ef95ae --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/KeyboardAccessory.strings @@ -0,0 +1,6 @@ +/* Accessibility label for next button that is displayed above the keyboard when a form field on a website was tapped. */ +"KeyboardAccessory.NextButton.Accessibility.Label.v124" = "Sljedeće polje obrasca"; + +/* Accessibility label for previous button that is displayed above the keyboard when a form field on a website was tapped. */ +"KeyboardAccessory.PreviousButton.Accessibility.Label.v124" = "Prethodno polje obrasca"; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/LoginsHelper.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/LoginsHelper.strings new file mode 100644 index 000000000000..ae15b83d75d0 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/LoginsHelper.strings @@ -0,0 +1,9 @@ +/* Button to not save the user's password in the logins helper */ +"LoginsHelper.DontSave.Button.v122" = "Ne sada"; + +/* Button to not update the user's password in the logins helper */ +"LoginsHelper.DontUpdate.Button.v122" = "Ne sada"; + +/* Button to save the user's password */ +"LoginsHelper.SaveLogin.Button.v122" = "Spremi"; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/Microsurvey.strings new file mode 100644 index 000000000000..3f26d5d41106 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/Microsurvey.strings @@ -0,0 +1,69 @@ +/* On top of the bottom toolbar, there can be a microsurvey prompt, this is the title for the button that appears on the prompt that allows the user to tap on and navigates them to the microsurvey to respond to. */ +"Microsurvey.Prompt.Button.v127" = "Nastavi"; + +/* On top of the bottom toolbar, there can be a microsurvey prompt, this is the accessibility label for the close button that appears on the prompt that allows the user to dismiss the microsurvey prompt. */ +"Microsurvey.Prompt.Close.AccessibilityLabel.v127" = "Zatvori upit ankete"; + +/* On top of the bottom toolbar, there can be a microsurvey prompt, this is the accessibility label for the close button that appears on the prompt that allows the user to dismiss the microsurvey prompt. */ +"Microsurvey.Prompt.Close.Button.AccessibilityLabel.v127" = "Zatvori"; + +/* On top of the bottom toolbar, there can be a microsurvey prompt, this is the logo image that appears on the prompt to inform the prompt is coming from the app specifically. Placeholder is for the app name. */ +"Microsurvey.Prompt.LogoImage.AccessibilityLabel.v129" = "%@ logotip"; + +/* On top of the bottom toolbar, there can be a microsurvey prompt, this is the title for the text that appears on the prompt to inform the user that this is a prompt to take a survey. Placeholder is for the app name. */ +"Microsurvey.Prompt.TitleLabel.v127" = "Pomogni nam poboljšati %@. Traje samo jednu minutu."; + +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this the title of button on the survey that a user can tap on to submit their responses. */ +"Microsurvey.Survey.Button.v127" = "Pošalji"; + +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label for close button that dismisses the sheet. */ +"Microsurvey.Survey.Close.AccessibilityLabel.v127" = "Zatvori anketu"; + +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label for close button that dismisses the sheet. */ +"Microsurvey.Survey.Close.Button.AccessibilityLabel.v127" = "Zatvori"; + +/* On the microsurvey, which is a bottom sheet that pops up with a survey question and options, this is the text shown on the confirmation page when the user has completed the survey. */ +"Microsurvey.Survey.ConfirmationPage.ConfirmationLabel.v127" = "Hvala ti povratnim informacijama!"; + +/* On the microsurvey, which is a bottom sheet that pops up with a survey question and options, this is the title for the header on the microsurvey when the user has completed the survey. */ +"Microsurvey.Survey.ConfirmationPage.HeaderLabel.v127" = "Anketa dovršena"; + +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the title for the header on the screen. */ +"Microsurvey.Survey.HeaderLabel.v127" = "Ispuni ovu anketu"; + +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the title for the header on the screen. */ +"Microsurvey.Survey.HeaderLabel.v129" = "Ispuni anketu"; + +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the logo image that appears on the bottom sheet that informs the user that it is coming from the app specifically. Placeholder is for the app name. */ +"Microsurvey.Survey.LogoImage.AccessibilityLabel.v129" = "%@ logotip"; + +/* On the microsurvey, this is the title for one of the options that the user can select to answer the survey. */ +"Microsurvey.Survey.Options.LikertScaleOption1.v127" = "Vrlo zadovoljan/na"; + +/* On the microsurvey, this is the title for one of the options that the user can select to answer the survey. */ +"Microsurvey.Survey.Options.LikertScaleOption2.v127" = "Zadovoljan/na"; + +/* On the microsurvey, this is the title for one of the options that the user can select to answer the survey. */ +"Microsurvey.Survey.Options.LikertScaleOption3.v127" = "Neutralno"; + +/* On the microsurvey, this is the title for one of the options that the user can select to answer the survey. */ +"Microsurvey.Survey.Options.LikertScaleOption4.v127" = "Nezadovoljan/na"; + +/* On the microsurvey, this is the title for one of the options that the user can select to answer the survey. */ +"Microsurvey.Survey.Options.LikertScaleOption5.v127" = "Vrlo nezadovoljan/na"; + +/* On the microsurvey, this is the title for one of the options that the user can select to answer the survey. It indicates that the user has not use the feature that the survey is inquiring about. */ +"Microsurvey.Survey.Options.LikertScaleOption6.v129" = "Ne koristim ju"; + +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states the order the survey option in the list of options. First placeholder is the number the option is in the list and the second placeholder is the total number of options such as 1 out of 6. */ +"Microsurvey.Survey.OptionsOrder.AccessibilityLabel.v129" = "%1$@ od %2$@"; + +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this the title of a link on the survey and allows the user to navigate to our privacy policy details. */ +"Microsurvey.Survey.PrivacyPolicyLink.v127" = "Napomena o privatnosti"; + +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was selected. */ +"Microsurvey.Survey.RadioButton.Selected.AccessibilityLabel.v129" = "Odabrano"; + +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ +"Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Neodabrano"; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/Notification.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/Notification.strings new file mode 100644 index 000000000000..9f4623fee9b1 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/Notification.strings @@ -0,0 +1,3 @@ +/* Fallback Title of notification if no notification title was configured. The notification is an advise to the user. The argument is the app name. */ +"Notification.Fallback.Title.v113" = "%@ savjet"; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/Onboarding.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/Onboarding.strings index 6939491be134..06f575403d12 100644 --- a/firefox-ios/Shared/Supporting Files/hr.lproj/Onboarding.strings +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/Onboarding.strings @@ -1,3 +1,72 @@ +/* The title of the button on the Default Browser Popup, which is a card with instructions telling the user how to set Firefox as their default browser. */ +"DefaultBrowserPopup.ButtonTitle.v114" = "Idi na postavke"; + +/* The footer label on the Default Browser Popup, which is below all the instructions asking the users if their Firefox browser is the default browser. If it is then close this message and tap skip. The *text inside asterisks* denotes part of the string to bold, please leave the text inside the '*' so that it is bolded correctly. */ +"DefaultBrowserPopup.DescriptionFooter.v124" = "*Je li %@ već tvoj standardni preglednik?* Zatvori ovu poruku i dodirni gumb „Preskoči”."; + +/* The first label on the Default Browser Popup, which is a card with instructions telling the user how to set Firefox as their default browser. The *text inside asterisks* denotes part of the string to bold, please leave the text inside the '*' so that it is bolded correctly. */ +"DefaultBrowserPopup.FirstLabel.v114" = "1. Idi na *Postavke*"; + +/* The second label on the Default Browser Popup, which is a card with instructions telling the user how to set Firefox as their default browser. The *text inside asterisks* denotes part of the string to bold, please leave the text inside the '*' so that it is bolded correctly. */ +"DefaultBrowserPopup.SecondLabel.v114" = "2. Dodirni *Standardni preglednik*"; + +/* The third label on the Default Browser Popup, which is a card with instructions telling the user how to set Firefox as their default browser. Placeholder is the app name. The *text inside asterisks* denotes part of the string to bold, please leave the text inside the '*' so that it is bolded correctly. */ +"DefaultBrowserPopup.ThirdLabel.v114" = "3. Odaberi *%@*"; + +/* The title on the Default Browser Popup, which is a card with instructions telling the user how to set Firefox as their default browser. */ +"DefaultBrowserPopup.Title.v114" = "Promijeni standardni preglednik"; + +/* String used to describe the option to continue to the next onboarding card in Firefox Onboarding screens. Placeholder is for the app name. */ +"Onboarding.Customization.Intro.Continue.Action.v123" = "Prilagodi %@"; + +/* String used to describe the description label of the customization onboarding page in our Onboarding screens. */ +"Onboarding.Customization.Intro.Description.v123" = "Postavi temu i alatnu traku tako da odgovaraju tvom jedinstvenom stilu pregledavanja."; + +/* String used to describe the option to skip the customization cards in Firefox Onboarding screens and start browsing. */ +"Onboarding.Customization.Intro.Skip.Action.v123" = "Počni pregledavati"; + +/* String used to describe the title of the customization onboarding page in our Onboarding screens. Placeholder is for the app name. */ +"Onboarding.Customization.Intro.Title.v123" = "%@ ti daje kontrolu"; + +/* String used to describe the option to save the user setting and continue to the next onboarding in Firefox Onboarding screens. */ +"Onboarding.Customization.Theme.Continue.Action.v123" = "Spremi i nastavi"; + +/* On the theme customization onboarding card, the string used to describe the option to set the theme to dark theme from the available choices. */ +"Onboarding.Customization.Theme.Dark.Action.v123" = "Tamna"; + +/* String used to describe the description label of the theme customization onboarding page in our Onboarding screens. */ +"Onboarding.Customization.Theme.Description.v123" = "Pogledaj web u najboljem svjetlu."; + +/* On the theme customization onboarding card, the string used to describe the option to set the theme to light theme from the available choices. */ +"Onboarding.Customization.Theme.Light.Action.v123" = "Svijetla"; + +/* String used to describe the option to skip the theme customization in Firefox Onboarding screens. */ +"Onboarding.Customization.Theme.Skip.Action.v123" = "Preskoči"; + +/* On the theme customization onboarding card, the string used to describe the option to set the theme to system theme from the available choices. */ +"Onboarding.Customization.Theme.System.Action.v123" = "Automatski od sustava"; + +/* String used to describe the title of the theme customization onboarding page in our Onboarding screens. */ +"Onboarding.Customization.Theme.Title.v123" = "Odaberi temu"; + +/* On the toolbar customization onboarding card, the string used to describe the option to set the toolbar at the bottom of the screen. */ +"Onboarding.Customization.Toolbar.Bottom.Action.v123" = "Dolje"; + +/* String used to describe the option to save set preferences and leave onboarding to start browsing in the app. */ +"Onboarding.Customization.Toolbar.Continue.Action.v123" = "Spremi i počni pregledavati"; + +/* String used to describe the description label of the toolbar customization onboarding page in our Onboarding screens. */ +"Onboarding.Customization.Toolbar.Description.v123" = "Zadrži pretrage nadohvat ruke."; + +/* String used to describe the option to skip the toolbar customization in Firefox Onboarding screens and start browisg in the app. */ +"Onboarding.Customization.Toolbar.Skip.Action.v123" = "Preskoči"; + +/* String used to describe the title of the toolbar customization onboarding page in our Onboarding screens. */ +"Onboarding.Customization.Toolbar.Title.v123" = "Odaberi položaj alatne trake"; + +/* On the toolbar customization onboarding card, the string used to describe the option to set the toolbar at the top of the screen. */ +"Onboarding.Customization.Toolbar.Top.Action.v123" = "Gore"; + /* Describes an action on some of the Onboarding screen, including the wallpaper onboarding screen. This string will be on a button so user can skip that onboarding page. */ "Onboarding.LaterAction.v115" = "Preskoči"; @@ -7,12 +76,39 @@ /* String used to describe the option to skip the notification permission in Firefox Onboarding screens. */ "Onboarding.Notification.Skip.Action.v115" = "Preskoči"; +/* String used to describe the option to continue to ask for the notification permission in Firefox Onboarding screens. */ +"Onboarding.Notification.TurnOnNotifications.Action.v114" = "Uključi obavijesti"; + /* String used to describes the option to skip the Sync sign in during onboarding for the current version in Firefox Onboarding screens. */ "Onboarding.Sync.SignIn.Action.v114" = "Prijava"; /* String used to describes the option to skip the Sync sign in during onboarding for the current version in Firefox Onboarding screens. */ "Onboarding.Sync.Skip.Action.v114" = "Preskoči"; +/* Accessibility label for the wallpaper onboarding modal displayed on top of the homepage. This describes to the user that which type of wallpaper they are seeing. */ +"Onboarding.Wallpaper.Accessibility.Classic.v114" = "Klasična pozadina"; + +/* Accessibility label for the wallpaper onboarding modal displayed on top of the homepage. This describes to the user that which type of wallpaper they are seeing. */ +"Onboarding.Wallpaper.Accessibility.LimitedEdition.v114" = "Pozadina ograničenog izdanja"; + +/* Description for the wallpaper onboarding page in our Onboarding screens. This describes to the user that they can set a wallpaper. */ +"Onboarding.Wallpaper.Action.v114" = "Postavi pozadinu"; + +/* Description for the wallpaper onboarding modal displayed on top of the homepage. This describes to the user that they can choose different wallpapers. */ +"Onboarding.Wallpaper.Description.v114" = "Odaberi pozadinu koja ti odgovara."; + +/* Title for the wallpaper onboarding modal displayed on top of the homepage. This describes to the user that they can choose different wallpapers. */ +"Onboarding.Wallpaper.SelectorTitle.v114" = "Isprobaj jednu obojanu pozadinu"; + +/* Title for the wallpaper onboarding page in our Onboarding screens. This describes to the user that they can choose different wallpapers. Placeholder is for app name. */ +"Onboarding.Wallpaper.Title.v114" = "Odaberi %@ pozadinu"; + +/* Describes the action on the first onboarding page in our Onboarding screen. This string will be on a button so user can continue the onboarding. */ +"Onboarding.Welcome.Action.v114" = "Započni"; + +/* Describes the action on the first onboarding page in our Onboarding screen. This indicates that the user will set their default browser to Firefox. */ +"Onboarding.Welcome.ActionTreatementA.v114" = "Postavi kao standardni preglednik"; + /* Describes the action on the first onboarding page in our Onboarding screen. This string will be on a button so user can skip this onboarding card. */ "Onboarding.Welcome.Skip.v114" = "Preskoči"; diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/Settings.strings index 31f48a41af2c..79c2d0867fbe 100644 --- a/firefox-ios/Shared/Supporting Files/hr.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/Settings.strings @@ -1,15 +1,123 @@ +/* Title label for user to use the toggle settings to allow saving and autofilling of addresses for webpages. */ +"Addresses.Settings.Switch.Title.v124" = "Spremi i ispuni adrese"; + +/* Displayed inside the keyboard hint when a user is entering their address and has at least one saved address. Indicates that there are stored addresses available for use in filling out a form. */ +"Addresses.Settings.UseSavedAddressFromKeyboard.v124" = "Koristi spremljenu adresu"; + +/* Accessibility label for the add button in autofill settings screen. Pressing this button presents a modal that allows users to add a card by entering the credit card information. */ +"CreditCard.Settings.AddCard.AccessibilityLabel.v121" = "Dodaj kreditnu karticu"; + +/* Title label for when there are no credit cards shown in credit card list in autofill settings screen. %@ is the product name and should not be altered. */ +"CreditCard.Settings.EmptyListTitle.v122" = "Spremi kreditne kartice na %@"; + +/* Accessibility label for a credit card list item in autofill settings screen. The first parameter is the credit card issuer (e.g. Visa). The second parameter is the name of the credit card holder. The third parameter is the last 4 digits of the credit card. The fourth parameter is the card's expiration date. */ +"CreditCard.Settings.ListItemA11y.v118" = "%1$@, izdano za %2$@, završava %3$@, isteče %4$@"; + +/* When a user is in the process or has finished making a purchase with a card not saved in Firefox's list of stored cards, we ask the user if they would like to save this card for future purchases. This string indicates to users that they can deny Firefox from remembering the card that is being used. */ +"CreditCard.Settings.NotNow.v122" = "Ne sada"; + +/* When a user is in the process or has finished making a purchase with a card not saved in Firefox's list of stored cards, we ask the user if they would like to save this card for future purchases. This string is a title string of the overall message that asks the user if they would like Firefox to remember the card that is being used. */ +"CreditCard.Settings.RememberThisCard.v122" = "Sigurno spremiti ovu kreditnu karticu?"; + +/* When a user is in the process or has finished making a purchase with a remembered card, and if the credit card information doesn't match the contents of the stored information of that card, we show this string. We ask this user if they would like Firefox update the staled information of that credit card. */ +"CreditCard.Settings.UpdateThisCard.v122" = "Aktualizirati kreditnu karticu?"; + +/* When a user is in the process or has finished making a purchase with a card not saved in Firefox's list of stored cards, we ask the user if they would like to save this card for future purchases. This string asks users to confirm if they would like Firefox to remember the card that is being used. */ +"CreditCard.Settings.Yes.v122" = "Aktualiziraj"; + /* When a user is in the process of making a purchase and has at least one saved credit card, a view above the keyboard shows actions a user can take. When tapping this label, the keyboard will dismiss from view. */ "CreditCards.Settings.Done.v114" = "Gotovo"; /* When a user is in the process or has finished making a purchase, and has at least one card saved, we show this tappable string. This indicates to users that they can navigate to their list of stored credit cards in the app's credit card list screen. */ "CreditCards.Settings.ManageCards.v112" = "Upravljaj karticama"; +/* When a user is in the process of making a purchase, and has at least one saved card, we show this label used as a title. This indicates to the user that there are stored cards available for use on this pending purchase. */ +"CreditCards.Settings.UseASavedCard.v122" = "Koristi spremljenu kreditnu karticu"; + /* When a user is in the process of making a purchase, and has at least one saved card, we show this label inside the keyboard hint. This indicates to the user that there are stored cards available for use on this pending purchase. */ "CreditCards.Settings.UseSavedCardFromKeyboard.v112" = "Koristi spremljenu karticu"; +/* Settings section title for the old Firefox account */ +"FxA.FirefoxAccount.v119" = "Račun"; + +/* Label used as an item in Settings screen. When touched, it will take user to address autofill settings page to that will allow user to add or modify saved addresses to allow for autofill in a webpage. */ +"Settings.AddressAutofill.Title.v124" = "Automatsko ispunjavanje adresa"; + +/* Label used as an item in Settings screen. When touched, it will take user to address autofill settings page to that will allow user to add or modify saved addresses to allow for autofill in a webpage. */ +"Settings.AddressAutofill.Title.v126" = "Adrese"; + +/* Label used as an item in Settings screen. When touched, it will take user to credit card settings page to that will allows to add or modify saved credit cards to allow for autofill in a webpage. */ +"Settings.AutofillCreditCard.Title.v122" = "Načini plaćanja"; + +/* Title displayed in header of the FxA settings panel. */ +"Settings.FxA.Title.v119" = "Račun"; + +/* This is the description for the setting that toggles Sync related notifications in the settings menu under the Notifications section. */ +"Settings.Notifications.SyncNotificationsStatus.v112" = "Ovo mora biti uključeno za primanje kartica i obavijest kada se prijaviš na jednom drugom uređaju."; + +/* This is the title for the setting that toggles Sync related notifications in the settings menu under the Notifications section. */ +"Settings.Notifications.SyncNotificationsTitle.v112" = "Sinkronizacija"; + /* This is the title for the setting that toggles Tips and Features feature in the settings menu under the Notifications section. */ "Settings.Notifications.TipsAndFeaturesNotificationsTitle.v112" = "Savjeti i značajke"; /* In the settings menu, in the Privacy section, this is the title for Notifications customization section. */ "Settings.Notifications.Title.v112" = "Obavijesti"; +/* This is the title informing the user needs to turn on notifications in iOS Settings. */ +"Settings.Notifications.TurnOnNotificationsTitle.v112" = "Uključi obavijesti"; + +/* Accessibility label for default search engine setting. */ +"Settings.Search.Accessibility.DefaultSearchEngine.v121" = "Standardna tražilica"; + +/* Title for alternate search engines settings section in the Search page in the Settings menu. */ +"Settings.Search.AlternateSearchEngines.Title.v124.v2" = "Alternativne tražilice"; + +/* Footer for the `default search engine` settings section in the Search Settings page, which explains in more details what the `Show Search Suggestions` setting includes. */ +"Settings.Search.DefaultSearchEngine.Footer.v122" = "Rezultati pretraživanja, povijesti, zabilješki i više"; + +/* Title for the `default search engine` settings section in the Search page in the Settings menu. */ +"Settings.Search.DefaultSearchEngine.Title.v121" = "Standardna tražilica"; + +/* Title for the `Suggestions from Search Engines` settings section in the Search page in the Settings menu. */ +"Settings.Search.EnginesSuggestions.Title.v124" = "Prijedlozi tražilica"; + +/* Navigation title for search page in the Settings menu. */ +"Settings.Search.PageTitle.v121" = "Traži"; + +/* Description for `Show in Private Sessions` toggle, located in `Suggestions from Search Engines` section in the Search page in the Settings menu. */ +"Settings.Search.PrivateSession.Description.v125" = "Prikaži prijedloge tražilica u privatnim sesijama"; + +/* Label for toggle. Explains that in private browsing mode, the search suggestions which appears at the top of the search bar, can be toggled on or off. Located in the Private Session section in the Search page in the Settings menu. */ +"Settings.Search.PrivateSession.Setting.v122" = "Prikaži prijedloge u privatnom pregledavanju"; + +/* Label for toggle. Explains that in private browsing mode, the search suggestions which appears at the top of the search bar, can be toggled on or off. Located in `Suggestions from Search Engines` and `Address Bar - Firefox Suggest` sections in the Search page in the Settings menu. */ +"Settings.Search.PrivateSession.Setting.v124" = "Prikaži u privatnim sesijama"; + +/* Title for the `Private Browsing` settings section in the Search page in the Settings menu. */ +"Settings.Search.PrivateSession.Title.v122" = "Privatno pregledavanje"; + +/* Title for quick-search engines settings section in the Search page in the Settings menu. */ +"Settings.Search.QuickEnginesTitle.v121" = "Tražilice za brzo pretraživanje"; + +/* Label for the `show search suggestions` setting, in the Search Settings page. */ +"Settings.Search.ShowSuggestions.v121" = "Prikaži prijedloge pretraživanja"; + +/* In the Search page of the Settings menu, the title for the setting to enable search browsing history. */ +"Settings.Search.Suggest.SearchBrowsingHistory.Title.v124" = "Pretraži povijest pregledavanja"; + +/* In the Search page of the Settings menu, the title for the setting to enable search bookmarks. */ +"Settings.Search.Suggest.SearchSearchBookmarks.Title.v124" = "Pretraži zabilješke"; + +/* In the Search page of the Settings menu, the title for the setting to enable synced tabs. */ +"Settings.Search.Suggest.SearchSyncedTabs.Title.v124" = "Pretraži sinkronizirane kartice"; + +/* In the Search page of the Settings menu, the title for setting to enable Suggestions from Firefox. Placeholder is for the app name - Firefox. */ +"Settings.Search.Suggest.ShowNonSponsoredSuggestions.Title.v124" = "Prijedlozi od %@"; + +/* In the Search page of the Settings menu, the title for setting to enable Suggestions from the web in Firefox. */ +"Settings.Search.Suggest.ShowNonSponsoredSuggestions.Title.v124.v2" = "Prijedlozi od weba"; + +/* In the Search page of the Settings menu, the title for the setting to enable Suggestions from sponsors. */ +"Settings.Search.Suggest.ShowSponsoredSuggestions.Title.v124" = "Prijedlozi od sponzora"; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/Shopping.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/Shopping.strings new file mode 100644 index 000000000000..044aad3fcf07 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/Shopping.strings @@ -0,0 +1,126 @@ +/* Contextual hints are little popups that appear for the users informing them of new features. This one is a call to action for the popup describing the Shopping feature. It indicates that a user can go directly to the Shopping feature by tapping the text of the action. */ +"ContextualHints.Shopping.NotOptedInAction.v120" = "Probaj provjeru recenzija"; + +/* Contextual hints are little popups that appear for the users informing them of new features. This is a call to action for the popup that appears after the user has opted in for the Shopping feature. It indicates that a user can directly open the review checker by tapping the text of the action. */ +"ContextualHints.Shopping.OptedInAction.v120" = "Otvori provjeru recenzija"; + +/* Description adjusted of the rating card displayed in the shopping review quality bottom sheet. */ +"Shopping.AdjustedRating.Description.v121" = "Na temelju pouzdanih recenzija"; + +/* Accessibility label, associated to adjusted rating stars. %@ is a decimal value from 0 to 5 that will only use a tenth (example: 3.5). */ +"Shopping.AdjustedRating.StarsAccessibilityLabel.v120" = "%@ od 5 zvjezdica"; + +/* Title of the adjusted rating card displayed in the shopping review quality bottom sheet. */ +"Shopping.AdjustedRating.Title.v120" = "Prilagođena ocjena"; + +/* Button text of the confirmation displayed in the shopping review quality bottom sheet. */ +"Shopping.ConfirmationCard.Button.Text.v120" = "Razumijem"; + +/* Title of the confirmation displayed in the shopping review quality bottom sheet. */ +"Shopping.ConfirmationCard.Title.v120" = "Analiza je aktualna"; + +/* Section title of the review highlights displayed in the shopping review quality bottom sheet. */ +"Shopping.HighlightsCard.Competitiveness.Title.v120" = "Konkurentnost"; + +/* Title of the button that shows less reviews in the review highlights displayed in the shopping review quality bottom sheet. */ +"Shopping.HighlightsCard.LessButton.Title.v120" = "Prikaži manje"; + +/* Title of the button that shows more reviews in the review highlights displayed in the shopping review quality bottom sheet. */ +"Shopping.HighlightsCard.MoreButton.Title.v120" = "Prikaži više"; + +/* Section title of the review highlights displayed in the shopping review quality bottom sheet, specifically focusing on the quality, design, and condition of the product's packaging. This may include details about the box, protective materials, presentation, and overall packaging experience. */ +"Shopping.HighlightsCard.Packaging.Title.v120" = "Ambalaža"; + +/* Section title of the review highlights displayed in the shopping review quality bottom sheet. */ +"Shopping.HighlightsCard.Price.Title.v120" = "Cijena"; + +/* Section title of the review highlights displayed in the shopping review quality bottom sheet. */ +"Shopping.HighlightsCard.Quality.Title.v120" = "Kvaliteta"; + +/* Section title of the review highlights displayed in the shopping review quality bottom sheet. */ +"Shopping.HighlightsCard.Shipping.Title.v120" = "Dostava"; + +/* Primary action title for info card when the product needs analysis */ +"Shopping.InfoCard.NeedsAnalysis.PrimaryAction.v120" = "Provjeri sada"; + +/* Title for the information card displayed by the review checker feature when the product the user is looking at is out of stock. This title is used for info card where the user can report if it's back in stock. */ +"Shopping.InfoCard.ProductNotInStock.Title.v121" = "Proizvod nije dostupan"; + +/* Description for info card when the product is in analysis mode */ +"Shopping.InfoCard.ProgressAnalysis.Description.v120" = "To bi moglo potrajati oko 60 sekundi."; + +/* Text for the main button of the Shopping Experience Opt In onboarding Card (Fakespot) */ +"Shopping.OptInCard.MainButton.Title.v120" = "Da, probaj"; + +/* Show Firefox Browser Privacy Policy page from the Privacy section in the Shopping Experience Opt In onboarding Card (Fakespot). See https://www.mozilla.org/privacy/firefox/ */ +"Shopping.OptInCard.PrivacyPolicy.Button.Title.v120" = "Politika privatnosti"; + +/* Show Firefox Browser Privacy Policy page from the Privacy section in the Shopping Experience Opt In onboarding Card (Fakespot). The parameter will be replace by the Firefox app name. */ +"Shopping.OptInCard.PrivacyPolicy.Button.Title.v123" = "%@ politika privatnosti"; + +/* Text for the secondary button of the Shopping Experience Opt In onboarding Card (Fakespot) */ +"Shopping.OptInCard.SecondaryButton.Title.v120" = "Ne sada"; + +/* Show Firefox Browser Terms of Use page from the Privacy section in the Shopping Experience Opt In onboarding Card (Fakespot). See https://www.mozilla.org/privacy/firefox/ */ +"Shopping.OptInCard.TermsOfUse.Button.Title.v120" = "Uvjeti korištenja"; + +/* Show Fakespot Terms of Use page in the Shopping Experience Opt In onboarding Card (Fakespot). The parameter will be replace by the Fakespot name. */ +"Shopping.OptInCard.TermsOfUse.Button.Title.v123" = "%@ uvjeti korištenja"; + +/* Accessibility label for the Grade labels used in 'How we determine review quality' card and 'How reliable are these reviews' card displayed in the shopping review quality bottom sheet. The placeholder will be replaced by a grade letter (e.g. A). The grading system contains letters from A-F. */ +"Shopping.ReliabilityScore.Grade.A11y.Label.v120" = "Ocjena %@"; + +/* Title of the reliability card displayed in the shopping review quality bottom sheet. */ +"Shopping.ReviewQuality.ReliabilityCardTitle.v120" = "Koliko su te recenzije pouzdane?"; + +/* Description of the reliability ratings for rating 'A' and 'B' displayed in the shopping review quality bottom sheet. */ +"Shopping.ReviewQuality.ReliabilityRating.AB.Description.v120" = "Pouzdane recenzije"; + +/* Description of the reliability rating 'C' displayed in the shopping review quality bottom sheet. */ +"Shopping.ReviewQuality.ReliabilityRating.C.Description.v120" = "Mješavina pouzdanih i nepouzdanih recenzija"; + +/* Description of the reliability ratings for rating 'D' and 'F' displayed in the shopping review quality bottom sheet. */ +"Shopping.ReviewQuality.ReliabilityRating.DF.Description.v120" = "Nepouzdane recenzije"; + +/* Title of the 'How we determine review quality' card displayed in the shopping review quality bottom sheet. */ +"Shopping.ReviewQualityCard.Label.Title.v120" = "Kako određujemo kvalitetu recenzija"; + +/* Label of the sub headline from How we determine review quality card displayed in the shopping review quality bottom sheet. The *text inside asterisks* denotes part of the string to bold, please leave the text inside the '*' so that it is bolded correctly. */ +"Shopping.ReviewQualityCard.SubHeadline.Label.v120" = "Svakoj recenziji proizvoda dodjeljujemo *slovnu ocjenu* od A do F."; + +/* Accessibility label for the up chevron icon used to collapse or minimize the Settings Card within the shopping product review bottom sheet. */ +"Shopping.SettingsCard.Collapse.AccessibilityLabel.v120" = "Sklopi karticu postavki"; + +/* Accessibility label for the down chevron icon used to expand or show the details of the Settings Card within the shopping product review bottom sheet. */ +"Shopping.SettingsCard.Expand.AccessibilityLabel.v120" = "Rasklopi karticu postavki"; + +/* Accessibility hint for the recommended products label and switch, grouped together. When the group is selected in VoiceOver mode, the hint is read to help the user understand what action can be performed. */ +"Shopping.SettingsCard.Expand.GroupedRecommendedProductsAndSwitch.AccessibilityHint.v123" = "Dodirni dvaput za mijenjanje postavke."; + +/* Title of the settings card displayed in the shopping review quality bottom sheet. */ +"Shopping.SettingsCard.Label.Title.v120" = "Postavke"; + +/* Label of the switch from settings card displayed in the shopping review quality bottom sheet. The placeholder will be replaced with the app name. */ +"Shopping.SettingsCard.RecommendedProducts.Label.v120" = "Prikaži proizvode koje preporučuje %@"; + +/* Toggled Off accessibility switch value from Settings Card within the shopping product review bottom sheet. */ +"Shopping.SettingsCard.SwitchValueOff.AccessibilityLabel.v123" = "Isključeno"; + +/* Toggled On accessibility value, from Settings Card within the shopping product review bottom sheet. */ +"Shopping.SettingsCard.SwitchValueOn.AccessibilityLabel.v123" = "Uključeno"; + +/* Label of the button from settings card displayed in the shopping review quality bottom sheet. */ +"Shopping.SettingsCard.TurnOffButton.Title.v120" = "Isključi provjeru recenzija"; + +/* Beta label for the header of the Shopping Experience (Fakespot) sheet */ +"Shopping.Sheet.Beta.Title.v120" = "BETA"; + +/* Accessibility label for close button that dismisses the Shopping Experience (Fakespot) sheet. */ +"Shopping.Sheet.Close.AccessibilityLabel.v121" = "Zatvori provjeru recenzija"; + +/* Label for the header of the Shopping Experience (Fakespot) sheet */ +"Shopping.Sheet.Title.v120" = "Provjera recenzija"; + +/* Title for error card displayed to the user when the device is disconnected from the network. */ +"Shopping.WarningCard.CheckNoConnection.Title.v120" = "Nema mrežne veze"; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/SnackBar.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/SnackBar.strings index 50dc8d4ab2d6..26d62b8858c7 100644 --- a/firefox-ios/Shared/Supporting Files/hr.lproj/SnackBar.strings +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/SnackBar.strings @@ -4,3 +4,6 @@ /* Label text that gets presented as a confirmation at the bottom of screen when credit card information gets saved successfully */ "CreditCard.SnackBar.SavedCardLabel.v112" = "Nova kartica spremljena"; +/* Label text that gets presented as a confirmation at the bottom of screen when credit card information gets updated successfully */ +"CreditCard.SnackBar.UpdatedCardLabel.v122" = "Podaci kreditne kartice su aktulizirani"; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/TabLocation.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/TabLocation.strings new file mode 100644 index 000000000000..6d59a3af9a10 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/TabLocation.strings @@ -0,0 +1,36 @@ +/* Accessibility hint for the reload button */ +"Address.Bar.Reload.A11y.Hint.v124" = "Dodirni dvaput i drži pritisnuto za više opcija"; + +/* Accessibility label for the security icon in url bar */ +"TabLocation.ETP.Off.NotSecure.A11y.Label.v119" = "Veza nije sigurna. Poboljšana zaštita od praćenja je isključena."; + +/* Accessibility label for the security icon in url bar */ +"TabLocation.ETP.Off.Secure.A11y.Label.v119" = "Veza nije sigurna. Poboljšana zaštita od praćenja je isključena."; + +/* Accessibility label for the security icon in url bar */ +"TabLocation.ETP.On.NotSecure.A11y.Label.v119" = "Veza nije sigurna"; + +/* Accessibility label for the security icon in url bar */ +"TabLocation.ETP.On.Secure.A11y.Label.v119" = "Sigurna veza"; + +/* Accessibility label for the lock / tracking protection button on the URL bar */ +"TabLocation.LockButton.AccessibilityLabel.v122" = "Zaštita od praćenja"; + +/* Large content title for the lock button. This title is displayed when accessible font sizes are enabled */ +"TabLocation.LockButton.LargeContentTitle.v122" = "Zaštita od praćenja"; + +/* Accessibility label for the share button in url bar */ +"TabLocation.Share.A11y.Label.v119" = "Dijeli ovu stranicu"; + +/* Large content title for the share button. This title is displayed when using accessible font sizes is enabled */ +"TabLocation.ShareButton.AccessibilityLabel.v122" = "Dijeli"; + +/* Accessibility label for the shopping button in url bar */ +"TabLocation.Shopping.A11y.Label.v120" = "Provjera recenzija"; + +/* Large content title for the tabs button. The argument is the number of open tabs or an infinity symbol. This title is displayed when using accessible font sizes is enabled. */ +"TabsButton.Accessibility.LargeContentTitle.v122" = "Prikaži kartice: %@"; + +/* Large content title for the button shown in editing mode to remove this site from the top sites panel. */ +"TopSites.RemoveButton.LargeContentTitle.v122" = "Ukloni stranicu"; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/TabsTray.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/TabsTray.strings index 68ddcb222ea4..f355df56602e 100644 --- a/firefox-ios/Shared/Supporting Files/hr.lproj/TabsTray.strings +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/TabsTray.strings @@ -4,6 +4,12 @@ /* When the user closes an individual tab in the tab tray, a popup will appear informing them the tab was closed. This is the text for the popup. */ "CloseTabsToast.SingleTabTitle.v113" = "Kartica zatvorena"; +/* When the user closes tabs in the tab tray, a popup will appear informing them how many tabs were closed. This is the text for the popup. The placeholder is the number of tabs */ +"CloseTabsToast.Title.v113" = "Zatvorene kartice: %d"; + /* This is the swipe action title for closing an inactive tab by swiping, located in the Inactive Tabs section of the Tabs Tray */ "InactiveTabs.TabTray.CloseSwipeActionTitle.v115" = "Zatvori"; +/* Button label to sync tabs in your account */ +"TabsTray.SyncTabs.SyncTabsButton.Title.v119" = "Sinkroniziraj kartice"; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/Toolbar.strings new file mode 100644 index 000000000000..54f9c4de7caa --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/Toolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Nova kartica"; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/UpdateCard.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/UpdateCard.strings index 3983b3a77c6c..da633dbbfb1b 100644 --- a/firefox-ios/Shared/Supporting Files/hr.lproj/UpdateCard.strings +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/UpdateCard.strings @@ -1,6 +1,15 @@ +/* This value is used as the toast message for the saving success alert in the remember credit card page */ +"CreditCard.RememberCard.SecondaryButtonTitle.v116" = "Podaci kreditne kartice su aktulizirani"; + +/* This value is used as the title for the update card page */ +"CreditCard.UpdateCard.MainTitle.v122" = "Aktualizirati kreditnu karticu?"; + /* This value is used as the title for the Manage Cards button from the update credit card page */ "CreditCard.UpdateCard.ManageCardsButtonTitle.v115" = "Upravljaj karticama"; /* This value is used as the title for the Not Now button in the update credit card page */ "CreditCard.UpdateCard.NotNowButtonTitle.v115" = "Ne sada"; +/* This value is used as the title for the button in the update credit card page. It indicates the action to update the details f9 the card. */ +"CreditCard.UpdateCard.YesButtonTitle.v122" = "Aktualiziraj"; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/ZoomPageBar.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/ZoomPageBar.strings new file mode 100644 index 000000000000..6f570b6cf2cc --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/ZoomPageBar.strings @@ -0,0 +1,12 @@ +/* Accessibility label for closing the zoom panel in Zoom Page Bar */ +"Menu.ZoomPage.Close.AccessibilityLabel.v113" = "Zatvori ploču zumiranja"; + +/* Accessibility label for current zoom level in Zoom Page Bar. The placeholder represents the zoom level */ +"Menu.ZoomPage.CurrentZoomLevel.AccessibilityLabel.v113" = "Trenutačna razina zumiranja: %@"; + +/* Accessibility label for decreasing the zoom level in Zoom Page Bar */ +"Menu.ZoomPage.DecreaseZoom.AccessibilityLabel.v113" = "Smanji razinu zumiranja"; + +/* Accessibility label for increasing the zoom level in Zoom Page Bar */ +"Menu.ZoomPage.IncreaseZoom.AccessibilityLabel.v113" = "Povećaj razinu zumiranja"; + diff --git a/firefox-ios/Shared/Supporting Files/hsb.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/hsb.lproj/Microsurvey.strings index 7ae91fd64dbd..43913174b85f 100644 --- a/firefox-ios/Shared/Supporting Files/hsb.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/hsb.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Njewubrany"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Naprašowanje"; + diff --git a/firefox-ios/Shared/Supporting Files/hsb.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/hsb.lproj/Toolbar.strings index 915c4b516f0c..602ce3e2508d 100644 --- a/firefox-ios/Shared/Supporting Files/hsb.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/hsb.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Nowy rajtark"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Tutón rajtark začinić"; + diff --git a/firefox-ios/Shared/Supporting Files/hy-AM.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/hy-AM.lproj/Microsurvey.strings index 040a2d1b2d3d..51ff09165334 100644 --- a/firefox-ios/Shared/Supporting Files/hy-AM.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/hy-AM.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Ապանշված"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Հարցում"; + diff --git a/firefox-ios/Shared/Supporting Files/hy-AM.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/hy-AM.lproj/Toolbar.strings index 87db8eee8d13..7dba3131d55d 100644 --- a/firefox-ios/Shared/Supporting Files/hy-AM.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/hy-AM.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Նոր ներդիր"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Փակել այս ներդիրը"; + diff --git a/firefox-ios/Shared/Supporting Files/ia.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/ia.lproj/Microsurvey.strings index 4dd776757c8f..02c40bd361db 100644 --- a/firefox-ios/Shared/Supporting Files/ia.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/ia.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "De-seligite"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Questionario"; + diff --git a/firefox-ios/Shared/Supporting Files/ia.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/ia.lproj/Toolbar.strings index 238d35aa1633..34a5654643ab 100644 --- a/firefox-ios/Shared/Supporting Files/ia.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/ia.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Nove scheda"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Clauder iste scheda"; + diff --git a/firefox-ios/Shared/Supporting Files/is.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/is.lproj/Microsurvey.strings index 757f6f1429a1..698760dc35a8 100644 --- a/firefox-ios/Shared/Supporting Files/is.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/is.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Óvalið"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Könnun"; + diff --git a/firefox-ios/Shared/Supporting Files/is.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/is.lproj/Toolbar.strings index ae327d8f3585..042daa71f003 100644 --- a/firefox-ios/Shared/Supporting Files/is.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/is.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Nýr flipi"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Loka þessum flipa"; + diff --git a/firefox-ios/Shared/Supporting Files/it.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/it.lproj/Microsurvey.strings index 240e565da150..10a2f5ed6a5c 100644 --- a/firefox-ios/Shared/Supporting Files/it.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/it.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Non selezionato"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Sondaggio"; + diff --git a/firefox-ios/Shared/Supporting Files/it.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/it.lproj/Toolbar.strings index 58f5638fe011..62b31c38dac6 100644 --- a/firefox-ios/Shared/Supporting Files/it.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/it.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Nuova scheda"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Chiudi questa scheda"; + diff --git a/firefox-ios/Shared/Supporting Files/ja.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/ja.lproj/Microsurvey.strings index e27c4c36936a..19955a0a862c 100644 --- a/firefox-ios/Shared/Supporting Files/ja.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/ja.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "未選択"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "アンケート"; + diff --git a/firefox-ios/Shared/Supporting Files/ja.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/ja.lproj/Toolbar.strings index 9c8d5e15bd21..aee165744cf6 100644 --- a/firefox-ios/Shared/Supporting Files/ja.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/ja.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "新規タブ"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "このタブを閉じる"; + diff --git a/firefox-ios/Shared/Supporting Files/kk.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/kk.lproj/Microsurvey.strings index d236b2bfb09b..53d6d71fe159 100644 --- a/firefox-ios/Shared/Supporting Files/kk.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/kk.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Таңдаудан алынды"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Сауалнама"; + diff --git a/firefox-ios/Shared/Supporting Files/kk.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/kk.lproj/Toolbar.strings index 1c21c2d5fa11..fde9c6709a66 100644 --- a/firefox-ios/Shared/Supporting Files/kk.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/kk.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Жаңа бет"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Бұл бетті жабу"; + diff --git a/firefox-ios/Shared/Supporting Files/ko.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/ko.lproj/Microsurvey.strings index 5c590bf04a75..34eb095ffc34 100644 --- a/firefox-ios/Shared/Supporting Files/ko.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/ko.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "선택 해제됨"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "조사"; + diff --git a/firefox-ios/Shared/Supporting Files/ko.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/ko.lproj/Toolbar.strings index 5dfb97d7645b..6d712f4c53bb 100644 --- a/firefox-ios/Shared/Supporting Files/ko.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/ko.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "새 탭"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "이 탭 닫기"; + diff --git a/firefox-ios/Shared/Supporting Files/nb.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/nb.lproj/EditAddress.strings index f3891e7b73b3..5c4ce4c0665f 100644 --- a/firefox-ios/Shared/Supporting Files/nb.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/nb.lproj/EditAddress.strings @@ -124,3 +124,18 @@ /* Toast message confirming that an address has been successfully removed. */ "Addresses.Toast.AddressRemovedConfirmation.v129" = "Adresse fjernet"; +/* Toast message confirming that an address has been successfully saved. */ +"Addresses.Toast.AddressSavedConfirmation.v129" = "Adresse lagret"; + +/* Toast message indicating an error occurred while trying to save an address. */ +"Addresses.Toast.AddressSaveError.v129" = "Klarte ikke å lagre adressen"; + +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Klarte ikke å fjerne adressen"; + +/* Suggestion to try again after an error occurred while trying to save an address. */ +"Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Prøv igjen"; + +/* Toast message confirming that an address has been successfully updated. */ +"Addresses.Toast.AddressUpdatedConfirmation.v129" = "Adresseinformasjon oppdatert"; + diff --git a/firefox-ios/Shared/Supporting Files/nb.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/nb.lproj/EnhancedTrackingProtection.strings index 9f4574838281..4d028ea976b5 100644 --- a/firefox-ios/Shared/Supporting Files/nb.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/nb.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,15 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Tilkoblingen er ikke sikker"; +/* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Sporingsinfokapsler på tvers av nettsteder: %@"; + +/* Text to let users know how many fingerprinters were blocked on the current website. The placeholder will show the number of fingerprinters detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.Fingerprinter.v129" = "Nettleseravtrykksporere: %@"; + +/* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Sporing via sosiale medier: %@"; + /* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked Text to let users know that no trackers were found on the current website. */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Sporere blokkert: %@"; @@ -54,6 +63,9 @@ /* A switch to disable enhanced tracking protection inside the menu. */ "Menu.EnhancedTrackingProtection.SwitchOff.Text.v128" = "Beskyttelser er AV. Vi foreslår at du slår den på igjen."; +/* A switch to disable enhanced tracking protection inside the menu. */ +"Menu.EnhancedTrackingProtection.SwitchOff.Text.v129" = "Beskyttelser er AV. Vi foreslår at du slår dem på igjen."; + /* A switch to disable enhanced tracking protection inside the menu. */ "Menu.EnhancedTrackingProtection.SwitchOn.Text.v128" = "Hvis noe ser ødelagt ut på dette nettstedet, prøv å slå det av."; diff --git a/firefox-ios/Shared/Supporting Files/nb.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/nb.lproj/Microsurvey.strings index fa157b1dfcb8..453a11b431d5 100644 --- a/firefox-ios/Shared/Supporting Files/nb.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/nb.lproj/Microsurvey.strings @@ -31,6 +31,9 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the title for the header on the screen. */ "Microsurvey.Survey.HeaderLabel.v127" = "Gjennomfør denne undersøkelsen"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the title for the header on the screen. */ +"Microsurvey.Survey.HeaderLabel.v129" = "Fyll ut spørreundersøkelsen"; + /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the logo image that appears on the bottom sheet that informs the user that it is coming from the app specifically. Placeholder is for the app name. */ "Microsurvey.Survey.LogoImage.AccessibilityLabel.v129" = "%@-logo"; @@ -49,6 +52,9 @@ /* On the microsurvey, this is the title for one of the options that the user can select to answer the survey. */ "Microsurvey.Survey.Options.LikertScaleOption5.v127" = "Veldig misfornøyd"; +/* On the microsurvey, this is the title for one of the options that the user can select to answer the survey. It indicates that the user has not use the feature that the survey is inquiring about. */ +"Microsurvey.Survey.Options.LikertScaleOption6.v129" = "Jeg bruker den ikke"; + /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states the order the survey option in the list of options. First placeholder is the number the option is in the list and the second placeholder is the total number of options such as 1 out of 6. */ "Microsurvey.Survey.OptionsOrder.AccessibilityLabel.v129" = "%1$@ av %2$@"; @@ -61,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Ikke valgt"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Spørreundersøkelse"; + diff --git a/firefox-ios/Shared/Supporting Files/nb.lproj/PasswordAutofill.strings b/firefox-ios/Shared/Supporting Files/nb.lproj/PasswordAutofill.strings index 155ef39c7dae..e47aafd49c12 100644 --- a/firefox-ios/Shared/Supporting Files/nb.lproj/PasswordAutofill.strings +++ b/firefox-ios/Shared/Supporting Files/nb.lproj/PasswordAutofill.strings @@ -1,3 +1,6 @@ +/* This label is used in a cell found in the list of autofill login options in place of an actual username to denote that no username was saved for this login */ +"PasswordAutofill.LoginListCellNoUsername.v129" = "(ingen brukernavn)"; + /* This label is used for a button in the password list screen allowing users to manage their saved passwords. It's meant to direct users to where they can add, remove, or edit their saved passwords. */ "PasswordAutofill.ManagePasswordsButton.v124" = "Behandle passord"; diff --git a/firefox-ios/Shared/Supporting Files/nb.lproj/ScanQRCode.strings b/firefox-ios/Shared/Supporting Files/nb.lproj/ScanQRCode.strings new file mode 100644 index 000000000000..d943b5da03d2 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/nb.lproj/ScanQRCode.strings @@ -0,0 +1,9 @@ +/* Allow button to open URL from scanned QR Code */ +"ScanQRCode.ConfirmOpenURL.AllowButton.v129" = "Tillat"; + +/* Deny button to cancel opening URL from scanned QR Code */ +"ScanQRCode.ConfirmOpenURL.DenyButton.v129" = "Avvis"; + +/* Text of the prompt to ask user permission to open a URL from a scanned QR code. Placeholder is app name. */ +"ScanQRCode.ConfirmOpenURL.Message.v129" = "Tillate %@ å åpne?"; + diff --git a/firefox-ios/Shared/Supporting Files/nb.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/nb.lproj/Toolbar.strings new file mode 100644 index 000000000000..785b809932a2 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/nb.lproj/Toolbar.strings @@ -0,0 +1,6 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Ny fane"; + +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Lukk denne fanen"; + diff --git a/firefox-ios/Shared/Supporting Files/nl.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/nl.lproj/Microsurvey.strings index 688108f1f609..65abf1d6bdbf 100644 --- a/firefox-ios/Shared/Supporting Files/nl.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/nl.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Selectie opgeheven"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Enquête"; + diff --git a/firefox-ios/Shared/Supporting Files/nl.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/nl.lproj/Toolbar.strings index ccd4752f79b7..06fd629912eb 100644 --- a/firefox-ios/Shared/Supporting Files/nl.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/nl.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Nieuw tabblad"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Dit tabblad sluiten"; + diff --git a/firefox-ios/Shared/Supporting Files/nn.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/nn.lproj/Microsurvey.strings index f60d820cea11..34df20a30b6b 100644 --- a/firefox-ios/Shared/Supporting Files/nn.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/nn.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Ikkje valt"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Undersøking"; + diff --git a/firefox-ios/Shared/Supporting Files/nn.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/nn.lproj/Toolbar.strings index 54abf2257395..b354df12f664 100644 --- a/firefox-ios/Shared/Supporting Files/nn.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/nn.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Ny fane"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Lat att denne fana"; + diff --git a/firefox-ios/Shared/Supporting Files/pa-IN.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/pa-IN.lproj/Microsurvey.strings index f1b1ad1dc079..8743760f68ad 100644 --- a/firefox-ios/Shared/Supporting Files/pa-IN.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/pa-IN.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "ਨਾ-ਚੁਣਿਆ"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "ਸਰਵੇਖਣ"; + diff --git a/firefox-ios/Shared/Supporting Files/pa-IN.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/pa-IN.lproj/Toolbar.strings index 05f9d815bc83..f5b3a5a7dbae 100644 --- a/firefox-ios/Shared/Supporting Files/pa-IN.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/pa-IN.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "ਨਵੀਂ ਟੈਬ"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "ਇਸ ਟੈਬ ਨੂੰ ਬੰਦ ਕਰੋ"; + diff --git a/firefox-ios/Shared/Supporting Files/pt-BR.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/pt-BR.lproj/Microsurvey.strings index f4533738be92..9e9f25aa683c 100644 --- a/firefox-ios/Shared/Supporting Files/pt-BR.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/pt-BR.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Não selecionado"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Pesquisa de opinião"; + diff --git a/firefox-ios/Shared/Supporting Files/pt-BR.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/pt-BR.lproj/Toolbar.strings index 79a59ed9dba8..3d5607320715 100644 --- a/firefox-ios/Shared/Supporting Files/pt-BR.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/pt-BR.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Nova aba"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Fechar esta aba"; + diff --git a/firefox-ios/Shared/Supporting Files/pt-PT.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/pt-PT.lproj/Microsurvey.strings index a676e54e3a52..b98f2157994a 100644 --- a/firefox-ios/Shared/Supporting Files/pt-PT.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/pt-PT.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Não selecionado"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Inquérito"; + diff --git a/firefox-ios/Shared/Supporting Files/pt-PT.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/pt-PT.lproj/Toolbar.strings index c2e904d4eea7..45d8fca515c3 100644 --- a/firefox-ios/Shared/Supporting Files/pt-PT.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/pt-PT.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Novo separador"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Fechar este separador"; + diff --git a/firefox-ios/Shared/Supporting Files/ru.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/ru.lproj/Microsurvey.strings index a79498557dc3..dcb8f46e83ce 100644 --- a/firefox-ios/Shared/Supporting Files/ru.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/ru.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Выбор снят"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Опрос"; + diff --git a/firefox-ios/Shared/Supporting Files/ru.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/ru.lproj/Toolbar.strings index 9070c6c4cba3..5dbc6cf45a90 100644 --- a/firefox-ios/Shared/Supporting Files/ru.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/ru.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Новая вкладка"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Закрыть эту вкладку"; + diff --git a/firefox-ios/Shared/Supporting Files/sk.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/sk.lproj/Microsurvey.strings index 1e2bafbb5e70..7322694117aa 100644 --- a/firefox-ios/Shared/Supporting Files/sk.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/sk.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Nezvolená"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Prieskum"; + diff --git a/firefox-ios/Shared/Supporting Files/sk.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/sk.lproj/Toolbar.strings index c23c52c9108a..866b50dbbdab 100644 --- a/firefox-ios/Shared/Supporting Files/sk.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/sk.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Nová karta"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Zavrieť túto kartu"; + diff --git a/firefox-ios/Shared/Supporting Files/sv.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/sv.lproj/Microsurvey.strings index 8fac7badc9ba..d574f8a2e4a5 100644 --- a/firefox-ios/Shared/Supporting Files/sv.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/sv.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Ej vald"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Undersökning"; + diff --git a/firefox-ios/Shared/Supporting Files/sv.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/sv.lproj/Toolbar.strings index 580543ef3975..165a455f4189 100644 --- a/firefox-ios/Shared/Supporting Files/sv.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/sv.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Ny flik"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Stäng denna flik"; + diff --git a/firefox-ios/Shared/Supporting Files/tr.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/tr.lproj/Microsurvey.strings index 485c8c8ef097..43bf0715932f 100644 --- a/firefox-ios/Shared/Supporting Files/tr.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/tr.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Seçilmedi"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Anket"; + diff --git a/firefox-ios/Shared/Supporting Files/tr.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/tr.lproj/Toolbar.strings index 18d25f2411dd..3452401fd8c6 100644 --- a/firefox-ios/Shared/Supporting Files/tr.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/tr.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Yeni sekme"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Bu sekmeyi kapat"; + diff --git a/firefox-ios/Shared/Supporting Files/ug.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/ug.lproj/Microsurvey.strings index 62b655d0f3d6..08d00ef18313 100644 --- a/firefox-ios/Shared/Supporting Files/ug.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/ug.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "تاللانمىدى"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "راي سىناش"; + diff --git a/firefox-ios/Shared/Supporting Files/ug.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/ug.lproj/Toolbar.strings index 3c17178827ed..967125334676 100644 --- a/firefox-ios/Shared/Supporting Files/ug.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/ug.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "يېڭى بەتكۈچ"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "بۇ بەتكۈچنى ياپ"; + diff --git a/firefox-ios/Shared/Supporting Files/vi.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/vi.lproj/Microsurvey.strings index 81a4cf3bc51b..951dc273d24b 100644 --- a/firefox-ios/Shared/Supporting Files/vi.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/vi.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Đã bỏ chọn"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Khảo sát"; + diff --git a/firefox-ios/Shared/Supporting Files/vi.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/vi.lproj/Toolbar.strings index e29c3c989adf..c877d4a00d70 100644 --- a/firefox-ios/Shared/Supporting Files/vi.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/vi.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Thẻ mới"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Đóng thẻ này"; + diff --git a/firefox-ios/Shared/Supporting Files/zh-CN.lproj/Footer.strings b/firefox-ios/Shared/Supporting Files/zh-CN.lproj/Footer.strings index 6c7e3684ffc7..a51e29acc26d 100644 --- a/firefox-ios/Shared/Supporting Files/zh-CN.lproj/Footer.strings +++ b/firefox-ios/Shared/Supporting Files/zh-CN.lproj/Footer.strings @@ -1,5 +1,5 @@ /* This is the learn more text of the Pocket footer on Firefox Homepage. */ -"FirefoxHomepage.Pocket.Footer.LearnMore.v115" = "了解更多"; +"FirefoxHomepage.Pocket.Footer.LearnMore.v115" = "详细了解"; /* This is the title of the Pocket footer on Firefox Homepage. The first placeholder is for the Pocket app name and the second placeholder for the app name */ "FirefoxHomepage.Pocket.Footer.Title.v116" = "由 %2$@ 系列产品 - %1$@ 提供。"; diff --git a/firefox-ios/Shared/Supporting Files/zh-TW.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/zh-TW.lproj/Microsurvey.strings index 52e738c31555..53b990d0501f 100644 --- a/firefox-ios/Shared/Supporting Files/zh-TW.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/zh-TW.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "未選擇"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "問卷調查"; + diff --git a/firefox-ios/Shared/Supporting Files/zh-TW.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/zh-TW.lproj/Toolbar.strings index ba1ff910542a..3f0b9f5cca89 100644 --- a/firefox-ios/Shared/Supporting Files/zh-TW.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/zh-TW.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "開新分頁"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "關閉此分頁"; + diff --git a/firefox-ios/Shared/dsb.lproj/Localizable.strings b/firefox-ios/Shared/dsb.lproj/Localizable.strings index a8f575e784f6..dd5d94ccd497 100644 --- a/firefox-ios/Shared/dsb.lproj/Localizable.strings +++ b/firefox-ios/Shared/dsb.lproj/Localizable.strings @@ -167,7 +167,7 @@ "ContextMenu.ButtonToast.NewPrivateTabOpened.LabelText" = "Nowy priwatny rejtarik jo se wócynił"; /* The label text in the Button Toast for switching to a fresh New Private Tab. */ -"ContextMenu.ButtonToast.NewPrivateTabOpened.LabelText.v113" = "Nowy priwatny rejtark jo se wócynił"; +"ContextMenu.ButtonToast.NewPrivateTabOpened.LabelText.v113" = "Nowy priwatny rejtarik jo se wócynił"; /* The button text in the Button Toast for switching to a fresh New Tab. */ "ContextMenu.ButtonToast.NewTabOpened.ButtonText" = "Pśešaltowaś"; diff --git a/firefox-ios/Shared/dsb.lproj/Today.strings b/firefox-ios/Shared/dsb.lproj/Today.strings index 46387a413d56..b5df66daba7a 100644 --- a/firefox-ios/Shared/dsb.lproj/Today.strings +++ b/firefox-ios/Shared/dsb.lproj/Today.strings @@ -1,8 +1,8 @@ /* Close Private Tabs button label */ -"TodayWidget.ClosePrivateTabsButton" = "Priwatne rejtarki zacyniś"; +"TodayWidget.ClosePrivateTabsButton" = "Priwatne rejtariki zacyniś"; /* Close Private Tabs */ -"TodayWidget.ClosePrivateTabsLabelV2" = "Priwatne rejtarki zacyniś"; +"TodayWidget.ClosePrivateTabsLabelV2" = "Priwatne\nrejtariki zacyniś"; /* Description for medium size widget to add Firefox Shortcut to home screen */ "TodayWidget.FirefoxShortcutGalleryDescription" = "Pśidajśo swójej startowej wobrazowce zwězanja Firefox"; diff --git a/firefox-ios/Shared/hr.lproj/Localizable.strings b/firefox-ios/Shared/hr.lproj/Localizable.strings index 154042c2c97e..467c8e0d23e9 100644 --- a/firefox-ios/Shared/hr.lproj/Localizable.strings +++ b/firefox-ios/Shared/hr.lproj/Localizable.strings @@ -754,6 +754,9 @@ /* Label for the button, displayed in the menu, takes you to History screen when pressed. */ "Menu.History.Label" = "Povijest"; +/* Label for the new private tab button in the menu page. Pressing this button opens a new private tab. */ +"Menu.NewPrivateTab.Label" = "Nova privatna kartica"; + /* Label for the new tab button in the menu page. Pressing this button opens a new tab. */ "Menu.NewTab.v99" = "Nova kartica"; @@ -1141,6 +1144,9 @@ /* The placeholder for URL Field when saving a custom search engine */ "Settings.AddCustomEngine.URLPlaceholder" = "URL (Zamijeni upit s %s)"; +/* Title of setting to block opening external apps when pressing links. */ +"Settings.BlockOpeningExternalApps.Title" = "Blokiraj otvaranje eksternih aplikacija"; + /* Button in Data Management that clears all items. */ "Settings.ClearAllWebsiteData.Clear.Button" = "Obriši sve podatke web lokacije"; @@ -1240,6 +1246,9 @@ /* This is the description below the settings section located in the menu under customize current homepage. It describes what the options in the section are for. */ "Settings.Home.Current.Description.v101" = "Odaberi što se prikazuje kao početna stranica."; +/* In the settings menu, on the Firefox homepage customization section, this is the description below the section, describing what the options in the section are for. */ +"Settings.Home.Option.Description.v101" = "Odaberi što je uključeno na početnoj Firefox stranici."; + /* In the settings menu, in the Firefox homepage customization section, this is the title for the option that allows users to toggle the Jump Back In section on homepage on or off */ "Settings.Home.Option.JumpBackIn" = "Vrati se natrag"; @@ -1276,6 +1285,27 @@ /* In the settings menu, on the Firefox homepage customization section, this is the title for the option that allows users to access the wallpaper settings for the application. */ "Settings.Home.Option.Wallpaper" = "Pozadinska slika"; +/* In the settings menu, on the Firefox wallpaper customization screen, this is the accessibility string for the amethyst firefox wallpaper. */ +"Settings.Home.Option.Wallpaper.Accessibility.AmethystWallpaper.v99" = "Firefox pozadina, uzorak ametista."; + +/* In the settings menu, on the Firefox wallpaper customization screen, this is the title accessibility string for the beach hills firefox wallpaper. */ +"Settings.Home.Option.Wallpaper.Accessibility.BeachHillsWallpaper.v100" = "Firefox pozadina, uzorak brežuljaka na plaži."; + +/* In the settings menu, on the Firefox wallpaper customization screen, this is the title accessibility string for the cerulean firefox wallpaper. */ +"Settings.Home.Option.Wallpaper.Accessibility.CeruleanWallpaper.v99" = "Firefox pozadina, nebesko plavi uzorak."; + +/* In the settings menu, on the Firefox wallpaper customization screen, this is the accessibility string for the default wallpaper. */ +"Settings.Home.Option.Wallpaper.Accessibility.DefaultWallpaper.v99" = "Standardna pozadina."; + +/* In the settings menu, on the Firefox wallpaper customization screen, this is the title accessibility string for the sunrise firefox wallpaper. */ +"Settings.Home.Option.Wallpaper.Accessibility.SunriseWallpaper.v99" = "Firefox pozadina, uzorak izlaska sunca."; + +/* In the settings menu, on the Firefox wallpaper customization screen, this is the accessibility string of the toggle for turning wallpaper cycling shortcut on or off on the homepage. */ +"Settings.Home.Option.Wallpaper.Accessibility.ToggleButton" = "Prebacivanje pozadine početne stranice"; + +/* In the settings menu, on the Firefox wallpaper customization screen, this is the title accessibility string for the twilight hills firefox wallpaper. */ +"Settings.Home.Option.Wallpaper.Accessibility.TwilightHillsWallpaper.v100" = "Firefox pozadina, uzorak brda u sumraku."; + /* In the settings menu, on the Firefox wallpaper customization screen, this is the title of the group of wallpapers that are always available to the user. The %@ will be replaced by the app name and thus doesn't need translation. */ "Settings.Home.Option.Wallpaper.Classic.Title.v106" = "Klasični %@"; @@ -1372,6 +1402,9 @@ /* Description displayed under the ”Offer to Open Copied Link” option. See https://bug1223660.bmoattachments.org/attachment.cgi?id=8898349 */ "Settings.OfferClipboardBar.Status" = "Prilikom otvaranja Firefoxa"; +/* Description displayed under the ”Offer to Open Copied Link” option. See https://bug1223660.bmoattachments.org/attachment.cgi?id=8898349. Placeholder is for the app name. */ +"Settings.OfferClipboardBar.Status.v128" = "Prilikom otvaranja %@"; + /* Description displayed under the ”Offer to Open Copied Link” option. See https://bug1223660.bmoattachments.org/attachment.cgi?id=8898349 */ "Settings.OfferClipboardBar.StatusV2" = "Prilikom otvaranja Firefoxa"; diff --git a/firefox-ios/Shared/hr.lproj/LoginManager.strings b/firefox-ios/Shared/hr.lproj/LoginManager.strings index 0735b5467161..49fc1bab3ac3 100644 --- a/firefox-ios/Shared/hr.lproj/LoginManager.strings +++ b/firefox-ios/Shared/hr.lproj/LoginManager.strings @@ -16,6 +16,21 @@ /* Label for the button used to delete the current login. */ "Delete" = "Izbriši"; +/* Prompt option for cancelling out of deletion */ +"DeleteLoginAlert.DeleteButton.Cancel.v122" = "Odustani"; + +/* Label for the button used to delete the current login. */ +"DeleteLoginAlert.DeleteButton.Title.v122" = "Ukloni"; + +/* Prompt message warning the user that deleting non-synced logins will permanently remove them, when they attempt to do so */ +"DeleteLoginAlert.Message.Local.v122" = "Ovu radnju ne možeš poništiti."; + +/* Prompt message warning the user that deleted logins will remove logins from all connected devices */ +"DeleteLoginAlert.Message.Synced.v122" = "Ovo će ukloniti lozinku sa svih tvojih sinkroniziranih uređaja."; + +/* Title for the prompt that appears when the user deletes a login. */ +"DeleteLoginsAlert.Title.v122" = "Ukloniti lozinku?"; + /* Label for the button used to deselect all logins. */ "Deselect All" = "Poništi odabir"; @@ -37,6 +52,9 @@ /* Label displayed when no logins are found after searching. */ "No logins found" = "Nema pronađenih prijava"; +/* Label displayed when no logins are found after searching. */ +"NoLoginsFound.Title.v122" = "Nije pronađena nijedna lozinka"; + /* Open and Fill website text selection menu item */ "Open & Fill" = "Otvori i ispuni"; diff --git a/firefox-ios/Shared/hr.lproj/Menu.strings b/firefox-ios/Shared/hr.lproj/Menu.strings index 5640dd7951c9..b001ad1d153d 100644 --- a/firefox-ios/Shared/hr.lproj/Menu.strings +++ b/firefox-ios/Shared/hr.lproj/Menu.strings @@ -4,6 +4,12 @@ /* Label for the button, displayed in the menu, used to copy the current page link to the clipboard. */ "Menu.CopyLink.Title" = "Kopiraj poveznicu"; +/* Toast displayed to user after downlaod pdf was pressed. */ +"Menu.DownloadPDF.Confirm.v129" = "Uspješno preuzet PDF"; + +/* Label for the button, displayed in the menu, downloads a pdf when pressed. */ +"Menu.DownloadPDF.Label.v129" = "Preuzmi PDF"; + /* Label for the button, displayed in the menu, used to open the toolbar to search for text within the current page. */ "Menu.FindInPageAction.Title" = "Pronađi na stranici"; diff --git a/firefox-ios/Shared/hr.lproj/Search.strings b/firefox-ios/Shared/hr.lproj/Search.strings index bb70d75ed171..6686f1632be9 100644 --- a/firefox-ios/Shared/hr.lproj/Search.strings +++ b/firefox-ios/Shared/hr.lproj/Search.strings @@ -4,3 +4,6 @@ /* Label for search settings button. */ "Search Settings" = "Postavke pretraživanja"; +/* When making a new search from the awesome bar, suggestions appear to the user as they write new letters in their search. Different types of suggestions can appear. This string will be used as a label for sponsored Firefox suggestions. */ +"Search.SponsoredSuggestionDescription.v119" = "Sponzorirano"; + diff --git a/firefox-ios/Shared/zh-CN.lproj/PrivateBrowsing.strings b/firefox-ios/Shared/zh-CN.lproj/PrivateBrowsing.strings index 05f6dcdd71f8..5a0a50afab88 100644 --- a/firefox-ios/Shared/zh-CN.lproj/PrivateBrowsing.strings +++ b/firefox-ios/Shared/zh-CN.lproj/PrivateBrowsing.strings @@ -8,7 +8,7 @@ "Firefox won’t remember any of your history or cookies, but new bookmarks will be saved." = "Firefox 不会记住您的历史记录和 Cookie,但新的书签将被保留。"; /* Text button displayed when there are no tabs open while in private mode */ -"Learn More" = "了解更多"; +"Learn More" = "详细了解"; /* Toggled OFF accessibility value */ "Off" = "关"; From 1d432cfc5c4b8d89ac08ae225537ea570ab8fe40 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 5 Aug 2024 08:56:13 -0400 Subject: [PATCH 044/128] Auto update SPM with latest rust-component release 130.0.20240802050337 (#21436) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- firefox-ios/Client.xcodeproj/project.pbxproj | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- focus-ios/Blockzilla.xcodeproj/project.pbxproj | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/firefox-ios/Client.xcodeproj/project.pbxproj b/firefox-ios/Client.xcodeproj/project.pbxproj index b5811336f3d8..a179bfd86989 100644 --- a/firefox-ios/Client.xcodeproj/project.pbxproj +++ b/firefox-ios/Client.xcodeproj/project.pbxproj @@ -23117,7 +23117,7 @@ repositoryURL = "https://github.com/mozilla/rust-components-swift.git"; requirement = { kind = exactVersion; - version = 130.0.20240731050243; + version = 130.0.20240802050337; }; }; 435C85EE2788F4D00072B526 /* XCRemoteSwiftPackageReference "glean-swift" */ = { diff --git a/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 927a6d85cc32..9a5a09dc2c1a 100644 --- a/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -95,8 +95,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/mozilla/rust-components-swift.git", "state" : { - "revision" : "f1cdc3f52f87f69ffd408eacd79543ee3b50a83d", - "version" : "130.0.20240731050243" + "revision" : "4450df67aab6bc140d68a321d13a0a9edd297066", + "version" : "130.0.20240802050337" } }, { diff --git a/focus-ios/Blockzilla.xcodeproj/project.pbxproj b/focus-ios/Blockzilla.xcodeproj/project.pbxproj index 8df41435c417..5c52815e0fcc 100644 --- a/focus-ios/Blockzilla.xcodeproj/project.pbxproj +++ b/focus-ios/Blockzilla.xcodeproj/project.pbxproj @@ -7159,7 +7159,7 @@ repositoryURL = "https://github.com/mozilla/rust-components-swift"; requirement = { kind = exactVersion; - version = 130.0.20240731050243; + version = 130.0.20240802050337; }; }; 8A0E7F2C2BA0F0E0006BC6B6 /* XCRemoteSwiftPackageReference "Fuzi" */ = { diff --git a/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 354cb5b8866e..3eb239af581e 100644 --- a/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -51,8 +51,8 @@ "repositoryURL": "https://github.com/mozilla/rust-components-swift", "state": { "branch": null, - "revision": "f1cdc3f52f87f69ffd408eacd79543ee3b50a83d", - "version": "130.0.20240731050243" + "revision": "4450df67aab6bc140d68a321d13a0a9edd297066", + "version": "130.0.20240802050337" } }, { From 3e44763fcc03df0ced44ca702c771843d14abbf1 Mon Sep 17 00:00:00 2001 From: Cyndi Chin Date: Mon, 5 Aug 2024 10:13:21 -0400 Subject: [PATCH 045/128] Bugfix FXIOS-9762 [Unit Tests] Separate testQueryLogins into isolated tests (#21441) --- .../PasswordManagerViewModelTests.swift | 50 ++++++++++++------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/PasswordManagerViewModelTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/PasswordManagerViewModelTests.swift index 8ac444cd29c8..c583f3354f7c 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/PasswordManagerViewModelTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/PasswordManagerViewModelTests.swift @@ -26,7 +26,6 @@ class PasswordManagerViewModelTests: XCTestCase { ) self.dataSource = LoginDataSource(viewModel: self.viewModel) self.viewModel.setBreachAlertsManager(MockBreachAlertsClient()) - self.addLogins() } override func tearDown() { @@ -36,54 +35,71 @@ class PasswordManagerViewModelTests: XCTestCase { dataSource = nil } - private func addLogins() { + private func setupLogins() { _ = self.viewModel.profile.logins.wipeLocalEngine() + var expectations: [XCTestExpectation] = [] for i in (0..<10) { + let addExp = XCTestExpectation(description: "Adding login \(i) \(#function)\(#line)") + expectations.append(addExp) + let login = LoginEntry(fromJSONDict: [ "hostname": "https://example\(i).com", "formSubmitUrl": "https://example.com", "username": "username\(i)", "password": "password\(i)" ]) - let addExp = expectation(description: "\(#function)\(#line)") - self.viewModel.profile.logins.addLogin(login: login).upon { addResult in - XCTAssertTrue(addResult.isSuccess) - XCTAssertNotNil(addResult.successValue) - addExp.fulfill() + self.viewModel.profile.logins.addLogin(login: login) { result in + switch result { + case .success(let logins): + XCTAssertEqual(logins?.fields.origin, "https://example\(i).com") + addExp.fulfill() + case .failure: + XCTFail("Should not have failed") + } } } - - let logins = self.viewModel.profile.logins.listLogins().value - XCTAssertTrue(logins.isSuccess) - XCTAssertNotNil(logins.successValue) - - waitForExpectations(timeout: 10.0, handler: nil) + wait(for: expectations, timeout: 10.0) } - func testQueryLogins() { - let expectation = XCTestExpectation() + func testQueryLoginsWithEmptyString() { + setupLogins() + let expectation = XCTestExpectation(description: "Waiting for login query to complete") viewModel.queryLogins("") { emptyQueryResult in XCTAssertEqual(emptyQueryResult.count, 10) expectation.fulfill() } + wait(for: [expectation], timeout: 1) + } + func testQueryLoginsWithExampleString() { + setupLogins() + let expectation = XCTestExpectation(description: "Waiting for login query to complete") viewModel.queryLogins("example") { exampleQueryResult in XCTAssertEqual(exampleQueryResult.count, 10) expectation.fulfill() } + wait(for: [expectation], timeout: 1) + } + func testQueryLoginsWithNumericString() { + setupLogins() + let expectation = XCTestExpectation(description: "Waiting for login query to complete") viewModel.queryLogins("3") { threeQueryResult in XCTAssertEqual(threeQueryResult.count, 1) expectation.fulfill() } + wait(for: [expectation], timeout: 1) + } + func testQueryLoginsWithNoResults() { + setupLogins() + let expectation = XCTestExpectation(description: "Waiting for login query to complete") viewModel.queryLogins("yxz") { zQueryResult in XCTAssertEqual(zQueryResult.count, 0) expectation.fulfill() } - - wait(for: [expectation], timeout: 5) + wait(for: [expectation], timeout: 1) } func testIsDuringSearchControllerDismiss() { From 5bccf54129a2c8b42910fffb6677c77c32af4833 Mon Sep 17 00:00:00 2001 From: Donal Meehan <76789979+DonalMe@users.noreply.github.com> Date: Mon, 5 Aug 2024 10:28:40 -0400 Subject: [PATCH 046/128] Bump - Set version to 131.0 (#21459) --- bitrise.yml | 6 +++--- firefox-ios/Client/Info.plist | 2 +- firefox-ios/CredentialProvider/Info.plist | 2 +- firefox-ios/Extensions/NotificationService/Info.plist | 2 +- firefox-ios/Extensions/ShareTo/Info.plist | 2 +- firefox-ios/WidgetKit/Info.plist | 2 +- focus-ios/Blockzilla/Info.plist | 2 +- focus-ios/ContentBlocker/Info.plist | 2 +- focus-ios/FocusIntentExtension/Info.plist | 2 +- focus-ios/OpenInFocus/Info.plist | 2 +- focus-ios/Widgets/Info.plist | 2 +- 11 files changed, 13 insertions(+), 13 deletions(-) diff --git a/bitrise.yml b/bitrise.yml index 5a32e1618367..c9e8eb65b254 100644 --- a/bitrise.yml +++ b/bitrise.yml @@ -2123,17 +2123,17 @@ app: BITRISE_NIGHTLY_VERSION: '9000' - opts: is_expand: false - BITRISE_RELEASE_VERSION: '130.0' + BITRISE_RELEASE_VERSION: '131.0' - opts: is_expand: false - BITRISE_BETA_VERSION: '130.0' + BITRISE_BETA_VERSION: '131.0' trigger_map: - push_branch: main pipeline: pipeline_build_and_test - push_branch: epic-branch/* pipeline: pipeline_build_and_test -- push_branch: release/v130 +- push_branch: release/v131 pipeline: pipeline_build_and_test - pull_request_target_branch: main pipeline: pipeline_build_and_test diff --git a/firefox-ios/Client/Info.plist b/firefox-ios/Client/Info.plist index dd7a19d43852..7a19c1cf64ee 100644 --- a/firefox-ios/Client/Info.plist +++ b/firefox-ios/Client/Info.plist @@ -28,7 +28,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 130.0 + 131.0 CFBundleSignature ???? CFBundleURLTypes diff --git a/firefox-ios/CredentialProvider/Info.plist b/firefox-ios/CredentialProvider/Info.plist index 60d0c97ffdb8..f8cebac915f7 100644 --- a/firefox-ios/CredentialProvider/Info.plist +++ b/firefox-ios/CredentialProvider/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 130.0 + 131.0 CFBundleVersion 1 MozDevelopmentTeam diff --git a/firefox-ios/Extensions/NotificationService/Info.plist b/firefox-ios/Extensions/NotificationService/Info.plist index 52f010dac4c2..4df6947735fb 100644 --- a/firefox-ios/Extensions/NotificationService/Info.plist +++ b/firefox-ios/Extensions/NotificationService/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType XPC! CFBundleShortVersionString - 130.0 + 131.0 CFBundleVersion 1 MozDevelopmentTeam diff --git a/firefox-ios/Extensions/ShareTo/Info.plist b/firefox-ios/Extensions/ShareTo/Info.plist index 273f049d3f92..8581bf2caaa7 100644 --- a/firefox-ios/Extensions/ShareTo/Info.plist +++ b/firefox-ios/Extensions/ShareTo/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType XPC! CFBundleShortVersionString - 130.0 + 131.0 CFBundleSignature ???? CFBundleVersion diff --git a/firefox-ios/WidgetKit/Info.plist b/firefox-ios/WidgetKit/Info.plist index 0dfb99b82ddc..1e0bf29516de 100644 --- a/firefox-ios/WidgetKit/Info.plist +++ b/firefox-ios/WidgetKit/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString - 130.0 + 131.0 CFBundleVersion 1 MozDevelopmentTeam diff --git a/focus-ios/Blockzilla/Info.plist b/focus-ios/Blockzilla/Info.plist index be107be44694..4a596cfe3ad5 100644 --- a/focus-ios/Blockzilla/Info.plist +++ b/focus-ios/Blockzilla/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 130.0 + 131.0 CFBundleSignature ???? CFBundleURLTypes diff --git a/focus-ios/ContentBlocker/Info.plist b/focus-ios/ContentBlocker/Info.plist index dfdb68990e29..7a6944ee4f28 100644 --- a/focus-ios/ContentBlocker/Info.plist +++ b/focus-ios/ContentBlocker/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType XPC! CFBundleShortVersionString - 130.0 + 131.0 CFBundleSignature ???? CFBundleVersion diff --git a/focus-ios/FocusIntentExtension/Info.plist b/focus-ios/FocusIntentExtension/Info.plist index dd39bc992c1d..6e6c33f687ef 100644 --- a/focus-ios/FocusIntentExtension/Info.plist +++ b/focus-ios/FocusIntentExtension/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType XPC! CFBundleShortVersionString - 130.0 + 131.0 CFBundleVersion 1 NSExtension diff --git a/focus-ios/OpenInFocus/Info.plist b/focus-ios/OpenInFocus/Info.plist index 474b988e52cb..f77d58a5b501 100644 --- a/focus-ios/OpenInFocus/Info.plist +++ b/focus-ios/OpenInFocus/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType XPC! CFBundleShortVersionString - 130.0 + 131.0 CFBundleVersion 1 NSExtension diff --git a/focus-ios/Widgets/Info.plist b/focus-ios/Widgets/Info.plist index 1c3413fbd257..bd444ff41590 100644 --- a/focus-ios/Widgets/Info.plist +++ b/focus-ios/Widgets/Info.plist @@ -3,7 +3,7 @@ CFBundleShortVersionString - 130.0 + 131.0 NSExtension NSExtensionPointIdentifier From 5f1bdfba93f0be2115a1decdaf9657a31b996d1b Mon Sep 17 00:00:00 2001 From: dragosb01 <134391433+dragosb01@users.noreply.github.com> Date: Tue, 6 Aug 2024 12:51:18 +0300 Subject: [PATCH 047/128] Update MTE-3227 - TestRail URLs to mozilla.testrail.io (#21466) --- .../Tests/XCUITests/ActivityStreamTest.swift | 16 ++++---- .../Tests/XCUITests/AuthenticationTest.swift | 2 +- .../Tests/XCUITests/BookmarksTests.swift | 30 +++++++------- .../Tests/XCUITests/BrowsingPDFTests.swift | 12 +++--- .../Tests/XCUITests/ClipBoardTests.swift | 6 +-- .../Tests/XCUITests/CreditCardsTests.swift | 24 +++++------ .../Tests/XCUITests/DataManagementTests.swift | 4 +- .../Tests/XCUITests/DatabaseFixtureTest.swift | 4 +- .../Tests/XCUITests/DesktopModeTests.swift | 14 +++---- .../XCUITests/DisplaySettingsTests.swift | 4 +- .../XCUITests/DomainAutocompleteTests.swift | 14 +++---- .../Tests/XCUITests/DownloadsTests.swift | 20 +++++----- .../Tests/XCUITests/DragAndDropTests.swift | 16 ++++---- .../EngagementNotificationTests.swift | 2 +- .../Tests/XCUITests/FakespotTests.swift | 30 +++++++------- .../Tests/XCUITests/FindInPageTests.swift | 18 ++++----- .../Tests/XCUITests/FirefoxSuggestTest.swift | 2 +- .../Tests/XCUITests/HistoryTests.swift | 32 +++++++-------- .../Tests/XCUITests/HomeButtonTests.swift | 6 +-- .../XCUITests/HomePageSettingsUITest.swift | 24 +++++------ .../Tests/XCUITests/JumpBackInTests.swift | 6 +-- .../Tests/XCUITests/LoginsTests.swift | 20 +++++----- .../Tests/XCUITests/NavigationTest.swift | 40 +++++++++---------- .../Tests/XCUITests/NewTabSettings.swift | 14 +++---- .../Tests/XCUITests/NightModeTests.swift | 2 +- .../Tests/XCUITests/OnboardingTests.swift | 6 +-- .../Tests/XCUITests/OpeningScreenTests.swift | 2 +- .../XCUITests/PhotonActionSheetTests.swift | 12 +++--- .../Tests/XCUITests/PocketTests.swift | 2 +- .../Tests/XCUITests/PrivateBrowsingTest.swift | 24 +++++------ .../Tests/XCUITests/ReadingListTests.swift | 24 +++++------ .../XCUITests/SearchSettingsUITest.swift | 10 ++--- .../Tests/XCUITests/SearchTest.swift | 22 +++++----- .../Tests/XCUITests/SettingsTests.swift | 12 +++--- .../Tests/XCUITests/SyncFAUITests.swift | 10 ++--- .../Tests/XCUITests/TabCounterTests.swift | 4 +- .../XCUITests/ThirdPartySearchTest.swift | 8 ++-- .../Tests/XCUITests/ToolbarMenuTests.swift | 2 +- .../Tests/XCUITests/ToolbarTest.swift | 8 ++-- .../Tests/XCUITests/TopTabsTest.swift | 38 +++++++++--------- .../XCUITests/TrackingProtectionTests.swift | 8 ++-- .../Tests/XCUITests/URLValidationTests.swift | 2 +- .../Tests/XCUITests/UrlBarTests.swift | 4 +- .../Tests/XCUITests/ZoomingTests.swift | 8 ++-- 44 files changed, 284 insertions(+), 284 deletions(-) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/ActivityStreamTest.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/ActivityStreamTest.swift index b9a23c9242ce..e3f234fee875 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/ActivityStreamTest.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/ActivityStreamTest.swift @@ -43,7 +43,7 @@ class ActivityStreamTest: BaseTestCase { super.tearDown() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2273342 + // https://mozilla.testrail.io/index.php?/cases/view/2273342 // Smoketest func testDefaultSites() throws { XCTExpectFailure("The app was not launched", strict: false) { @@ -60,7 +60,7 @@ class ActivityStreamTest: BaseTestCase { mozWaitForElementToExist(app.collectionViews.cells.staticTexts["Facebook"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2272218 + // https://mozilla.testrail.io/index.php?/cases/view/2272218 func testTopSites2Add() { if iPad() { checkNumberOfExpectedTopSites(numberOfExpectedTopSites: 12) @@ -69,7 +69,7 @@ class ActivityStreamTest: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2272219 + // https://mozilla.testrail.io/index.php?/cases/view/2272219 func testTopSitesRemoveAllExceptDefaultClearPrivateData() { waitForExistence(app.cells.staticTexts[newTopSite["bookmarkLabel"]!], timeout: TIMEOUT_LONG) // A new site has been added to the top sites @@ -91,7 +91,7 @@ class ActivityStreamTest: BaseTestCase { mozWaitForElementToNotExist(app.cells.staticTexts[newTopSite["bookmarkLabel"]!]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2272220 + // https://mozilla.testrail.io/index.php?/cases/view/2272220 func testTopSitesRemoveAllExceptPinnedClearPrivateData() { waitForExistence(TopSiteCellgroup) if iPad() { @@ -129,7 +129,7 @@ class ActivityStreamTest: BaseTestCase { checkNumberOfExpectedTopSites(numberOfExpectedTopSites: 6) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2272514 + // https://mozilla.testrail.io/index.php?/cases/view/2272514 func testTopSitesShiftAfterRemovingOne() { // Check top site in first and second cell let allTopSites = app.collectionViews.cells.matching(identifier: "TopSitesCell") @@ -159,7 +159,7 @@ class ActivityStreamTest: BaseTestCase { ) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2273338 + // https://mozilla.testrail.io/index.php?/cases/view/2273338 // Smoketest func testTopSitesOpenInNewPrivateTab() throws { XCTExpectFailure("The app was not launched", strict: false) { @@ -229,7 +229,7 @@ class ActivityStreamTest: BaseTestCase { XCTAssertEqual(numberOfTopSites, numberOfExpectedTopSites, "The number of Top Sites is not correct") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2273339 + // https://mozilla.testrail.io/index.php?/cases/view/2273339 func testContextMenuInLandscape() { // For iPhone test is failing to find top sites in landscape // can't scroll only to that area. Needs investigation @@ -250,7 +250,7 @@ class ActivityStreamTest: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2436086 + // https://mozilla.testrail.io/index.php?/cases/view/2436086 func testLongTapOnTopSiteOptions() { waitForExistence(app.cells[TopSites.itemCell]) app.collectionViews.cells.element(boundBy: 3).press(forDuration: 1) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/AuthenticationTest.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/AuthenticationTest.swift index 83754eb1ad07..67daef37dfe0 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/AuthenticationTest.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/AuthenticationTest.swift @@ -7,7 +7,7 @@ import XCTest let testBasicHTTPAuthURL = "https://jigsaw.w3.org/HTTP/Basic/" class AuthenticationTest: BaseTestCase { - // https://testrail.stage.mozaws.net/index.php?/cases/view/2360560 + // https://mozilla.testrail.io/index.php?/cases/view/2360560 func testBasicHTTPAuthenticationPromptVisible() { mozWaitForElementToExist(app.textFields["url"]) navigator.nowAt(NewTabScreen) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/BookmarksTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/BookmarksTests.swift index 5521b5e94974..fa471874b6b7 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/BookmarksTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/BookmarksTests.swift @@ -42,7 +42,7 @@ class BookmarksTests: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306905 + // https://mozilla.testrail.io/index.php?/cases/view/2306905 func testBookmarkingUI() { // Go to a webpage, and add to bookmarks, check it's added navigator.nowAt(NewTabScreen) @@ -105,7 +105,7 @@ class BookmarksTests: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306906 + // https://mozilla.testrail.io/index.php?/cases/view/2306906 func testAccessBookmarksFromContextMenu() { // Add a bookmark navigator.nowAt(NewTabScreen) @@ -120,7 +120,7 @@ class BookmarksTests: BaseTestCase { checkItemInBookmarkList(oneItemBookmarked: true) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306907 + // https://mozilla.testrail.io/index.php?/cases/view/2306907 // Smoketest func testBookmarksAwesomeBar() { XCTExpectFailure("The app was not launched", strict: false) { @@ -160,7 +160,7 @@ class BookmarksTests: BaseTestCase { XCTAssertNotEqual(app.tables["SiteTable"].cells.count, 0) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306913 + // https://mozilla.testrail.io/index.php?/cases/view/2306913 func testAddBookmark() { addNewBookmark() // Verify that clicking on bookmark opens the website @@ -168,7 +168,7 @@ class BookmarksTests: BaseTestCase { mozWaitForElementToExist(app.textFields["url"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306914 + // https://mozilla.testrail.io/index.php?/cases/view/2306914 func testAddNewFolder() { navigator.goto(LibraryPanel_Bookmarks) navigator.nowAt(MobileBookmarks) @@ -193,7 +193,7 @@ class BookmarksTests: BaseTestCase { checkItemsInBookmarksList(items: 1) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306915 + // https://mozilla.testrail.io/index.php?/cases/view/2306915 func testAddNewMarker() { navigator.goto(LibraryPanel_Bookmarks) navigator.nowAt(MobileBookmarks) @@ -211,7 +211,7 @@ class BookmarksTests: BaseTestCase { checkItemsInBookmarksList(items: 1) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306916 + // https://mozilla.testrail.io/index.php?/cases/view/2306916 // Test failing in M1s because the swipe gesture. Needs work to run only on Intel. func testDeleteBookmarkSwiping() { addNewBookmark() @@ -223,7 +223,7 @@ class BookmarksTests: BaseTestCase { checkItemsInBookmarksList(items: 1) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306917 + // https://mozilla.testrail.io/index.php?/cases/view/2306917 func testDeleteBookmarkContextMenu() { addNewBookmark() // Remove by long press and select option from context menu @@ -234,7 +234,7 @@ class BookmarksTests: BaseTestCase { checkItemsInBookmarksList(items: 1) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306908 + // https://mozilla.testrail.io/index.php?/cases/view/2306908 // Smoketest func testUndoDeleteBookmark() { navigator.openURL(path(forTestPage: url_1)) @@ -274,7 +274,7 @@ class BookmarksTests: BaseTestCase { app.textFields["address"].typeText(text) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306909 + // https://mozilla.testrail.io/index.php?/cases/view/2306909 // Smoketest func testBookmarkLibraryAddDeleteBookmark() { // Verify that there are only 1 cell (desktop bookmark folder) @@ -306,7 +306,7 @@ class BookmarksTests: BaseTestCase { mozWaitForElementToNotExist(app.tables["Bookmarks List"].cells.staticTexts["Example Domain"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306910 + // https://mozilla.testrail.io/index.php?/cases/view/2306910 // Smoketest func testDesktopFoldersArePresent() { // Verify that there are only 1 cell (desktop bookmark folder) @@ -323,7 +323,7 @@ class BookmarksTests: BaseTestCase { XCTAssertEqual(app.tables["Bookmarks List"].cells.count, 3) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306911 + // https://mozilla.testrail.io/index.php?/cases/view/2306911 func testRecentlyBookmarked() { navigator.openURL(path(forTestPage: url_2["url"]!)) waitForTabsButton() @@ -339,7 +339,7 @@ class BookmarksTests: BaseTestCase { checkItemInBookmarkList(oneItemBookmarked: false) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306866 + // https://mozilla.testrail.io/index.php?/cases/view/2306866 func testEditBookmark() { navigator.openURL(path(forTestPage: url_2["url"]!)) waitForTabsButton() @@ -353,7 +353,7 @@ class BookmarksTests: BaseTestCase { checkItemInBookmarkList(oneItemBookmarked: true) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2445808 + // https://mozilla.testrail.io/index.php?/cases/view/2445808 func testLongTapRecentlySavedLink() { // Go to "Recently saved" section and long tap on one of the links navigator.openURL(path(forTestPage: url_2["url"]!)) @@ -372,7 +372,7 @@ class BookmarksTests: BaseTestCase { mozWaitForElementToExist(ContextMenuTable.cells.otherElements[StandardImageIdentifiers.Large.shareApple]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307054 + // https://mozilla.testrail.io/index.php?/cases/view/2307054 func testBookmark() { navigator.openURL(url_3) waitForTabsButton() diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/BrowsingPDFTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/BrowsingPDFTests.swift index b7c0891f3736..004428fcc970 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/BrowsingPDFTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/BrowsingPDFTests.swift @@ -13,7 +13,7 @@ let PDF_website = [ "longUrlValue": "http://www.education.gov.yk.ca/" ] class BrowsingPDFTests: BaseTestCase { - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307116 + // https://mozilla.testrail.io/index.php?/cases/view/2307116 func testOpenPDFViewer() { navigator.openURL(PDF_website["url"]!) waitUntilPageLoad() @@ -25,7 +25,7 @@ class BrowsingPDFTests: BaseTestCase { mozWaitForElementToExist(app.staticTexts["1 of 1"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307117 + // https://mozilla.testrail.io/index.php?/cases/view/2307117 // Smoketest func testOpenLinkFromPDF() { navigator.openURL(PDF_website["url"]!) @@ -42,7 +42,7 @@ class BrowsingPDFTests: BaseTestCase { mozWaitForValueContains(app.textFields["url"], value: PDF_website["pdfValue"]!) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307118 + // https://mozilla.testrail.io/index.php?/cases/view/2307118 func testLongPressOnPDFLink() { navigator.openURL(PDF_website["url"]!) waitUntilPageLoad() @@ -60,7 +60,7 @@ class BrowsingPDFTests: BaseTestCase { mozWaitForElementToExist(app.buttons["Share…"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307119 + // https://mozilla.testrail.io/index.php?/cases/view/2307119 func testLongPressOnPDFLinkToAddToReadingList() { navigator.openURL(PDF_website["url"]!) waitUntilPageLoad() @@ -77,7 +77,7 @@ class BrowsingPDFTests: BaseTestCase { mozWaitForElementToExist(savedToReadingList) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307120 + // https://mozilla.testrail.io/index.php?/cases/view/2307120 // Smoketest func testPinPDFtoTopSites() { navigator.openURL(PDF_website["url"]!) @@ -109,7 +109,7 @@ class BrowsingPDFTests: BaseTestCase { mozWaitForElementToExist(app.collectionViews.cells.staticTexts[PDF_website["bookmarkLabel"]!]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307121 + // https://mozilla.testrail.io/index.php?/cases/view/2307121 // Smoketest func testBookmarkPDF() { navigator.openURL(PDF_website["url"]!) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/ClipBoardTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/ClipBoardTests.swift index fed26e5368b8..f3b649f1c4c0 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/ClipBoardTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/ClipBoardTests.swift @@ -49,7 +49,7 @@ class ClipBoardTests: BaseTestCase { } // This test is disabled in release, but can still run on master - // https://testrail.stage.mozaws.net/index.php?/cases/view/2325688 + // https://mozilla.testrail.io/index.php?/cases/view/2325688 func testClipboard() { navigator.nowAt(NewTabScreen) navigator.openURL(url) @@ -67,7 +67,7 @@ class ClipBoardTests: BaseTestCase { mozWaitForValueContains(app.textFields["address"], value: "www.example.com") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307051 + // https://mozilla.testrail.io/index.php?/cases/view/2307051 func testCopyLink() { // Tap on "Copy Link navigator.openURL(url_3) @@ -87,7 +87,7 @@ class ClipBoardTests: BaseTestCase { mozWaitForElementToExist(app.staticTexts["Example Domain"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2325691 + // https://mozilla.testrail.io/index.php?/cases/view/2325691 // Smoketest func testClipboardPasteAndGo() { // Temporarily disabled until url bar redesign work FXIOS-8172 diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/CreditCardsTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/CreditCardsTests.swift index 1d50e0b21555..5395da02d675 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/CreditCardsTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/CreditCardsTests.swift @@ -24,7 +24,7 @@ class CreditCardsTests: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306967 + // https://mozilla.testrail.io/index.php?/cases/view/2306967 // SmokeTest func testAccessingTheCreditCardsSection() { navigator.nowAt(NewTabScreen) @@ -55,7 +55,7 @@ class CreditCardsTests: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306978 + // https://mozilla.testrail.io/index.php?/cases/view/2306978 // SmokeTest func testDeleteButtonFromEditCard() { addCardAndReachViewCardPage() @@ -91,7 +91,7 @@ class CreditCardsTests: BaseTestCase { mozWaitForElementToNotExist(app.tables.cells.element(boundBy: 1)) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306975 + // https://mozilla.testrail.io/index.php?/cases/view/2306975 // SmokeTest func testEditSavedCardsUI() { addCardAndReachViewCardPage() @@ -103,7 +103,7 @@ class CreditCardsTests: BaseTestCase { mozWaitForElementToExist(app.staticTexts[creditCardsStaticTexts.AutoFillCreditCard.savedCards]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306972 + // https://mozilla.testrail.io/index.php?/cases/view/2306972 func testManageCreditCardsOption() throws { if #unavailable(iOS 16) { throw XCTSkip("addCreditCardAndReachAutofillWebsite() does not work on iOS 15") @@ -124,7 +124,7 @@ class CreditCardsTests: BaseTestCase { mozWaitForElementToNotExist(app.buttons[useSavedCard]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306969 + // https://mozilla.testrail.io/index.php?/cases/view/2306969 // Smoketest func testAutofillCreditCardsToggleOnOoff() { navigator.nowAt(NewTabScreen) @@ -181,7 +181,7 @@ class CreditCardsTests: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306971 + // https://mozilla.testrail.io/index.php?/cases/view/2306971 func testCreditCardsAutofill() throws { if #unavailable(iOS 16) { throw XCTSkip("addCreditCardAndReachAutofillWebsite() does not work on iOS 15") @@ -200,7 +200,7 @@ class CreditCardsTests: BaseTestCase { XCTAssertEqual(contentView["ZIP"].value! as! String, "ZIP") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306976 + // https://mozilla.testrail.io/index.php?/cases/view/2306976 func testVerifyThatTheEditedCreditCardIsSaved() { // Go to a saved credit card and change the name on card let updatedName = "Firefox" @@ -231,7 +231,7 @@ class CreditCardsTests: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306974 + // https://mozilla.testrail.io/index.php?/cases/view/2306974 func testVerifyThatMultipleCardsCanBeAdded() { // Add multiple credit cards let expectedCards = 3 @@ -294,7 +294,7 @@ class CreditCardsTests: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306977 + // https://mozilla.testrail.io/index.php?/cases/view/2306977 func testErrorStatesCreditCards() { // Go to a saved credit card and delete the name addCardAndReachViewCardPage() @@ -349,7 +349,7 @@ class CreditCardsTests: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306979 + // https://mozilla.testrail.io/index.php?/cases/view/2306979 func testSaveThisCardPrompt() { navigator.goto(NewTabScreen) navigator.openURL("https://checkout.stripe.dev/preview") @@ -410,7 +410,7 @@ class CreditCardsTests: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306980 + // https://mozilla.testrail.io/index.php?/cases/view/2306980 func testUpdatePrompt() throws { if #unavailable(iOS 16) { throw XCTSkip("addCreditCardAndReachAutofillWebsite() does not work on iOS 15") @@ -491,7 +491,7 @@ class CreditCardsTests: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306970 + // https://mozilla.testrail.io/index.php?/cases/view/2306970 func testRedirectionToCreditCardsSection() { navigator.nowAt(NewTabScreen) waitForTabsButton() diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/DataManagementTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/DataManagementTests.swift index 455dc30c7cac..85b0cf7d4161 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/DataManagementTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/DataManagementTests.swift @@ -6,7 +6,7 @@ import XCTest class DataManagementTests: BaseTestCase { // Testing the search bar, and clear website data option - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307015 + // https://mozilla.testrail.io/index.php?/cases/view/2307015 func testWebSiteDataOptions() { navigator.nowAt(NewTabScreen) waitForTabsButton() @@ -31,7 +31,7 @@ class DataManagementTests: BaseTestCase { XCTAssertEqual(expectedWebsitesCleared, 1) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307017 + // https://mozilla.testrail.io/index.php?/cases/view/2307017 // Smoketest func testWebSiteDataEnterFirstTime() { navigator.openURL("example.com") diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/DatabaseFixtureTest.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/DatabaseFixtureTest.swift index 3e2bb5177dc2..088a0a940b38 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/DatabaseFixtureTest.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/DatabaseFixtureTest.swift @@ -23,7 +23,7 @@ class DatabaseFixtureTest: BaseTestCase { super.setUp() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2458579 + // https://mozilla.testrail.io/index.php?/cases/view/2458579 func testBookmarksDatabaseFixture() { // Warning: Avoid using mozWaitForElementToExist as it is up to 25x less performant let tabsButton = app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton] @@ -51,7 +51,7 @@ class DatabaseFixtureTest: BaseTestCase { app.terminate() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2459133 + // https://mozilla.testrail.io/index.php?/cases/view/2459133 func testHistoryDatabaseFixture() throws { let tabsButton = app.buttons[AccessibilityIdentifiers.Toolbar.tabsButton] mozWaitForElementToExist(tabsButton) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/DesktopModeTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/DesktopModeTests.swift index 24ea1d956d4d..8284a1df5401 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/DesktopModeTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/DesktopModeTests.swift @@ -8,7 +8,7 @@ import XCTest // swiftlint:disable empty_count // Tests for both platforms class DesktopModeTestsIpad: IpadOnlyTestCase { - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306852 + // https://mozilla.testrail.io/index.php?/cases/view/2306852 // smoketest func testLongPressReload() { if skipPlatform { return } @@ -43,7 +43,7 @@ class DesktopModeTestsIpad: IpadOnlyTestCase { } class DesktopModeTestsIphone: IphoneOnlyTestCase { - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306853 + // https://mozilla.testrail.io/index.php?/cases/view/2306853 func testClearPrivateData() { if skipPlatform { return } @@ -68,7 +68,7 @@ class DesktopModeTestsIphone: IphoneOnlyTestCase { XCTAssert(app.webViews.staticTexts.matching(identifier: "MOBILE_UA").count > 0) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306855 + // https://mozilla.testrail.io/index.php?/cases/view/2306855 func testSameHostInMultipleTabs() { if skipPlatform { return } @@ -99,7 +99,7 @@ class DesktopModeTestsIphone: IphoneOnlyTestCase { XCTAssert(app.webViews.staticTexts.matching(identifier: "MOBILE_UA").count > 0) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306854 + // https://mozilla.testrail.io/index.php?/cases/view/2306854 // Smoketest func testChangeModeInSameTab() { if skipPlatform { return } @@ -123,7 +123,7 @@ class DesktopModeTestsIphone: IphoneOnlyTestCase { XCTAssert(app.webViews.staticTexts.matching(identifier: "MOBILE_UA").count > 0) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306856 + // https://mozilla.testrail.io/index.php?/cases/view/2306856 func testPrivateModeOffAlsoRemovesFromNormalMode() { if skipPlatform { return } @@ -158,7 +158,7 @@ class DesktopModeTestsIphone: IphoneOnlyTestCase { XCTAssert(app.webViews.staticTexts.matching(identifier: "MOBILE_UA").count > 0) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306857 + // https://mozilla.testrail.io/index.php?/cases/view/2306857 func testPrivateModeOnHasNoAffectOnNormalMode() { if skipPlatform { return } @@ -185,7 +185,7 @@ class DesktopModeTestsIphone: IphoneOnlyTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306852 + // https://mozilla.testrail.io/index.php?/cases/view/2306852 // smoketest func testLongPressReload() { if skipPlatform { return } diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/DisplaySettingsTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/DisplaySettingsTests.swift index 24a676fd3bc8..d758043245cd 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/DisplaySettingsTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/DisplaySettingsTests.swift @@ -5,7 +5,7 @@ import XCTest class DisplaySettingTests: BaseTestCase { - // https://testrail.stage.mozaws.net/index.php?/cases/view/2337485 + // https://mozilla.testrail.io/index.php?/cases/view/2337485 func testCheckDisplaySettingsDefault() { navigator.nowAt(NewTabScreen) navigator.goto(DisplaySettings) @@ -15,7 +15,7 @@ class DisplaySettingTests: BaseTestCase { XCTAssertEqual(switchValue as! String, "1") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2337487 + // https://mozilla.testrail.io/index.php?/cases/view/2337487 func testCheckSystemThemeChanges() { navigator.nowAt(NewTabScreen) navigator.goto(DisplaySettings) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/DomainAutocompleteTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/DomainAutocompleteTests.swift index d1cda653f897..bd58ad14f0fa 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/DomainAutocompleteTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/DomainAutocompleteTests.swift @@ -43,7 +43,7 @@ class DomainAutocompleteTests: BaseTestCase { super.setUp() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2334558 + // https://mozilla.testrail.io/index.php?/cases/view/2334558 func test1Autocomplete() { // Basic autocompletion cases // The autocomplete does not display the history item from the DB. Workaround is to manually visit "mozilla.org". @@ -71,7 +71,7 @@ class DomainAutocompleteTests: BaseTestCase { } // Test that deleting characters works correctly with autocomplete - // https://testrail.stage.mozaws.net/index.php?/cases/view/2334647 + // https://mozilla.testrail.io/index.php?/cases/view/2334647 func test3AutocompleteDeletingChars() { // The autocomplete does not display the history item from the DB. Workaround is to manually visit "mozilla.org". navigator.openURL("mozilla.org") @@ -101,7 +101,7 @@ class DomainAutocompleteTests: BaseTestCase { } } // Delete the entire string and verify that the home panels are shown again. - // https://testrail.stage.mozaws.net/index.php?/cases/view/2334648 + // https://mozilla.testrail.io/index.php?/cases/view/2334648 func test6DeleteEntireString() { navigator.goto(URLBarOpen) app.textFields["address"].typeText("www.moz") @@ -116,7 +116,7 @@ class DomainAutocompleteTests: BaseTestCase { } // Ensure that the scheme is included in the autocompletion. - // https://testrail.stage.mozaws.net/index.php?/cases/view/2334649 + // https://mozilla.testrail.io/index.php?/cases/view/2334649 func test4EnsureSchemeIncludedAutocompletion() { navigator.openURL(websiteExample["url"]!) waitUntilPageLoad() @@ -130,7 +130,7 @@ class DomainAutocompleteTests: BaseTestCase { } // Non-matches. - // https://testrail.stage.mozaws.net/index.php?/cases/view/2334650 + // https://mozilla.testrail.io/index.php?/cases/view/2334650 func test5NoMatches() { navigator.openURL("twitter.com/login") waitUntilPageLoad() @@ -177,7 +177,7 @@ class DomainAutocompleteTests: BaseTestCase { } // Test default domains. - // https://testrail.stage.mozaws.net/index.php?/cases/view/2334651 + // https://mozilla.testrail.io/index.php?/cases/view/2334651 func test2DefaultDomains() { navigator.goto(URLBarOpen) app.textFields["address"].typeText("a") @@ -199,7 +199,7 @@ class DomainAutocompleteTests: BaseTestCase { } // Test mixed case autocompletion. - // https://testrail.stage.mozaws.net/index.php?/cases/view/2334653 + // https://mozilla.testrail.io/index.php?/cases/view/2334653 func testMixedCaseAutocompletion() { navigator.goto(URLBarOpen) app.textFields["address"].typeText("MoZ") diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/DownloadsTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/DownloadsTests.swift index 7ac22aaac235..ae8e55cabe59 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/DownloadsTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/DownloadsTests.swift @@ -39,7 +39,7 @@ class DownloadsTests: BaseTestCase { app.tables.cells.buttons["Delete"].tap() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306896 + // https://mozilla.testrail.io/index.php?/cases/view/2306896 func testDownloadFilesAppMenuFirstTime() { navigator.nowAt(NewTabScreen) navigator.goto(LibraryPanel_Downloads) @@ -49,7 +49,7 @@ class DownloadsTests: BaseTestCase { mozWaitForElementToExist(app.staticTexts["Downloaded files will show up here."]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306897 + // https://mozilla.testrail.io/index.php?/cases/view/2306897 func testDownloadFileContextMenu() { navigator.openURL(testURL) waitUntilPageLoad() @@ -69,7 +69,7 @@ class DownloadsTests: BaseTestCase { checkTheNumberOfDownloadedItems(items: 0) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306898 + // https://mozilla.testrail.io/index.php?/cases/view/2306898 // Smoketest func testDownloadFile() { downloadFile(fileName: testFileName, numberOfDownloads: 1) @@ -83,7 +83,7 @@ class DownloadsTests: BaseTestCase { mozWaitForElementToExist(app.tables.cells.staticTexts[testFileSize]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306899 + // https://mozilla.testrail.io/index.php?/cases/view/2306899 func testDownloadBLOBFile() { downloadBLOBFile() mozWaitForElementToExist(app.buttons["Downloads"]) @@ -97,7 +97,7 @@ class DownloadsTests: BaseTestCase { mozWaitForElementToExist(app.tables.cells.staticTexts[testBLOBFileSize]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306900 + // https://mozilla.testrail.io/index.php?/cases/view/2306900 func testDeleteDownloadedFile() throws { downloadFile(fileName: testFileName, numberOfDownloads: 1) navigator.goto(BrowserTabMenu) @@ -109,7 +109,7 @@ class DownloadsTests: BaseTestCase { checkTheNumberOfDownloadedItems(items: 0) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306901 + // https://mozilla.testrail.io/index.php?/cases/view/2306901 func testShareDownloadedFile() throws { downloadFile(fileName: testFileName, numberOfDownloads: 1) navigator.goto(BrowserTabMenu) @@ -137,7 +137,7 @@ class DownloadsTests: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306902 + // https://mozilla.testrail.io/index.php?/cases/view/2306902 func testLongPressOnDownloadedFile() { downloadFile(fileName: testFileName, numberOfDownloads: 1) navigator.goto(BrowserTabMenu) @@ -189,7 +189,7 @@ class DownloadsTests: BaseTestCase { app.buttons["Download Link"].tap() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306903 + // https://mozilla.testrail.io/index.php?/cases/view/2306903 func testDownloadMoreThanOneFile() { downloadFile(fileName: testFileName, numberOfDownloads: 2) navigator.goto(BrowserTabMenu) @@ -199,7 +199,7 @@ class DownloadsTests: BaseTestCase { checkTheNumberOfDownloadedItems(items: 2) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306904 + // https://mozilla.testrail.io/index.php?/cases/view/2306904 func testRemoveUserDataRemovesDownloadedFiles() { navigator.nowAt(NewTabScreen) // The option to remove downloaded files from clear private data is off by default @@ -239,7 +239,7 @@ class DownloadsTests: BaseTestCase { XCTAssertEqual(list, items, "The number of items in the downloads table is not correct") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306895 + // https://mozilla.testrail.io/index.php?/cases/view/2306895 // Smoketest func testToastButtonToGoToDownloads() { downloadFile(fileName: testFileName, numberOfDownloads: 1) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/DragAndDropTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/DragAndDropTests.swift index 15841171ceeb..4e1fc6fe37e5 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/DragAndDropTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/DragAndDropTests.swift @@ -26,7 +26,7 @@ class DragAndDropTests: BaseTestCase { super.tearDown() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2362645 + // https://mozilla.testrail.io/index.php?/cases/view/2362645 // Smoketest func testRearrangeTabsTabTray() { openTwoWebsites() @@ -44,7 +44,7 @@ class DragAndDropTests: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2390210 + // https://mozilla.testrail.io/index.php?/cases/view/2390210 func testRearrangeMoreThan3TabsTabTray() { // Arranging more than 3 to check that it works moving tabs between lines let thirdWebsite = (url: "example.com", tabName: "Example Domain. Currently selected tab.") @@ -89,7 +89,7 @@ class DragAndDropTests: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2361191 + // https://mozilla.testrail.io/index.php?/cases/view/2361191 func testRearrangeTabsTabTrayLandscape() { // Set the device in landscape mode XCUIDevice.shared.orientation = UIDeviceOrientation.landscapeLeft @@ -116,7 +116,7 @@ class DragAndDropTests: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2361192 + // https://mozilla.testrail.io/index.php?/cases/view/2361192 func testDragAndDropHomeTabTabsTray() { navigator.openNewURL(urlString: secondWebsite.url) waitUntilPageLoad() @@ -144,7 +144,7 @@ class DragAndDropTests: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2361193 + // https://mozilla.testrail.io/index.php?/cases/view/2361193 func testRearrangeTabsPrivateModeTabTray() { mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton]) navigator.toggleOn(userState.isPrivate, withAction: Action.TogglePrivateMode) @@ -252,7 +252,7 @@ class DragAndDropTestIpad: IpadOnlyTestCase { super.tearDown() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307024 + // https://mozilla.testrail.io/index.php?/cases/view/2307024 func test4RearrangeTabs() { if skipPlatform { return } @@ -271,7 +271,7 @@ class DragAndDropTestIpad: IpadOnlyTestCase { ) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2361413 + // https://mozilla.testrail.io/index.php?/cases/view/2361413 func testRearrangeTabsTabTrayIsKeptinTopTabs() { if skipPlatform { return } openTwoWebsites() @@ -290,7 +290,7 @@ class DragAndDropTestIpad: IpadOnlyTestCase { checkTabsOrder(dragAndDropTab: true, firstTab: secondWebsite.tabName, secondTab: firstWebsite.tabName) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2417438 + // https://mozilla.testrail.io/index.php?/cases/view/2417438 // This test drags the address bar and since it is not possible to drop it on another app, // lets do it in a search box func testDragAddressBarIntoSearchBox() { diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/EngagementNotificationTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/EngagementNotificationTests.swift index 38845177efb9..20dbf3a484a9 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/EngagementNotificationTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/EngagementNotificationTests.swift @@ -12,7 +12,7 @@ class EngagementNotificationTests: BaseTestCase { super.setUp() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307101 + // https://mozilla.testrail.io/index.php?/cases/view/2307101 func testDontAllowNotifications() { // Skip login navigator.nowAt(BrowserTab) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/FakespotTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/FakespotTests.swift index 656653da1466..44b6823c8f90 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/FakespotTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/FakespotTests.swift @@ -9,7 +9,7 @@ class FakespotTests: BaseTestCase { super.tearDown() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307128 + // https://mozilla.testrail.io/index.php?/cases/view/2307128 func testFakespotAvailable() { reachReviewChecker() mozWaitForElementToExist(app.staticTexts[AccessibilityIdentifiers.Shopping.sheetHeaderTitle]) @@ -20,7 +20,7 @@ class FakespotTests: BaseTestCase { mozWaitForElementToNotExist(app.otherElements[AccessibilityIdentifiers.Shopping.sheetHeaderTitle]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2358865 + // https://mozilla.testrail.io/index.php?/cases/view/2358865 func testReviewQualityCheckBottomSheetUI() { reachReviewChecker() mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Shopping.OptInCard.mainButton]) @@ -28,7 +28,7 @@ class FakespotTests: BaseTestCase { validateReviewQualityCheckSheet() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2358866 + // https://mozilla.testrail.io/index.php?/cases/view/2358866 func testReviewQualityCheckBottomSheetUILandscape() throws { if iPad() { throw XCTSkip("iPhone only test") @@ -42,7 +42,7 @@ class FakespotTests: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2358902 + // https://mozilla.testrail.io/index.php?/cases/view/2358902 // Smoketest func testPriceTagIconAvailableOnlyOnDetailPage() { // Search for a product but do not open the product detail page @@ -52,7 +52,7 @@ class FakespotTests: BaseTestCase { mozWaitForElementToNotExist(app.buttons[AccessibilityIdentifiers.Toolbar.shoppingButton]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2358904 + // https://mozilla.testrail.io/index.php?/cases/view/2358904 // Smoketest func testPriceTagNotDisplayedInPrivateMode() { // Open a product detail page using a private tab and check the address bar @@ -62,7 +62,7 @@ class FakespotTests: BaseTestCase { mozWaitForElementToNotExist(app.buttons[AccessibilityIdentifiers.Toolbar.shoppingButton]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2358924 + // https://mozilla.testrail.io/index.php?/cases/view/2358924 func testAcceptTheRejectedOptInNotification() { reachReviewChecker() mozWaitForElementToExist(app.staticTexts[AccessibilityIdentifiers.Shopping.sheetHeaderTitle]) @@ -87,7 +87,7 @@ class FakespotTests: BaseTestCase { XCTAssertEqual(app.buttons[AccessibilityIdentifiers.Shopping.sheetCloseButton].label, "Close Review Checker") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2358901 + // https://mozilla.testrail.io/index.php?/cases/view/2358901 func testPriceTagNotDisplayedOnSitesNotIntegratedFakespot() { // Navigate to ebay.com navigator.openURL("https://www.ebay.com") @@ -110,7 +110,7 @@ class FakespotTests: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2358863 + // https://mozilla.testrail.io/index.php?/cases/view/2358863 func testSettingsSectionUI() { // Navigate to a product detail page reachReviewChecker() @@ -137,7 +137,7 @@ class FakespotTests: BaseTestCase { validateExpandedSettingsSection() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2358892 + // https://mozilla.testrail.io/index.php?/cases/view/2358892 func testOptInNotificationLayout() { // Navigate to a product detail page on amazon.com page reachReviewChecker() @@ -150,7 +150,7 @@ class FakespotTests: BaseTestCase { validateLayoutOnWalmartAndBestBuy("https://www.bestbuy.com", isWalmart: false, "Best Buy", "Amazon", "Walmart") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2358878 + // https://mozilla.testrail.io/index.php?/cases/view/2358878 func testLearnMoreAboutFakespotHyperlink() { // Navigate to a product detail page reachReviewChecker() @@ -170,7 +170,7 @@ class FakespotTests: BaseTestCase { validateMozillaSupportWebpage("Review Checker for Firefox Mobile", "support.mozilla.org") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2358864 + // https://mozilla.testrail.io/index.php?/cases/view/2358864 func testTurnOffAndOnTheReviewQualityCheck() { // Navigate to a product detail page reachReviewChecker() @@ -193,7 +193,7 @@ class FakespotTests: BaseTestCase { mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Shopping.OptInCard.mainButton]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2358894 + // https://mozilla.testrail.io/index.php?/cases/view/2358894 func testLearnMoreLink() { // Navigate to a product detail page reachReviewChecker() @@ -206,7 +206,7 @@ class FakespotTests: BaseTestCase { validateMozillaSupportWebpage("Review Checker for Firefox Mobile", "support.mozilla.org") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2358896 + // https://mozilla.testrail.io/index.php?/cases/view/2358896 func testTermsOfUseLink() { // Navigate to a product detail page reachReviewChecker() @@ -219,7 +219,7 @@ class FakespotTests: BaseTestCase { validateMozillaSupportWebpage("Fakespot Terms of Use", "www.fakespot.com") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2358895 + // https://mozilla.testrail.io/index.php?/cases/view/2358895 func testPrivacyPolicyLink() { // Navigate to a product detail page reachReviewChecker() @@ -232,7 +232,7 @@ class FakespotTests: BaseTestCase { validateMozillaSupportWebpage("Privacy Notice", "privacy/firefox") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2358929 + // https://mozilla.testrail.io/index.php?/cases/view/2358929 func testPriceTagIconAndReviewCheckLandscape() { // Change the device orientation to be landscape XCUIDevice.shared.orientation = UIDeviceOrientation.landscapeLeft diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/FindInPageTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/FindInPageTests.swift index 6573f3ce0b8f..73503fbb89db 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/FindInPageTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/FindInPageTests.swift @@ -19,7 +19,7 @@ class FindInPageTests: BaseTestCase { mozWaitForElementToExist(app.searchFields["find.searchField"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2323463 + // https://mozilla.testrail.io/index.php?/cases/view/2323463 func testFindInLargeDoc() { navigator.openURL("http://localhost:\(serverPort)/test-fixture/find-in-page-test.html") waitUntilPageLoad() @@ -39,7 +39,7 @@ class FindInPageTests: BaseTestCase { XCTAssertEqual(app.staticTexts["find.resultLabel"].label, "1 of 1,000", "The book word count does match") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306851 + // https://mozilla.testrail.io/index.php?/cases/view/2306851 // Smoketest func testFindFromMenu() { userState.url = path(forTestPage: "test-mozilla-book.html") @@ -76,7 +76,7 @@ class FindInPageTests: BaseTestCase { mozWaitForElementToNotExist(app.textFields["Book"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2323705 + // https://mozilla.testrail.io/index.php?/cases/view/2323705 func testFindInPageTwoWordsSearch() { userState.url = path(forTestPage: "test-mozilla-book.html") openFindInPageFromMenu(openSite: userState.url!) @@ -88,7 +88,7 @@ class FindInPageTests: BaseTestCase { XCTAssertTrue(app.staticTexts["1 of 6"].exists) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2323714 + // https://mozilla.testrail.io/index.php?/cases/view/2323714 func testFindInPageTwoWordsSearchLargeDoc() { navigator.openURL("http://localhost:\(serverPort)/test-fixture/find-in-page-test.html") // Workaround until FxSGraph is fixed to allow the previous way with goto @@ -103,7 +103,7 @@ class FindInPageTests: BaseTestCase { XCTAssertEqual(app.staticTexts["find.resultLabel"].label, "1 of 1,000", "The book word count does match") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2323718 + // https://mozilla.testrail.io/index.php?/cases/view/2323718 func testFindInPageResultsPageShowHideContent() { userState.url = path(forTestPage: "test-mozilla-book.html") openFindInPageFromMenu(openSite: userState.url!) @@ -115,7 +115,7 @@ class FindInPageTests: BaseTestCase { XCTAssertTrue(app.staticTexts["1 of 6"].exists) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2323801 + // https://mozilla.testrail.io/index.php?/cases/view/2323801 func testQueryWithNoMatches() { userState.url = path(forTestPage: "test-mozilla-book.html") openFindInPageFromMenu(openSite: userState.url!) @@ -126,7 +126,7 @@ class FindInPageTests: BaseTestCase { XCTAssertTrue(app.staticTexts["0"].exists, "There should not be any matches") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2323802 + // https://mozilla.testrail.io/index.php?/cases/view/2323802 func testBarDisappearsWhenReloading() { userState.url = path(forTestPage: "test-mozilla-book.html") openFindInPageFromMenu(openSite: userState.url!) @@ -140,7 +140,7 @@ class FindInPageTests: BaseTestCase { XCTAssertFalse(app.searchFields["find.searchField"].exists) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2323803 + // https://mozilla.testrail.io/index.php?/cases/view/2323803 func testBarDisappearsWhenOpeningTabsTray() { userState.url = path(forTestPage: "test-mozilla-book.html") openFindInPageFromMenu(openSite: userState.url!) @@ -159,7 +159,7 @@ class FindInPageTests: BaseTestCase { XCTAssertFalse(app.buttons[AccessibilityIdentifiers.FindInPage.findPreviousButton].exists) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2323467 + // https://mozilla.testrail.io/index.php?/cases/view/2323467 func testFindFromLongTap() { userState.url = path(forTestPage: "test-mozilla-book.html") openFindInPageFromMenu(openSite: userState.url!) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/FirefoxSuggestTest.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/FirefoxSuggestTest.swift index 32b155339468..bb4745623732 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/FirefoxSuggestTest.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/FirefoxSuggestTest.swift @@ -5,7 +5,7 @@ import XCTest class FirefoxSuggestTest: BaseTestCase { - // https://testrail.stage.mozaws.net/index.php?/cases/view/2360075 + // https://mozilla.testrail.io/index.php?/cases/view/2360075 func testFirefoxSuggestExists() { navigator.openURL("www.example.com") navigator.createNewTab() diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/HistoryTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/HistoryTests.swift index 3cfcddf84fd4..bc3d6148b215 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/HistoryTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/HistoryTests.swift @@ -55,7 +55,7 @@ class HistoryTests: BaseTestCase { super.setUp() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307300 + // https://mozilla.testrail.io/index.php?/cases/view/2307300 func testEmptyHistoryListFirstTime() { navigator.nowAt(NewTabScreen) @@ -66,7 +66,7 @@ class HistoryTests: BaseTestCase { mozWaitForElementToExist(app.tables[HistoryPanelA11y.tableView].staticTexts[emptyRecentlyClosedMesg]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307301 + // https://mozilla.testrail.io/index.php?/cases/view/2307301 func testOpenSyncDevices() { // Firefox sync page should be available navigator.nowAt(NewTabScreen) @@ -76,7 +76,7 @@ class HistoryTests: BaseTestCase { mozWaitForElementToExist(app.otherElements.buttons["Sync and Save Data"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307487 + // https://mozilla.testrail.io/index.php?/cases/view/2307487 func testClearHistoryFromSettings() throws { XCTExpectFailure("The app was not launched", strict: false) { navigator.nowAt(NewTabScreen) @@ -102,7 +102,7 @@ class HistoryTests: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307014 + // https://mozilla.testrail.io/index.php?/cases/view/2307014 // Smoketest func testClearPrivateData() throws { XCTExpectFailure("The app was not launched", strict: false) { @@ -127,7 +127,7 @@ class HistoryTests: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307357 + // https://mozilla.testrail.io/index.php?/cases/view/2307357 func testRecentlyClosedWebsiteOpen() { // Open "Book of Mozilla" openBookOfMozilla() @@ -140,7 +140,7 @@ class HistoryTests: BaseTestCase { mozWaitForElementToExist(app.tables[HistoryPanelA11y.tableView].staticTexts[emptyRecentlyClosedMesg]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307463 + // https://mozilla.testrail.io/index.php?/cases/view/2307463 func testRecentlyClosedWebsiteClosed() { // Open "Book of Mozilla" and close the tab openBookOfMozilla() @@ -161,7 +161,7 @@ class HistoryTests: BaseTestCase { mozWaitForElementToExist(app.tables.cells.staticTexts[bookOfMozilla["label"]!]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307475 + // https://mozilla.testrail.io/index.php?/cases/view/2307475 func testRecentlyClosedPrivateMode() { // Open "Book of Mozilla" on private mode and close the tab waitForTabsButton() @@ -181,7 +181,7 @@ class HistoryTests: BaseTestCase { mozWaitForElementToNotExist(app.tables.cells.staticTexts[bookOfMozilla["label"]!]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307479 + // https://mozilla.testrail.io/index.php?/cases/view/2307479 func testRemoveAllTabsButtonRecentlyClosedHistory() { // Open "Book of Mozilla" openBookOfMozilla() @@ -200,7 +200,7 @@ class HistoryTests: BaseTestCase { mozWaitForElementToExist(app.tables.cells.staticTexts[bookOfMozilla["label"]!]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307482 + // https://mozilla.testrail.io/index.php?/cases/view/2307482 func testClearRecentlyClosedHistory() { // Open "Book of Mozilla" and close the tab openBookOfMozilla() @@ -226,7 +226,7 @@ class HistoryTests: BaseTestCase { mozWaitForElementToNotExist(app.tables.cells.staticTexts[bookOfMozilla["label"]!]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307483 + // https://mozilla.testrail.io/index.php?/cases/view/2307483 func testLongTapOptionsRecentlyClosedItem() { // Open "Book of Mozilla" and close the tab openBookOfMozilla() @@ -243,7 +243,7 @@ class HistoryTests: BaseTestCase { mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.privateMode]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307484 + // https://mozilla.testrail.io/index.php?/cases/view/2307484 func testOpenInNewTabRecentlyClosedItem() { // Open "Book of Mozilla" and close the tab openBookOfMozilla() @@ -274,7 +274,7 @@ class HistoryTests: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307485 + // https://mozilla.testrail.io/index.php?/cases/view/2307485 func testOpenInNewPrivateTabRecentlyClosedItem() { // Open "Book of Mozilla" and close the tab openBookOfMozilla() @@ -308,7 +308,7 @@ class HistoryTests: BaseTestCase { XCTAssertEqual(userState.numTabs, 1) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307486 + // https://mozilla.testrail.io/index.php?/cases/view/2307486 func testPrivateClosedSiteDoesNotAppearOnRecentlyClosed() { navigator.nowAt(NewTabScreen) @@ -349,7 +349,7 @@ class HistoryTests: BaseTestCase { XCTAssertFalse(app.tables.cells.staticTexts[bookOfMozilla["label"]!].exists) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307025 + // https://mozilla.testrail.io/index.php?/cases/view/2307025 // Smoke func testTabHistory() { navigator.nowAt(NewTabScreen) @@ -426,7 +426,7 @@ class HistoryTests: BaseTestCase { navigator.nowAt(NewTabScreen) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306894 + // https://mozilla.testrail.io/index.php?/cases/view/2306894 // Smoke func testClearRecentHistory() { // Visit a page to create a recent history entry. @@ -467,7 +467,7 @@ class HistoryTests: BaseTestCase { mozWaitForElementToNotExist(app.staticTexts["Older"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306890 + // https://mozilla.testrail.io/index.php?/cases/view/2306890 // Smoketest func testDeleteHistoryEntryBySwiping() { navigateToPage() diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/HomeButtonTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/HomeButtonTests.swift index 9f4b93aba10b..0caf8ee5b1b0 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/HomeButtonTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/HomeButtonTests.swift @@ -10,7 +10,7 @@ class HomeButtonTests: BaseTestCase { super.tearDown() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306925 + // https://mozilla.testrail.io/index.php?/cases/view/2306925 func testGoHome() throws { if iPad() { waitForTabsButton() @@ -34,7 +34,7 @@ class HomeButtonTests: BaseTestCase { navigator.nowAt(NewTabScreen) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306883 + // https://mozilla.testrail.io/index.php?/cases/view/2306883 func testSwitchHomepageKeyboardNotRaisedUp() { // Open a new tab and load a web page navigator.openURL("http://localhost:\(serverPort)/test-fixture/find-in-page-test.html") @@ -47,7 +47,7 @@ class HomeButtonTests: BaseTestCase { validateHomePageAndKeyboardNotRaisedUp() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306881 + // https://mozilla.testrail.io/index.php?/cases/view/2306881 func testAppLaunchKeyboardNotRaisedUp() { mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton]) validateHomePageAndKeyboardNotRaisedUp() diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/HomePageSettingsUITest.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/HomePageSettingsUITest.swift index a8a63eff86a9..a41f22693934 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/HomePageSettingsUITest.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/HomePageSettingsUITest.swift @@ -38,7 +38,7 @@ class HomePageSettingsUITests: BaseTestCase { super.setUp() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2339256 + // https://mozilla.testrail.io/index.php?/cases/view/2339256 func testCheckHomeSettingsByDefault() { navigator.nowAt(NewTabScreen) navigator.goto(HomeSettings) @@ -71,7 +71,7 @@ class HomePageSettingsUITests: BaseTestCase { mozWaitForElementToExist(app.tables.cells["HomeAsCustomURL"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2339257 + // https://mozilla.testrail.io/index.php?/cases/view/2339257 func testTyping() { waitForTabsButton() navigator.nowAt(NewTabScreen) @@ -96,7 +96,7 @@ class HomePageSettingsUITests: BaseTestCase { mozWaitForValueContains(app.textFields["url"], value: "example") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2339258 + // https://mozilla.testrail.io/index.php?/cases/view/2339258 func testClipboard() { navigator.nowAt(NewTabScreen) // Check that what's in clipboard is copied @@ -121,7 +121,7 @@ class HomePageSettingsUITests: BaseTestCase { mozWaitForValueContains(app.textFields["HomeAsCustomURLTextField"], value: websiteUrl1) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2339260 + // https://mozilla.testrail.io/index.php?/cases/view/2339260 func testSetFirefoxHomeAsHome() { // Start by setting to History since FF Home is default waitForTabsButton() @@ -144,7 +144,7 @@ class HomePageSettingsUITests: BaseTestCase { mozWaitForElementToExist(app.cells[AccessibilityIdentifiers.FirefoxHomepage.TopSites.itemCell]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307031 + // https://mozilla.testrail.io/index.php?/cases/view/2307031 func testSetCustomURLAsHome() { waitForTabsButton() navigator.nowAt(NewTabScreen) @@ -165,7 +165,7 @@ class HomePageSettingsUITests: BaseTestCase { mozWaitForValueContains(app.textFields["url"], value: "mozilla") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2339489 + // https://mozilla.testrail.io/index.php?/cases/view/2339489 func testDisableTopSitesSettingsRemovesSection() { mozWaitForElementToExist( app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton] @@ -183,7 +183,7 @@ class HomePageSettingsUITests: BaseTestCase { mozWaitForElementToNotExist(app.collectionViews.cells.staticTexts["YouTube"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2339491 + // https://mozilla.testrail.io/index.php?/cases/view/2339491 func testChangeHomeSettingsLabel() { // Go to New Tab settings and select Custom URL option navigator.performAction(Action.SelectHomeAsCustomURL) @@ -214,7 +214,7 @@ class HomePageSettingsUITests: BaseTestCase { XCTAssertEqual(numberOfTopSites, numberOfExpectedTopSites) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307033 + // https://mozilla.testrail.io/index.php?/cases/view/2307033 func testJumpBackIn() { navigator.openURL(path(forTestPage: exampleUrl)) waitUntilPageLoad() @@ -254,7 +254,7 @@ class HomePageSettingsUITests: BaseTestCase { mozWaitForElementToNotExist(app.buttons[AccessibilityIdentifiers.FirefoxHomepage.MoreButtons.jumpBackIn]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307034 + // https://mozilla.testrail.io/index.php?/cases/view/2307034 func testRecentlySaved() { // Preconditons: Create 6 bookmarks & add 1 items to reading list bookmarkPages() @@ -295,7 +295,7 @@ class HomePageSettingsUITests: BaseTestCase { checkBookmarksUpdated() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306923 + // https://mozilla.testrail.io/index.php?/cases/view/2306923 // Smoketest // FXIOS-8107: Disabled test as history highlights has been disabled to fix app hangs / slowness // Reloads for notification @@ -351,7 +351,7 @@ class HomePageSettingsUITests: BaseTestCase { // swiftlint:enable line_length // } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306871 + // https://mozilla.testrail.io/index.php?/cases/view/2306871 // Smoketest func testCustomizeHomepage() { if !iPad() { @@ -399,7 +399,7 @@ class HomePageSettingsUITests: BaseTestCase { ) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307032 + // https://mozilla.testrail.io/index.php?/cases/view/2307032 func testShortcutsRows() { addWebsitesToShortcut(website: path(forTestPage: url_1)) addWebsitesToShortcut(website: path(forTestPage: url_2["url"]!)) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/JumpBackInTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/JumpBackInTests.swift index 36c3cdaf283f..01961b944b20 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/JumpBackInTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/JumpBackInTests.swift @@ -32,7 +32,7 @@ class JumpBackInTests: BaseTestCase { navigator.goto(NewTabScreen) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306922 + // https://mozilla.testrail.io/index.php?/cases/view/2306922 func testJumpBackInSection() { // Open a tab and visit a page navigator.openURL("https://www.example.com") @@ -49,7 +49,7 @@ class JumpBackInTests: BaseTestCase { // I don't test for its existence. } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306920 + // https://mozilla.testrail.io/index.php?/cases/view/2306920 // Smoketest func testPrivateTab() throws { throw XCTSkip("This test is flaky") @@ -147,7 +147,7 @@ class JumpBackInTests: BaseTestCase { // mozWaitForElementToNotExist(app.cells["JumpBackInCell"].staticTexts["YouTube"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2445811 + // https://mozilla.testrail.io/index.php?/cases/view/2445811 func testLongTapOnJumpBackInLink() { // On homepage, go to the "Jump back in" section and long tap on one of the links navigator.openURL(path(forTestPage: "test-example.html")) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/LoginsTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/LoginsTests.swift index 64fe66472907..eafe906dd237 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/LoginsTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/LoginsTests.swift @@ -55,7 +55,7 @@ class LoginTest: BaseTestCase { navigator.nowAt(LoginsSettings) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306961 + // https://mozilla.testrail.io/index.php?/cases/view/2306961 func testLoginsListFromBrowserTabMenu() { closeURLBar() // Make sure you can access empty Login List from Browser Tab Menu @@ -77,7 +77,7 @@ class LoginTest: BaseTestCase { XCTAssertEqual(app.tables["Login List"].cells.count, defaultNumRowsLoginsList + 1) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306951 + // https://mozilla.testrail.io/index.php?/cases/view/2306951 // Smoketest func testSaveLogin() { closeURLBar() @@ -122,7 +122,7 @@ class LoginTest: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306965 + // https://mozilla.testrail.io/index.php?/cases/view/2306965 func testDoNotSaveLogin() { navigator.openURL(testLoginPage) waitUntilPageLoad() @@ -135,7 +135,7 @@ class LoginTest: BaseTestCase { XCTAssertEqual(app.tables["Login List"].cells.count, defaultNumRowsLoginsList) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306962 + // https://mozilla.testrail.io/index.php?/cases/view/2306962 func testSavedLoginSelectUnselect() { saveLogin(givenUrl: testLoginPage) navigator.goto(SettingsScreen) @@ -154,7 +154,7 @@ class LoginTest: BaseTestCase { mozWaitForElementToExist(app.buttons["Delete"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306963 + // https://mozilla.testrail.io/index.php?/cases/view/2306963 func testDeleteLogin() { saveLogin(givenUrl: testLoginPage) openLoginsSettings() @@ -170,7 +170,7 @@ class LoginTest: BaseTestCase { XCTAssertEqual(app.tables["Login List"].cells.count, defaultNumRowsLoginsList) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306966 + // https://mozilla.testrail.io/index.php?/cases/view/2306966 func testEditOneLoginEntry() { // Go to test login page and save the login: test-password.html saveLogin(givenUrl: testLoginPage) @@ -204,7 +204,7 @@ class LoginTest: BaseTestCase { mozWaitForElementToExist(app.tables.cells[loginsListPasswordLabel]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306964 + // https://mozilla.testrail.io/index.php?/cases/view/2306964 func testSearchLogin() { saveLogin(givenUrl: testLoginPage) openLoginsSettings() @@ -226,7 +226,7 @@ class LoginTest: BaseTestCase { XCTAssertEqual(app.tables["Login List"].cells.count, defaultNumRowsLoginsList + 1) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306952 + // https://mozilla.testrail.io/index.php?/cases/view/2306952 // Smoketest func testSavedLoginAutofilled() { navigator.openURL(urlLogin) @@ -261,7 +261,7 @@ class LoginTest: BaseTestCase { // XCTAssertEqual(passwordValue as! String, "••••••••") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306953 + // https://mozilla.testrail.io/index.php?/cases/view/2306953 // Smoketest func testCreateLoginManually() { closeURLBar() @@ -278,7 +278,7 @@ class LoginTest: BaseTestCase { mozWaitForElementToExist(app.tables["Login List"].staticTexts["https://testweb"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306954 + // https://mozilla.testrail.io/index.php?/cases/view/2306954 func testAddDuplicateLogin() { // Add login credential openLoginsSettingsFromBrowserTab() diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/NavigationTest.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/NavigationTest.swift index 57bb8c7a6396..f90fad4483ea 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/NavigationTest.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/NavigationTest.swift @@ -21,7 +21,7 @@ let website_2 = [ let popUpTestUrl = path(forTestPage: "test-popup-blocker.html") class NavigationTest: BaseTestCase { - // https://testrail.stage.mozaws.net/index.php?/cases/view/2441488 + // https://mozilla.testrail.io/index.php?/cases/view/2441488 func testNavigation() { let urlPlaceholder = "Search or enter address" mozWaitForElementToExist(app.textFields["url"]) @@ -67,7 +67,7 @@ class NavigationTest: BaseTestCase { mozWaitForValueContains(app.textFields["url"], value: "test-mozilla-org") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2441489 + // https://mozilla.testrail.io/index.php?/cases/view/2441489 func testTapSignInShowsFxAFromTour() { waitForTabsButton() navigator.nowAt(NewTabScreen) @@ -78,7 +78,7 @@ class NavigationTest: BaseTestCase { mozWaitForElementToExist(app.webViews.staticTexts["Continue to your Mozilla account"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2441493 + // https://mozilla.testrail.io/index.php?/cases/view/2441493 func testTapSigninShowsFxAFromSettings() { waitForTabsButton() navigator.nowAt(NewTabScreen) @@ -118,7 +118,7 @@ class NavigationTest: BaseTestCase { XCTAssertEqual(mailPlaceholder, defaultMailPlaceholder, "The mail placeholder does not show the correct value") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2441494 + // https://mozilla.testrail.io/index.php?/cases/view/2441494 func testTapSignInShowsFxAFromRemoteTabPanel() { waitForTabsButton() navigator.nowAt(NewTabScreen) @@ -131,7 +131,7 @@ class NavigationTest: BaseTestCase { mozWaitForElementToExist(app.buttons["Use Email Instead"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2441495 + // https://mozilla.testrail.io/index.php?/cases/view/2441495 func testScrollsToTopWithMultipleTabs() { navigator.goto(TabTray) navigator.openURL(website_1["url"]!) @@ -148,7 +148,7 @@ class NavigationTest: BaseTestCase { mozWaitForElementToExist(topElement) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306836 + // https://mozilla.testrail.io/index.php?/cases/view/2306836 // Smoketest func testLongPressLinkOptions() { openContextMenuForArticleLink() @@ -160,7 +160,7 @@ class NavigationTest: BaseTestCase { mozWaitForElementToExist(app.buttons["Bookmark Link"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2441496 + // https://mozilla.testrail.io/index.php?/cases/view/2441496 func testCopyLink() { longPressLinkOptions(optionSelected: "Copy Link") navigator.goto(NewTabScreen) @@ -173,7 +173,7 @@ class NavigationTest: BaseTestCase { mozWaitForValueContains(app.textFields["url"], value: website_2["moreLinkLongPressInfo"]!) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2441497 + // https://mozilla.testrail.io/index.php?/cases/view/2441497 func testCopyLinkPrivateMode() { navigator.nowAt(NewTabScreen) navigator.toggleOn(userState.isPrivate, withAction: Action.TogglePrivateMode) @@ -189,7 +189,7 @@ class NavigationTest: BaseTestCase { mozWaitForValueContains(app.textFields["url"], value: website_2["moreLinkLongPressInfo"]!) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2441923 + // https://mozilla.testrail.io/index.php?/cases/view/2441923 func testLongPressOnAddressBar() throws { // Long press on the URL requires copy & paste permission throw XCTSkip("Test needs to be updated") @@ -267,7 +267,7 @@ class NavigationTest: BaseTestCase { app.buttons[optionSelected].tap() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2441498 + // https://mozilla.testrail.io/index.php?/cases/view/2441498 func testDownloadLink() { longPressLinkOptions(optionSelected: "Download Link") mozWaitForElementToExist(app.tables["Context Menu"]) @@ -287,7 +287,7 @@ class NavigationTest: BaseTestCase { mozWaitForValueContains(app.textFields["url"], value: "example-domains.html") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2441499 + // https://mozilla.testrail.io/index.php?/cases/view/2441499 func testShareLink() { longPressLinkOptions(optionSelected: "Share Link") if #available(iOS 16, *) { @@ -305,7 +305,7 @@ class NavigationTest: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2441500 + // https://mozilla.testrail.io/index.php?/cases/view/2441500 func testShareLinkPrivateMode() { navigator.nowAt(NewTabScreen) navigator.toggleOn(userState.isPrivate, withAction: Action.TogglePrivateMode) @@ -325,7 +325,7 @@ class NavigationTest: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2441776 + // https://mozilla.testrail.io/index.php?/cases/view/2441776 // Smoketest func testPopUpBlocker() throws { throw XCTSkip("This test is flakey") @@ -362,7 +362,7 @@ class NavigationTest: BaseTestCase { // XCTAssertNotEqual("1", numTabsAfter as? String, "Several tabs are open") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306858 + // https://mozilla.testrail.io/index.php?/cases/view/2306858 // Smoketest func testSSL() { navigator.nowAt(NewTabScreen) @@ -376,7 +376,7 @@ class NavigationTest: BaseTestCase { mozWaitForElementToExist(app.webViews.otherElements["expired.badssl.com"], timeout: TIMEOUT_LONG) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307022 + // https://mozilla.testrail.io/index.php?/cases/view/2307022 // In this test, the parent window opens a child and in the child it creates a fake link 'link-created-by-parent' func testWriteToChildPopupTab() { waitForTabsButton() @@ -394,7 +394,7 @@ class NavigationTest: BaseTestCase { mozWaitForElementToExist(app.links["link-created-by-parent"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307020 + // https://mozilla.testrail.io/index.php?/cases/view/2307020 // Smoketest func testVerifyBrowserTabMenu() { mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton]) @@ -415,7 +415,7 @@ class NavigationTest: BaseTestCase { mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.settings]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2441775 + // https://mozilla.testrail.io/index.php?/cases/view/2441775 // Smoketest func testURLBar() { let urlBar = app.textFields["url"] @@ -435,7 +435,7 @@ class NavigationTest: BaseTestCase { // swiftlint:enable empty_count } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2441772 + // https://mozilla.testrail.io/index.php?/cases/view/2441772 func testOpenInNewTab() { // Long-tap on an article link. Choose "Open in New Tab". openContextMenuForArticleLink() @@ -449,7 +449,7 @@ class NavigationTest: BaseTestCase { mozWaitForElementToExist(app.otherElements["Tabs Tray"].cells.elementContainingText("Example Domain.")) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2441773 + // https://mozilla.testrail.io/index.php?/cases/view/2441773 func testOpenInNewPrivateTab() { // Long-tap on an article link. Choose "Open in New Private Tab". openContextMenuForArticleLink() @@ -470,7 +470,7 @@ class NavigationTest: BaseTestCase { mozWaitForElementToExist(app.otherElements["Tabs Tray"].cells.staticTexts["Example Domains"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2441774 + // https://mozilla.testrail.io/index.php?/cases/view/2441774 func testBookmarkLink() { // Long-tap on an article link. Choose "Bookmark Link". openContextMenuForArticleLink() diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/NewTabSettings.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/NewTabSettings.swift index 39e9ce60de4f..1aaf84d40e4c 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/NewTabSettings.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/NewTabSettings.swift @@ -6,7 +6,7 @@ import XCTest let websiteUrl = "www.mozilla.org" class NewTabSettingsTest: BaseTestCase { - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307026 + // https://mozilla.testrail.io/index.php?/cases/view/2307026 // Smoketest func testCheckNewTabSettingsByDefault() { mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton]) @@ -18,7 +18,7 @@ class NewTabSettingsTest: BaseTestCase { mozWaitForElementToExist(app.tables.cells["NewTabAsCustomURL"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307027 + // https://mozilla.testrail.io/index.php?/cases/view/2307027 // Smoketest func testChangeNewTabSettingsShowBlankPage() { mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton]) @@ -38,7 +38,7 @@ class NewTabSettingsTest: BaseTestCase { mozWaitForElementToNotExist(app.staticTexts["Highlights"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307028 + // https://mozilla.testrail.io/index.php?/cases/view/2307028 func testChangeNewTabSettingsShowFirefoxHome() { // Set to history page first since FF Home is default waitForTabsButton() @@ -60,7 +60,7 @@ class NewTabSettingsTest: BaseTestCase { mozWaitForElementToExist(app.collectionViews.cells[AccessibilityIdentifiers.FirefoxHomepage.TopSites.itemCell]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307029 + // https://mozilla.testrail.io/index.php?/cases/view/2307029 // Smoketest func testChangeNewTabSettingsShowCustomURL() { navigator.nowAt(NewTabScreen) @@ -83,7 +83,7 @@ class NewTabSettingsTest: BaseTestCase { mozWaitForValueContains(app.textFields["url"], value: "mozilla") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307030 + // https://mozilla.testrail.io/index.php?/cases/view/2307030 func testChangeNewTabSettingsLabel() { navigator.nowAt(NewTabScreen) // Go to New Tab settings and select Custom URL option @@ -107,7 +107,7 @@ class NewTabSettingsTest: BaseTestCase { XCTAssertEqual(app.tables.cells["NewTab"].label, "New Tab, Firefox Home") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306877 + // https://mozilla.testrail.io/index.php?/cases/view/2306877 // Smoketest func testKeyboardRaisedWhenTabOpenedFromTabTray() { // Add New tab and set it as Blank @@ -128,7 +128,7 @@ class NewTabSettingsTest: BaseTestCase { validateKeyboardIsRaisedAndDismissed() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306875 + // https://mozilla.testrail.io/index.php?/cases/view/2306875 // Smoketest func testNewTabCustomURLKeyboardNotRaised() { // Set a custom URL diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/NightModeTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/NightModeTests.swift index d92447db85be..1abae1456093 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/NightModeTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/NightModeTests.swift @@ -14,7 +14,7 @@ class NightModeTests: BaseTestCase { mozWaitForElementToExist(app.tables.otherElements[StandardImageIdentifiers.Large.nightMode]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307056 + // https://mozilla.testrail.io/index.php?/cases/view/2307056 func testNightModeUI() { let url1 = "test-example.html" // Go to a webpage, and select night mode on and off, check it's applied or not diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/OnboardingTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/OnboardingTests.swift index fb0ce7285479..9887dba314d7 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/OnboardingTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/OnboardingTests.swift @@ -19,7 +19,7 @@ class OnboardingTests: BaseTestCase { } // Smoketest - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306814 + // https://mozilla.testrail.io/index.php?/cases/view/2306814 func testFirstRunTour() { // Complete the First run from first screen to the latest one // Check that the first's tour screen is shown as well as all the elements in there @@ -77,14 +77,14 @@ class OnboardingTests: BaseTestCase { } // Smoketest - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306816 + // https://mozilla.testrail.io/index.php?/cases/view/2306816 func testCloseTour() { app.buttons["\(AccessibilityIdentifiers.Onboarding.closeButton)"].tap() let topSites = app.collectionViews.cells[AccessibilityIdentifiers.FirefoxHomepage.TopSites.itemCell] mozWaitForElementToExist(topSites) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306815 + // https://mozilla.testrail.io/index.php?/cases/view/2306815 func testWhatsNewPage() { app.buttons["\(AccessibilityIdentifiers.Onboarding.closeButton)"].tap() navigator.goto(BrowserTabMenu) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/OpeningScreenTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/OpeningScreenTests.swift index e8601be815be..80b03467ec6d 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/OpeningScreenTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/OpeningScreenTests.swift @@ -4,7 +4,7 @@ import Foundation class OpeningScreenTests: BaseTestCase { - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307039 + // https://mozilla.testrail.io/index.php?/cases/view/2307039 func testLastOpenedTab() { // Open a web page navigator.openURL(path(forTestPage: "test-mozilla-org.html"), waitForLoading: true) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/PhotonActionSheetTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/PhotonActionSheetTests.swift index c4fa07086bd6..d918b4e613ad 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/PhotonActionSheetTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/PhotonActionSheetTests.swift @@ -6,7 +6,7 @@ import XCTest import Common class PhotonActionSheetTests: BaseTestCase { - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306849 + // https://mozilla.testrail.io/index.php?/cases/view/2306849 // Smoketest func testPinToShortcuts() { navigator.openURL("http://example.com") @@ -31,7 +31,7 @@ class PhotonActionSheetTests: BaseTestCase { mozWaitForElementToExist(app.tables.cells.otherElements[StandardImageIdentifiers.Large.pin]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2322067 + // https://mozilla.testrail.io/index.php?/cases/view/2322067 // Smoketest func testShareOptionIsShown() { // Temporarily disabled until url bar redesign work FXIOS-8172 @@ -44,7 +44,7 @@ class PhotonActionSheetTests: BaseTestCase { // mozWaitForElementToExist(app.cells["Copy"], timeout: 15) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2322667 + // https://mozilla.testrail.io/index.php?/cases/view/2322667 func testSendToDeviceFromPageOptionsMenu() { // User not logged in navigator.openURL(path(forTestPage: "test-mozilla-org.html")) @@ -93,7 +93,7 @@ class PhotonActionSheetTests: BaseTestCase { mozWaitForElementToExist(app.navigationBars["ShareTo.ShareView"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306841 + // https://mozilla.testrail.io/index.php?/cases/view/2306841 // Smoketest func testSharePageWithShareSheetOptions() { openNewShareSheet() @@ -104,7 +104,7 @@ class PhotonActionSheetTests: BaseTestCase { mozWaitForElementToExist(app.staticTexts["Send to Device"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2323203 + // https://mozilla.testrail.io/index.php?/cases/view/2323203 func testShareSheetSendToDevice() { openNewShareSheet() mozWaitForElementToExist(app.staticTexts["Send to Device"]) @@ -117,7 +117,7 @@ class PhotonActionSheetTests: BaseTestCase { app.navigationBars.buttons[AccessibilityIdentifiers.ShareTo.HelpView.doneButton].tap() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2323204 + // https://mozilla.testrail.io/index.php?/cases/view/2323204 func testShareSheetOpenAndCancel() { openNewShareSheet() app.buttons["Cancel"].tap() diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/PocketTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/PocketTests.swift index 0f2349556eaf..0da6a27c2d59 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/PocketTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/PocketTests.swift @@ -5,7 +5,7 @@ import XCTest class PocketTests: BaseTestCase { - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306924 + // https://mozilla.testrail.io/index.php?/cases/view/2306924 func testPocketEnabledByDefault() { navigator.goto(NewTabScreen) mozWaitForElementToExist(app.staticTexts[AccessibilityIdentifiers.FirefoxHomepage.SectionTitles.pocket]) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/PrivateBrowsingTest.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/PrivateBrowsingTest.swift index 19af4e4999aa..6a23a26d28a1 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/PrivateBrowsingTest.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/PrivateBrowsingTest.swift @@ -15,7 +15,7 @@ let url2Label = "Internet for people, not profit — Mozilla" class PrivateBrowsingTest: BaseTestCase { typealias HistoryPanelA11y = AccessibilityIdentifiers.LibraryPanels.HistoryPanel - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307004 + // https://mozilla.testrail.io/index.php?/cases/view/2307004 func testPrivateTabDoesNotTrackHistory() { navigator.openURL(url1) waitForTabsButton() @@ -45,7 +45,7 @@ class PrivateBrowsingTest: BaseTestCase { XCTAssertEqual(privateHistory, 1, "History entries in private browsing do not match") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307005 + // https://mozilla.testrail.io/index.php?/cases/view/2307005 func testTabCountShowsOnlyNormalOrPrivateTabCount() { // Open two tabs in normal browsing and check the number of tabs open navigator.nowAt(NewTabScreen) @@ -89,7 +89,7 @@ class PrivateBrowsingTest: BaseTestCase { XCTAssertEqual(numRegularTabs, 2, "The number of regular tabs is not correct") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307006 + // https://mozilla.testrail.io/index.php?/cases/view/2307006 func testClosePrivateTabsOptionClosesPrivateTabs() { // Check that Close Private Tabs when closing the Private Browsing Button is off by default navigator.nowAt(NewTabScreen) @@ -120,7 +120,7 @@ class PrivateBrowsingTest: BaseTestCase { created (because the db didn't exist in the cache) https://bugzilla.mozilla.org/show_bug.cgi?id=1646756 */ - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307011 + // https://mozilla.testrail.io/index.php?/cases/view/2307011 func testClearIndexedDB() { navigator.nowAt(NewTabScreen) @@ -145,7 +145,7 @@ class PrivateBrowsingTest: BaseTestCase { // checkIndexedDBIsCreated() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307007 + // https://mozilla.testrail.io/index.php?/cases/view/2307007 func testPrivateBrowserPanelView() { navigator.nowAt(NewTabScreen) // If no private tabs are open, there should be a initial screen with label Private Browsing @@ -174,7 +174,7 @@ class PrivateBrowsingTest: BaseTestCase { XCTAssertEqual(numPrivTabsOpen, 1, "The number of private tabs is not correct") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307012 + // https://mozilla.testrail.io/index.php?/cases/view/2307012 func testLongPressLinkOptionsPrivateMode() { navigator.nowAt(NewTabScreen) navigator.toggleOn(userState.isPrivate, withAction: Action.TogglePrivateMode) @@ -191,7 +191,7 @@ class PrivateBrowsingTest: BaseTestCase { mozWaitForElementToExist(app.buttons["Download Link"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2497357 + // https://mozilla.testrail.io/index.php?/cases/view/2497357 func testAllPrivateTabsRestore() { // Several tabs opened in private tabs tray. Tap on the trashcan navigator.nowAt(NewTabScreen) @@ -238,7 +238,7 @@ class PrivateBrowsingTest: BaseTestCase { XCTAssertEqual(4, numTab, "The number of counted tabs is not equal to \(String(describing: numTab))") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307003 + // https://mozilla.testrail.io/index.php?/cases/view/2307003 func testHamburgerMenuNewPrivateTab() { navigator.toggleOn(userState.isPrivate, withAction: Action.TogglePrivateMode) navigator.openURL(urlExample) @@ -283,7 +283,7 @@ fileprivate extension BaseTestCase { class PrivateBrowsingTestIphone: IphoneOnlyTestCase { // This test is disabled for iPad because the toast menu is not shown there - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307013 + // https://mozilla.testrail.io/index.php?/cases/view/2307013 // Smoketest func testSwitchBetweenPrivateTabsToastButton() { if skipPlatform { return } @@ -314,7 +314,7 @@ class PrivateBrowsingTestIpad: IpadOnlyTestCase { typealias HistoryPanelA11y = AccessibilityIdentifiers.LibraryPanels.HistoryPanel // This test is only enabled for iPad. Shortcut does not exists on iPhone - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307008 + // https://mozilla.testrail.io/index.php?/cases/view/2307008 func testClosePrivateTabsOptionClosesPrivateTabsShortCutiPad() { if skipPlatform { return } waitForTabsButton() @@ -329,7 +329,7 @@ class PrivateBrowsingTestIpad: IpadOnlyTestCase { checkOpenTabsBeforeClosingPrivateMode() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307009 + // https://mozilla.testrail.io/index.php?/cases/view/2307009 func testiPadDirectAccessPrivateMode() { if skipPlatform { return } waitForTabsButton() @@ -354,7 +354,7 @@ class PrivateBrowsingTestIpad: IpadOnlyTestCase { XCTAssertEqual(history, 0, "History list should be empty") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307010 + // https://mozilla.testrail.io/index.php?/cases/view/2307010 func testiPadDirectAccessPrivateModeBrowserTab() { if skipPlatform { return } navigator.openURL("www.mozilla.org") diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/ReadingListTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/ReadingListTests.swift index 15aa751be555..b51f748b88e0 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/ReadingListTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/ReadingListTests.swift @@ -6,7 +6,7 @@ import Common import XCTest class ReadingListTests: BaseTestCase { - // https://testrail.stage.mozaws.net/index.php?/cases/view/2287278f + // https://mozilla.testrail.io/index.php?/cases/view/2287278f // Smoketest func testLoadReaderContent() { navigator.openURL(path(forTestPage: "test-mozilla-book.html")) @@ -25,7 +25,7 @@ class ReadingListTests: BaseTestCase { XCTAssertEqual(list, items, "The number of items in the reading table is not correct") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306991 + // https://mozilla.testrail.io/index.php?/cases/view/2306991 // Smoketest func testAddToReadingList() { navigator.nowAt(NewTabScreen) @@ -47,7 +47,7 @@ class ReadingListTests: BaseTestCase { checkReadingListNumberOfItems(items: 1) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306995 + // https://mozilla.testrail.io/index.php?/cases/view/2306995 func testAddToReadingListPrivateMode() { navigator.nowAt(NewTabScreen) navigator.toggleOn(userState.isPrivate, withAction: Action.TogglePrivateMode) @@ -84,7 +84,7 @@ class ReadingListTests: BaseTestCase { checkReadingListNumberOfItems(items: 1) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306992 + // https://mozilla.testrail.io/index.php?/cases/view/2306992 func testMarkAsReadAndUreadFromReaderView() { addContentToReaderView() @@ -97,7 +97,7 @@ class ReadingListTests: BaseTestCase { mozWaitForElementToExist(app.buttons["Mark as Read"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306996 + // https://mozilla.testrail.io/index.php?/cases/view/2306996 func testRemoveFromReadingView() { addContentToReaderView() // Once the content has been added, remove it @@ -114,7 +114,7 @@ class ReadingListTests: BaseTestCase { checkReadingListNumberOfItems(items: 0) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306997 + // https://mozilla.testrail.io/index.php?/cases/view/2306997 func testMarkAsReadAndUnreadFromReadingList() throws { addContentToReaderView() navigator.goto(BrowserTabMenu) @@ -133,7 +133,7 @@ class ReadingListTests: BaseTestCase { mozWaitForElementToExist(app.tables.cells.buttons.staticTexts["Mark as Unread"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306998 + // https://mozilla.testrail.io/index.php?/cases/view/2306998 func testRemoveFromReadingList() { addContentToReaderView() navigator.goto(BrowserTabMenu) @@ -152,7 +152,7 @@ class ReadingListTests: BaseTestCase { checkReadingListNumberOfItems(items: 0) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306999 + // https://mozilla.testrail.io/index.php?/cases/view/2306999 func testAddToReadingListFromBrowserTabMenu() { navigator.nowAt(NewTabScreen) // First time Reading list is empty @@ -170,7 +170,7 @@ class ReadingListTests: BaseTestCase { checkReadingListNumberOfItems(items: 1) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307000 + // https://mozilla.testrail.io/index.php?/cases/view/2307000 func testOpenSavedForReadingLongPressInNewTab() { let numTab = app.buttons["Show Tabs"].value as? String XCTAssertEqual(numTab, "1") @@ -195,7 +195,7 @@ class ReadingListTests: BaseTestCase { // XCTAssertEqual(numTabAfter, "2") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307001 + // https://mozilla.testrail.io/index.php?/cases/view/2307001 func testRemoveSavedForReadingLongPress() { // Add item to Reading List addContentToReaderView() @@ -212,7 +212,7 @@ class ReadingListTests: BaseTestCase { mozWaitForElementToNotExist(app.tables["ReadingTable"].cells.staticTexts["The Book of Mozilla"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306893 + // https://mozilla.testrail.io/index.php?/cases/view/2306893 // Smoketest func testReadingList() { navigator.nowAt(NewTabScreen) @@ -261,7 +261,7 @@ class ReadingListTests: BaseTestCase { mozWaitForElementToExist(app.staticTexts[emptyReadingList3]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306993 + // https://mozilla.testrail.io/index.php?/cases/view/2306993 // Smoketest func testAddToReaderListOptions() { addContentToReaderView() diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/SearchSettingsUITest.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/SearchSettingsUITest.swift index a4cb73c1230b..342948392297 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/SearchSettingsUITest.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/SearchSettingsUITest.swift @@ -9,7 +9,7 @@ let defaultSearchEngine2 = "Bing" let customSearchEngine = ["name": "youtube", "url": "https://youtube.com/search?q=%s"] class SearchSettingsUITests: BaseTestCase { - // https://testrail.stage.mozaws.net/index.php?/cases/view/2435664 + // https://mozilla.testrail.io/index.php?/cases/view/2435664 func testDefaultSearchEngine() { navigator.nowAt(NewTabScreen) navigator.goto(SearchSettings) @@ -24,7 +24,7 @@ class SearchSettingsUITests: BaseTestCase { mozWaitForElementToExist(app.tables.cells.staticTexts[defaultSearchEngine2]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2353247 + // https://mozilla.testrail.io/index.php?/cases/view/2353247 func testCustomSearchEngineIsEditable() { navigator.nowAt(NewTabScreen) navigator.goto(SearchSettings) @@ -59,7 +59,7 @@ class SearchSettingsUITests: BaseTestCase { mozWaitForElementToExist(app.tables.cells.staticTexts[customSearchEngine["name"]!]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2353248 + // https://mozilla.testrail.io/index.php?/cases/view/2353248 func testCustomSearchEngineAsDefaultIsNotEditable() { navigator.nowAt(NewTabScreen) navigator.goto(SearchSettings) @@ -79,7 +79,7 @@ class SearchSettingsUITests: BaseTestCase { XCTAssertFalse(app.buttons["Edit"].isEnabled) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2353249 + // https://mozilla.testrail.io/index.php?/cases/view/2353249 func testNavigateToSearchPickerTurnsOffEditing() { navigator.nowAt(NewTabScreen) navigator.goto(SearchSettings) @@ -105,7 +105,7 @@ class SearchSettingsUITests: BaseTestCase { XCTAssertEqual(app.tables.cells.switches.count, app.tables.cells.count - 3) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2353250 + // https://mozilla.testrail.io/index.php?/cases/view/2353250 func testDeletingLastCustomEngineExitsEditing() { navigator.nowAt(NewTabScreen) navigator.goto(SearchSettings) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/SearchTest.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/SearchTest.swift index 25cee8cccb52..b0234b47872e 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/SearchTest.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/SearchTest.swift @@ -40,7 +40,7 @@ class SearchTests: BaseTestCase { mozWaitForElementToExist(elementQuery.element) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2436093 + // https://mozilla.testrail.io/index.php?/cases/view/2436093 func testPromptPresence() { // Suggestion is on by default (starting on Oct 24th 2017), so the prompt should not appear navigator.goto(URLBarOpen) @@ -88,7 +88,7 @@ class SearchTests: BaseTestCase { mozWaitForElementToExist(app.tables["SiteTable"].cells.firstMatch) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2436094 + // https://mozilla.testrail.io/index.php?/cases/view/2436094 func testDoNotShowSuggestionsWhenEnteringURL() { // According to bug 1192155 if a string contains /, do not show suggestions, if there a space an a string, // the suggestions are shown again @@ -122,7 +122,7 @@ class SearchTests: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2436095 + // https://mozilla.testrail.io/index.php?/cases/view/2436095 func testCopyPasteComplete() { // Copy, Paste and Go to url navigator.goto(URLBarOpen) @@ -179,7 +179,7 @@ class SearchTests: BaseTestCase { mozWaitForValueContains(app.textFields["url"], value: searchEngine.lowercased()) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306940 + // https://mozilla.testrail.io/index.php?/cases/view/2306940 // Smoketest func testSearchEngine() { navigator.nowAt(NewTabScreen) @@ -191,14 +191,14 @@ class SearchTests: BaseTestCase { changeSearchEngine(searchEngine: "Wikipedia") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2353246 + // https://mozilla.testrail.io/index.php?/cases/view/2353246 func testDefaultSearchEngine() { navigator.nowAt(NewTabScreen) navigator.goto(SearchSettings) XCTAssert(app.tables.staticTexts["Google"].exists) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2436091 + // https://mozilla.testrail.io/index.php?/cases/view/2436091 func testSearchWithFirefoxOption() { navigator.nowAt(NewTabScreen) navigator.openURL(path(forTestPage: "test-mozilla-book.html")) @@ -230,7 +230,7 @@ class SearchTests: BaseTestCase { XCTAssertEqual("2", numTab) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2436092 + // https://mozilla.testrail.io/index.php?/cases/view/2436092 // Smoketest func testSearchStartAfterTypingTwoWords() { navigator.goto(URLBarOpen) @@ -241,7 +241,7 @@ class SearchTests: BaseTestCase { mozWaitForValueContains(app.textFields["url"], value: "google") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306943 + // https://mozilla.testrail.io/index.php?/cases/view/2306943 func testSearchIconOnAboutHome() throws { if iPad() { throw XCTSkip("iPad does not have search icon") @@ -283,7 +283,7 @@ class SearchTests: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306989 + // https://mozilla.testrail.io/index.php?/cases/view/2306989 // Smoketest func testOpenTabsInSearchSuggestions() throws { if #unavailable(iOS 16) { @@ -304,7 +304,7 @@ class SearchTests: BaseTestCase { validateSearchSuggestionText(typeText: "localhost") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306886 + // https://mozilla.testrail.io/index.php?/cases/view/2306886 // SmokeTest func testBottomVIewURLBar() throws { if iPad() { @@ -357,7 +357,7 @@ class SearchTests: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306942 + // https://mozilla.testrail.io/index.php?/cases/view/2306942 func testSearchSuggestions() { // Tap on URL Bar and type "g" navigator.nowAt(NewTabScreen) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/SettingsTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/SettingsTests.swift index b66b1466a454..831d4709496b 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/SettingsTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/SettingsTests.swift @@ -15,7 +15,7 @@ class SettingsTests: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2334757 + // https://mozilla.testrail.io/index.php?/cases/view/2334757 func testHelpOpensSUMOInTab() { navigator.nowAt(NewTabScreen) navigator.goto(SettingsScreen) @@ -36,7 +36,7 @@ class SettingsTests: BaseTestCase { XCTAssertEqual("2", numTabs as? String, "Sume should be open in a different tab") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2334760 + // https://mozilla.testrail.io/index.php?/cases/view/2334760 func testOpenSiriOption() { waitForTabsButton() navigator.nowAt(NewTabScreen) @@ -44,7 +44,7 @@ class SettingsTests: BaseTestCase { mozWaitForElementToExist(app.cells["SiriSettings"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2334756 + // https://mozilla.testrail.io/index.php?/cases/view/2334756 func testCopiedLinks() { navigator.nowAt(NewTabScreen) navigator.goto(SettingsScreen) @@ -76,7 +76,7 @@ class SettingsTests: BaseTestCase { XCTAssertEqual(value3 as? String, "1") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307041 + // https://mozilla.testrail.io/index.php?/cases/view/2307041 func testOpenMailAppSettings() { waitForTabsButton() navigator.nowAt(NewTabScreen) @@ -107,7 +107,7 @@ class SettingsTests: BaseTestCase { navigator.goto(SettingsScreen) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307058 + // https://mozilla.testrail.io/index.php?/cases/view/2307058 // Functionality is tested by UITests/NoImageModeTests, here only the UI is updated properly // SmokeTest func testImageOnOff() { @@ -133,7 +133,7 @@ class SettingsTests: BaseTestCase { checkShowImages(showImages: true) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306808 + // https://mozilla.testrail.io/index.php?/cases/view/2306808 // Smoketest func testSettingsOptionSubtitles() { mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton]) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/SyncFAUITests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/SyncFAUITests.swift index 6466439ee864..aa9aab121245 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/SyncFAUITests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/SyncFAUITests.swift @@ -16,7 +16,7 @@ var uid: String! var code: String! class SyncUITests: BaseTestCase { - // https://testrail.stage.mozaws.net/index.php?/cases/view/2448597 + // https://mozilla.testrail.io/index.php?/cases/view/2448597 func testSyncUIFromBrowserTabMenu() { // Check menu available from HomeScreenPanel waitForTabsButton() @@ -47,7 +47,7 @@ class SyncUITests: BaseTestCase { mozWaitForElementToExist(app.webViews.buttons[AccessibilityIdentifiers.Settings.FirefoxAccount.continueButton]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2448874 + // https://mozilla.testrail.io/index.php?/cases/view/2448874 func testTypeOnGivenFields() { waitForTabsButton() navigator.nowAt(NewTabScreen) @@ -83,7 +83,7 @@ class SyncUITests: BaseTestCase { mozWaitForElementToNotExist(app.webViews.staticTexts["At least 8 characters"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2449603 + // https://mozilla.testrail.io/index.php?/cases/view/2449603 func testCreateAnAccountLink() { navigator.nowAt(NewTabScreen) navigator.goto(FxASigninScreen) @@ -98,7 +98,7 @@ class SyncUITests: BaseTestCase { mozWaitForElementToExist(app.webViews.buttons["Create account"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2449604 + // https://mozilla.testrail.io/index.php?/cases/view/2449604 func testShowPassword() { // The aim of this test is to check if the option to show password is shown when user starts typing // and disappears when no password is typed @@ -124,7 +124,7 @@ class SyncUITests: BaseTestCase { mozWaitForElementToNotExist(app.webViews.staticTexts[passMessage]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2449605 + // https://mozilla.testrail.io/index.php?/cases/view/2449605 func testQRPairing() { waitForTabsButton() navigator.nowAt(NewTabScreen) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/TabCounterTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/TabCounterTests.swift index d5f878208e46..5655667d89cf 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/TabCounterTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/TabCounterTests.swift @@ -6,7 +6,7 @@ import Common import XCTest class TabCounterTests: BaseTestCase { - // https://testrail.stage.mozaws.net/index.php?/cases/view/2359077 + // https://mozilla.testrail.io/index.php?/cases/view/2359077 func testTabIncrement() throws { navigator.nowAt(NewTabScreen) waitForTabsButton() @@ -35,7 +35,7 @@ class TabCounterTests: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2359078 + // https://mozilla.testrail.io/index.php?/cases/view/2359078 func testTabDecrement() throws { navigator.nowAt(NewTabScreen) waitForTabsButton() diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/ThirdPartySearchTest.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/ThirdPartySearchTest.swift index a94476c479ed..872b8b3a6743 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/ThirdPartySearchTest.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/ThirdPartySearchTest.swift @@ -11,7 +11,7 @@ class ThirdPartySearchTest: BaseTestCase { app.buttons["Done"].tap() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2443998 + // https://mozilla.testrail.io/index.php?/cases/view/2443998 func testCustomSearchEngines() { addCustomSearchEngine() @@ -36,7 +36,7 @@ class ThirdPartySearchTest: BaseTestCase { XCTAssert(url.hasPrefix("https://developer.mozilla.org/en-US"), "The URL should indicate that the search was performed on MDN and not the default") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2444328 + // https://mozilla.testrail.io/index.php?/cases/view/2444328 func testCustomSearchEngineAsDefault() { addCustomSearchEngine() @@ -61,7 +61,7 @@ class ThirdPartySearchTest: BaseTestCase { XCTAssert(url.hasPrefix("https://developer.mozilla.org/en-US/search"), "The URL should indicate that the search was performed on MDN and not the default") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306941 + // https://mozilla.testrail.io/index.php?/cases/view/2306941 func testCustomSearchEngineDeletion() { addCustomSearchEngine() mozWaitForElementToExist(app.navigationBars["Search"].buttons["Settings"]) @@ -120,7 +120,7 @@ class ThirdPartySearchTest: BaseTestCase { app.navigationBars["Settings"].buttons[AccessibilityIdentifiers.Settings.navigationBarItem].tap() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2444333 + // https://mozilla.testrail.io/index.php?/cases/view/2444333 func testCustomEngineFromIncorrectTemplate() { waitForTabsButton() navigator.nowAt(NewTabScreen) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/ToolbarMenuTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/ToolbarMenuTests.swift index d4feb9480831..2a83df7e52ec 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/ToolbarMenuTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/ToolbarMenuTests.swift @@ -11,7 +11,7 @@ class ToolbarMenuTests: BaseTestCase { super.tearDown() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306840 + // https://mozilla.testrail.io/index.php?/cases/view/2306840 func testToolbarMenu() { navigator.nowAt(NewTabScreen) let hamburgerMenu = app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton] diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/ToolbarTest.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/ToolbarTest.swift index c127c4fadaec..e9cd45d8f2bd 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/ToolbarTest.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/ToolbarTest.swift @@ -23,7 +23,7 @@ class ToolbarTests: BaseTestCase { super.tearDown() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2344428 + // https://mozilla.testrail.io/index.php?/cases/view/2344428 /** * Tests landscape page navigation enablement with the URL bar with tab switching. */ @@ -74,7 +74,7 @@ class ToolbarTests: BaseTestCase { XCTAssertTrue(app.buttons[AccessibilityIdentifiers.Toolbar.forwardButton].isEnabled) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2344430 + // https://mozilla.testrail.io/index.php?/cases/view/2344430 func testClearURLTextUsingBackspace() { navigator.openURL(website1["url"]!) waitUntilPageLoad() @@ -94,7 +94,7 @@ class ToolbarTests: BaseTestCase { // Check that after scrolling on a page, the URL bar is hidden. Tapping one on the status bar will reveal // the URL bar, tapping again on the status will scroll to the top // Skipping for iPad for now, not sure how to implement it there - // https://testrail.stage.mozaws.net/index.php?/cases/view/2344431 + // https://mozilla.testrail.io/index.php?/cases/view/2344431 func testRevealToolbarWhenTappingOnStatusbar() { if !iPad() { // Workaround when testing on iPhone. If the orientation is in landscape on iPhone the tests will fail. @@ -126,7 +126,7 @@ class ToolbarTests: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306870 + // https://mozilla.testrail.io/index.php?/cases/view/2306870 func testOpenNewTabButtonOnToolbar() throws { if iPad() { throw XCTSkip("iPhone only test") diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/TopTabsTest.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/TopTabsTest.swift index cfb23c6ec195..8c2d607ed126 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/TopTabsTest.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/TopTabsTest.swift @@ -18,7 +18,7 @@ let urlValueLongExample = "localhost:\(serverPort)/test-fixture/test-example.htm let toastUrl = ["url": "twitter.com", "link": "About", "urlLabel": "about"] class TopTabsTest: BaseTestCase { - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307042 + // https://mozilla.testrail.io/index.php?/cases/view/2307042 // Smoketest func testAddTabFromTabTray() throws { XCTExpectFailure("The app was not launched", strict: false) { @@ -44,7 +44,7 @@ class TopTabsTest: BaseTestCase { mozWaitForElementToExist(app.cells.staticTexts[urlLabel]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2354300 + // https://mozilla.testrail.io/index.php?/cases/view/2354300 func testAddTabFromContext() { navigator.nowAt(NewTabScreen) navigator.openURL(urlExample) @@ -63,7 +63,7 @@ class TopTabsTest: BaseTestCase { mozWaitForElementToExist(app.cells.staticTexts["Example Domain"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2354447 + // https://mozilla.testrail.io/index.php?/cases/view/2354447 func testSwitchBetweenTabs() { // Open two urls from tab tray and switch between them navigator.openURL(path(forTestPage: "test-mozilla-org.html")) @@ -88,7 +88,7 @@ class TopTabsTest: BaseTestCase { XCTAssertEqual(value, urlValueLongExample) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2354449 + // https://mozilla.testrail.io/index.php?/cases/view/2354449 func testCloseOneTab() { navigator.openURL(path(forTestPage: "test-mozilla-org.html")) waitUntilPageLoad() @@ -116,7 +116,7 @@ class TopTabsTest: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306865 + // https://mozilla.testrail.io/index.php?/cases/view/2306865 // Smoketest func testCloseAllTabsUndo() { navigator.nowAt(NewTabScreen) @@ -166,7 +166,7 @@ class TopTabsTest: BaseTestCase { mozWaitForElementToExist(app.cells.staticTexts[urlLabel]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2354473 + // https://mozilla.testrail.io/index.php?/cases/view/2354473 // Smoketest func testCloseAllTabsPrivateModeUndo() { navigator.goto(URLBarOpen) @@ -200,7 +200,7 @@ class TopTabsTest: BaseTestCase { mozWaitForElementToExist(app.staticTexts["Private Browsing"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2354579 + // https://mozilla.testrail.io/index.php?/cases/view/2354579 func testCloseAllTabs() { // A different tab than home is open to do the proper checks navigator.openURL(path(forTestPage: "test-mozilla-org.html")) @@ -225,7 +225,7 @@ class TopTabsTest: BaseTestCase { mozWaitForElementToExist(app.cells.staticTexts["Homepage"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2354580 + // https://mozilla.testrail.io/index.php?/cases/view/2354580 func testCloseAllTabsPrivateMode() { // A different tab than home is open to do the proper checks navigator.toggleOn(userState.isPrivate, withAction: Action.TogglePrivateMode) @@ -245,7 +245,7 @@ class TopTabsTest: BaseTestCase { mozWaitForElementToExist(app.staticTexts["Private Browsing"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306884 + // https://mozilla.testrail.io/index.php?/cases/view/2306884 // Smoketest func testOpenNewTabLandscape() { XCUIDevice.shared.orientation = .landscapeLeft @@ -270,7 +270,7 @@ class TopTabsTest: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306838 + // https://mozilla.testrail.io/index.php?/cases/view/2306838 // Smoketest func testLongTapTabCounter() { if !iPad() { @@ -321,7 +321,7 @@ class TopTabsTest: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307047 + // https://mozilla.testrail.io/index.php?/cases/view/2307047 func testOpenTabsViewCurrentTabThumbnail() { // Open ten or more tabs navigator.nowAt(NewTabScreen) @@ -374,7 +374,7 @@ class TopTabsTest: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306869 + // https://mozilla.testrail.io/index.php?/cases/view/2306869 func testTabTrayContextMenuCloseTab() { // Have multiple tabs opened in the tab tray navigator.nowAt(NewTabScreen) @@ -385,7 +385,7 @@ class TopTabsTest: BaseTestCase { addTabsAndUndoCloseTabAction(nrOfTabs: 4) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306868 + // https://mozilla.testrail.io/index.php?/cases/view/2306868 func testTabTrayCloseMultipleTabs() { navigator.nowAt(NewTabScreen) validateToastWhenClosingMultipleTabs() @@ -493,7 +493,7 @@ fileprivate extension BaseTestCase { } class TopTabsTestIphone: IphoneOnlyTestCase { - // https://testrail.stage.mozaws.net/index.php?/cases/view/2355535 + // https://mozilla.testrail.io/index.php?/cases/view/2355535 // Smoketest func testCloseTabFromLongPressTabsButton() { if skipPlatform { return } @@ -524,7 +524,7 @@ class TopTabsTestIphone: IphoneOnlyTestCase { } // This test only runs for iPhone see bug 1409750 - // https://testrail.stage.mozaws.net/index.php?/cases/view/2355536 + // https://mozilla.testrail.io/index.php?/cases/view/2355536 // Smoketest func testAddTabByLongPressTabsButton() { if skipPlatform { return } @@ -537,7 +537,7 @@ class TopTabsTestIphone: IphoneOnlyTestCase { } // This test only runs for iPhone see bug 1409750 - // https://testrail.stage.mozaws.net/index.php?/cases/view/2355537 + // https://mozilla.testrail.io/index.php?/cases/view/2355537 // Smoketest func testAddPrivateTabByLongPressTabsButton() { if skipPlatform { return } @@ -553,7 +553,7 @@ class TopTabsTestIphone: IphoneOnlyTestCase { } // This test is disabled for iPad because the toast menu is not shown there - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306861 + // https://mozilla.testrail.io/index.php?/cases/view/2306861 // Smoketest func testSwitchBetweenTabsToastButton() { if skipPlatform { return } @@ -577,7 +577,7 @@ class TopTabsTestIphone: IphoneOnlyTestCase { } // This test is disabled for iPad because the toast menu is not shown there - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306860 + // https://mozilla.testrail.io/index.php?/cases/view/2306860 // Smoketest func testSwitchBetweenTabsNoPrivatePrivateToastButton() { if skipPlatform { return } @@ -603,7 +603,7 @@ class TopTabsTestIphone: IphoneOnlyTestCase { // Tests to check if Tab Counter is updating correctly after opening three tabs by tapping on '+' button // and closing the tabs by tapping 'x' button class TopTabsTestIpad: IpadOnlyTestCase { - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307023 + // https://mozilla.testrail.io/index.php?/cases/view/2307023 func testUpdateTabCounter() { if skipPlatform { return } // Open three tabs by tapping on '+' button diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/TrackingProtectionTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/TrackingProtectionTests.swift index 3bb3ec0c91af..f7103eca67b5 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/TrackingProtectionTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/TrackingProtectionTests.swift @@ -14,7 +14,7 @@ let websiteWithBlockedElements = "twitter.com" let differentWebsite = path(forTestPage: "test-example.html") class TrackingProtectionTests: BaseTestCase { - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307059 + // https://mozilla.testrail.io/index.php?/cases/view/2307059 // Smoketest func testStandardProtectionLevel() { navigator.goto(URLBarOpen) @@ -81,7 +81,7 @@ class TrackingProtectionTests: BaseTestCase { app.buttons["Done"].tap() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2319381 + // https://mozilla.testrail.io/index.php?/cases/view/2319381 func testLockIconMenu() { navigator.openURL(differentWebsite) waitUntilPageLoad() @@ -122,7 +122,7 @@ class TrackingProtectionTests: BaseTestCase { XCTAssertTrue(app.switches.element.exists) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2318742 + // https://mozilla.testrail.io/index.php?/cases/view/2318742 func testProtectionLevelMoreInfoMenu() { navigator.nowAt(NewTabScreen) navigator.goto(TrackingProtectionSettings) @@ -146,7 +146,7 @@ class TrackingProtectionTests: BaseTestCase { app.buttons["Tracking Protection"].tap() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2307061 + // https://mozilla.testrail.io/index.php?/cases/view/2307061 func testLockIconSecureConnection() { navigator.openURL("https://www.Mozilla.org") waitUntilPageLoad() diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/URLValidationTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/URLValidationTests.swift index c044a9041ed0..a4638c62153b 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/URLValidationTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/URLValidationTests.swift @@ -19,7 +19,7 @@ class URLValidationTests: BaseTestCase { navigator.goto(NewTabScreen) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2460854 + // https://mozilla.testrail.io/index.php?/cases/view/2460854 // Smoketest func testDifferentURLTypes() { for i in urlTypes { diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/UrlBarTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/UrlBarTests.swift index dc85eb89e9eb..3898634a4c65 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/UrlBarTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/UrlBarTests.swift @@ -28,7 +28,7 @@ let iPhoneSearchIcon = XCUIApplication() .children(matching: .image).element class UrlBarTests: BaseTestCase { - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306888 + // https://mozilla.testrail.io/index.php?/cases/view/2306888 func testNewTabUrlBar() { // Visit any website and select the URL bar navigator.openURL("http://localhost:\(serverPort)/test-fixture/find-in-page-test.html") @@ -48,7 +48,7 @@ class UrlBarTests: BaseTestCase { XCTAssertEqual(app.textFields["url"].value as! String, "Search or enter address") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306887 + // https://mozilla.testrail.io/index.php?/cases/view/2306887 func testSearchEngineLogo() { tapUrlBarValidateKeyboardAndIcon() // Type a search term and hit "go" diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/ZoomingTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/ZoomingTests.swift index c01b6b337826..40de3083ab14 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/ZoomingTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/ZoomingTests.swift @@ -25,7 +25,7 @@ class ZoomingTests: BaseTestCase { super.tearDown() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306947 + // https://mozilla.testrail.io/index.php?/cases/view/2306947 // Smoketest func testZoomingActions() { // Regular browsing @@ -42,7 +42,7 @@ class ZoomingTests: BaseTestCase { validateZoomActions() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306949 + // https://mozilla.testrail.io/index.php?/cases/view/2306949 func testZoomForceCloseFirefox() { openWebsiteAndReachZoomSetting(website: 0) zoomLevel = app.staticTexts[AccessibilityIdentifiers.ZoomPageBar.zoomPageZoomLevelLabel] @@ -59,7 +59,7 @@ class ZoomingTests: BaseTestCase { XCTAssertEqual(zoomLevel.label, "Current Zoom Level: 100%") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2306948 + // https://mozilla.testrail.io/index.php?/cases/view/2306948 func testSwitchingZoomedTabs() { validateZoomLevelOnSwitchingTabs() // Repeat all steps in private browsing @@ -72,7 +72,7 @@ class ZoomingTests: BaseTestCase { validateZoomLevelOnSwitchingTabs() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2609150 + // https://mozilla.testrail.io/index.php?/cases/view/2609150 func testSwitchingZoomedTabsLandscape() { XCUIDevice.shared.orientation = UIDeviceOrientation.landscapeLeft validateZoomLevelOnSwitchingTabs() From 2b730b10fd62c82e4614982b7787f7a8387d6a64 Mon Sep 17 00:00:00 2001 From: dragosb01 <134391433+dragosb01@users.noreply.github.com> Date: Tue, 6 Aug 2024 12:51:52 +0300 Subject: [PATCH 048/128] Update MTE-3228 - TestRail URLs to mozilla.testrail.io for focus (#21467) --- .../XCUITest/AsianLocaleTest.swift | 2 +- .../XCUITest/BrowsingTest.swift | 10 +++++----- .../XCUITest/CopyPasteTest.swift | 6 +++--- .../XCUITest/DragAndDropTest.swift | 2 +- .../XCUITest/OnboardingTest.swift | 2 +- .../XCUITest/PageActionMenuTest.swift | 4 ++-- .../XCUITest/PageShortcutsTest.swift | 6 +++--- .../XCUITest/SearchProviderTest.swift | 12 ++++++------ .../XCUITest/SearchSuggestionsTest.swift | 8 ++++---- .../focus-ios-tests/XCUITest/SettingTest.swift | 18 +++++++++--------- .../XCUITest/TrackingProtectionTest.swift | 8 ++++---- .../XCUITest/URLValidationTest.swift | 2 +- 12 files changed, 40 insertions(+), 40 deletions(-) diff --git a/focus-ios/focus-ios-tests/XCUITest/AsianLocaleTest.swift b/focus-ios/focus-ios-tests/XCUITest/AsianLocaleTest.swift index fdce73b0ef69..296a819f1fc2 100644 --- a/focus-ios/focus-ios-tests/XCUITest/AsianLocaleTest.swift +++ b/focus-ios/focus-ios-tests/XCUITest/AsianLocaleTest.swift @@ -20,7 +20,7 @@ class AsianLocaleTest: BaseTestCase { checkForHomeScreen() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2599440 + // https://mozilla.testrail.io/index.php?/cases/view/2599440 func testSearchInLocale() { // Test Setup dismissURLBarFocused() diff --git a/focus-ios/focus-ios-tests/XCUITest/BrowsingTest.swift b/focus-ios/focus-ios-tests/XCUITest/BrowsingTest.swift index 4bf5e6171ea4..376054cc6f99 100644 --- a/focus-ios/focus-ios-tests/XCUITest/BrowsingTest.swift +++ b/focus-ios/focus-ios-tests/XCUITest/BrowsingTest.swift @@ -7,7 +7,7 @@ import XCTest class BrowsingTest: BaseTestCase { // Smoke test - // https://testrail.stage.mozaws.net/index.php?/cases/view/1569888 + // https://mozilla.testrail.io/index.php?/cases/view/1569888 func testLaunchExternalApp() { // Load URL loadWebPage("https://www.example.com") @@ -18,7 +18,7 @@ class BrowsingTest: BaseTestCase { app.buttons["HomeView.settingsButton"].tap() // Tap Share button - // https://testrail.stage.mozaws.net/index.php?/cases/view/1569888 + // https://mozilla.testrail.io/index.php?/cases/view/1569888 let shareButton: XCUIElement if #available(iOS 14, *) { shareButton = app.cells.buttons["Share Page With…"] @@ -43,7 +43,7 @@ class BrowsingTest: BaseTestCase { } // Smoketest - // https://testrail.stage.mozaws.net/index.php?/cases/view/1569889 + // https://mozilla.testrail.io/index.php?/cases/view/1569889 func testNavigationToolbar() { loadWebPage("example.com") waitForWebPageLoad() @@ -78,7 +78,7 @@ class BrowsingTest: BaseTestCase { } // Smoketest - // https://testrail.stage.mozaws.net/index.php?/cases/view/2587661 + // https://mozilla.testrail.io/index.php?/cases/view/2587661 func testActivityMenuRequestDesktopItem() { // Wait for existence rather than hittable because the textfield is technically disabled loadWebPage("facebook.com") @@ -113,7 +113,7 @@ class BrowsingTest: BaseTestCase { } // Smoketest - // https://testrail.stage.mozaws.net/index.php?/cases/view/2587662 + // https://mozilla.testrail.io/index.php?/cases/view/2587662 func testCheckCollapsedURL() { // Test do not apply to iPad if !iPad() { diff --git a/focus-ios/focus-ios-tests/XCUITest/CopyPasteTest.swift b/focus-ios/focus-ios-tests/XCUITest/CopyPasteTest.swift index 774f72821c86..c81a5379eca5 100644 --- a/focus-ios/focus-ios-tests/XCUITest/CopyPasteTest.swift +++ b/focus-ios/focus-ios-tests/XCUITest/CopyPasteTest.swift @@ -5,7 +5,7 @@ import XCTest class CopyPasteTest: BaseTestCase { - // https://testrail.stage.mozaws.net/index.php?/cases/view/395745 + // https://mozilla.testrail.io/index.php?/cases/view/395745 func testCopyMenuItem() { let urlBarTextField = app.textFields["URLBar.urlText"] loadWebPage("https://www.example.com") @@ -34,7 +34,7 @@ class CopyPasteTest: BaseTestCase { } // Smoketest - // https://testrail.stage.mozaws.net/index.php?/cases/view/2609148 + // https://mozilla.testrail.io/index.php?/cases/view/2609148 // Test the clipboard contents are displayed/updated properly func testClipboard() throws { let app = XCUIApplication() @@ -85,7 +85,7 @@ class CopyPasteTest: BaseTestCase { } // Smoketest - // https://testrail.stage.mozaws.net/index.php?/cases/view/2609149 + // https://mozilla.testrail.io/index.php?/cases/view/2609149 // Test Paste & Go feature func testPastenGo() { // Inject a string into clipboard diff --git a/focus-ios/focus-ios-tests/XCUITest/DragAndDropTest.swift b/focus-ios/focus-ios-tests/XCUITest/DragAndDropTest.swift index 7d84b81cc9e0..515380e254cb 100644 --- a/focus-ios/focus-ios-tests/XCUITest/DragAndDropTest.swift +++ b/focus-ios/focus-ios-tests/XCUITest/DragAndDropTest.swift @@ -7,7 +7,7 @@ import XCTest class DragAndDropTest: BaseTestCase { let websiteWithSearchField = ["url": "https://developer.mozilla.org/en-US/", "urlSearchField": "Search MDN"] - // https://testrail.stage.mozaws.net/index.php?/cases/view/2609718 + // https://mozilla.testrail.io/index.php?/cases/view/2609718 func testDragElement() { let urlBarTextField = app.textFields["URLBar.urlText"] loadWebPage(websiteWithSearchField["url"]!) diff --git a/focus-ios/focus-ios-tests/XCUITest/OnboardingTest.swift b/focus-ios/focus-ios-tests/XCUITest/OnboardingTest.swift index ef1079a65099..c8d50e8e2c17 100644 --- a/focus-ios/focus-ios-tests/XCUITest/OnboardingTest.swift +++ b/focus-ios/focus-ios-tests/XCUITest/OnboardingTest.swift @@ -18,7 +18,7 @@ class OnboardingTest: BaseTestCase { } // Smoketest - // https://testrail.stage.mozaws.net/index.php?/cases/view/394959 + // https://mozilla.testrail.io/index.php?/cases/view/394959 func testPressingDots() throws { let pageIndicatorButton = app.pageIndicators.firstMatch XCTAssertEqual(pageIndicatorButton.value as? String, "page 1 of 2") diff --git a/focus-ios/focus-ios-tests/XCUITest/PageActionMenuTest.swift b/focus-ios/focus-ios-tests/XCUITest/PageActionMenuTest.swift index 58871ddb3c1d..cd613b601872 100644 --- a/focus-ios/focus-ios-tests/XCUITest/PageActionMenuTest.swift +++ b/focus-ios/focus-ios-tests/XCUITest/PageActionMenuTest.swift @@ -5,7 +5,7 @@ import XCTest class PageActionMenuTest: BaseTestCase { - // https://testrail.stage.mozaws.net/index.php?/cases/view/2587660 + // https://mozilla.testrail.io/index.php?/cases/view/2587660 func testFindInPageURLBarElement() { // Navigate to website loadWebPage("https://www.example.com") @@ -33,7 +33,7 @@ class PageActionMenuTest: BaseTestCase { } // Smoketest - // https://testrail.stage.mozaws.net/index.php?/cases/view/395022 + // https://mozilla.testrail.io/index.php?/cases/view/395022 func testActivityMenuFindInPageAction() { // Navigate to website loadWebPage("https://www.example.com") diff --git a/focus-ios/focus-ios-tests/XCUITest/PageShortcutsTest.swift b/focus-ios/focus-ios-tests/XCUITest/PageShortcutsTest.swift index 7652ee97cd4e..dadeebf8fc27 100644 --- a/focus-ios/focus-ios-tests/XCUITest/PageShortcutsTest.swift +++ b/focus-ios/focus-ios-tests/XCUITest/PageShortcutsTest.swift @@ -11,7 +11,7 @@ class PageShortcutsTest: BaseTestCase { super.tearDown() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/1857439 + // https://mozilla.testrail.io/index.php?/cases/view/1857439 func testAddRemoveShortcut() { addShortcut(website: "mozilla.org") @@ -29,7 +29,7 @@ class PageShortcutsTest: BaseTestCase { } // Smoketest - // https://testrail.stage.mozaws.net/index.php?/cases/view/1857438 + // https://mozilla.testrail.io/index.php?/cases/view/1857438 func testAddRenameShortcut() { addShortcut(website: "mozilla.org") @@ -51,7 +51,7 @@ class PageShortcutsTest: BaseTestCase { } // Smoketest - // https://testrail.stage.mozaws.net/index.php?/cases/view/1857440 + // https://mozilla.testrail.io/index.php?/cases/view/1857440 func testShortcutShownWhileTypingURLBar() { addShortcut(website: "example.com") app.urlTextField.tap() diff --git a/focus-ios/focus-ios-tests/XCUITest/SearchProviderTest.swift b/focus-ios/focus-ios-tests/XCUITest/SearchProviderTest.swift index 19cc423f6c2a..20be7b5b40d5 100644 --- a/focus-ios/focus-ios-tests/XCUITest/SearchProviderTest.swift +++ b/focus-ios/focus-ios-tests/XCUITest/SearchProviderTest.swift @@ -5,22 +5,22 @@ import XCTest class SearchProviderTest: BaseTestCase { - // https://testrail.stage.mozaws.net/index.php?/cases/view/1707743 + // https://mozilla.testrail.io/index.php?/cases/view/1707743 func testGoogleSearchProvider() { searchProviderTestHelper(provider: "Google") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2512720 + // https://mozilla.testrail.io/index.php?/cases/view/2512720 func testDuckDuckGoSearchProvider() { searchProviderTestHelper(provider: "DuckDuckGo") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2512721 + // https://mozilla.testrail.io/index.php?/cases/view/2512721 func testWikipediaSearchProvider() { searchProviderTestHelper(provider: "Wikipedia") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2524588 + // https://mozilla.testrail.io/index.php?/cases/view/2524588 func testSearchQuery() { searchQuery("test", provider: "Google") dismissKeyboardFocusMenuSettings() @@ -65,7 +65,7 @@ class SearchProviderTest: BaseTestCase { } } - // https://testrail.stage.mozaws.net/index.php?/cases/view/1707744 + // https://mozilla.testrail.io/index.php?/cases/view/1707744 func testAddRemoveCustomSearchProvider() { dismissURLBarFocused() waitForExistence(app.buttons["HomeView.settingsButton"]) @@ -110,7 +110,7 @@ class SearchProviderTest: BaseTestCase { app.navigationBars.buttons["edit"].tap() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/1707745 + // https://mozilla.testrail.io/index.php?/cases/view/1707745 func testPreventionOfRemovingDefaultSearchProvider() { dismissURLBarFocused() waitForExistence(app.buttons["HomeView.settingsButton"]) diff --git a/focus-ios/focus-ios-tests/XCUITest/SearchSuggestionsTest.swift b/focus-ios/focus-ios-tests/XCUITest/SearchSuggestionsTest.swift index e1ea08034b64..e870ef9f78a7 100644 --- a/focus-ios/focus-ios-tests/XCUITest/SearchSuggestionsTest.swift +++ b/focus-ios/focus-ios-tests/XCUITest/SearchSuggestionsTest.swift @@ -46,7 +46,7 @@ class SearchSuggestionsPromptTest: BaseTestCase { checkToggle(isOn: false) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/1707746 + // https://mozilla.testrail.io/index.php?/cases/view/1707746 func testEnableThroughPrompt() { // Check search suggestions toggle is initially OFF checkToggleStartsOff() @@ -80,7 +80,7 @@ class SearchSuggestionsPromptTest: BaseTestCase { checkToggle(isOn: true) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2524590 + // https://mozilla.testrail.io/index.php?/cases/view/2524590 func testDisableThroughPrompt() { // Check search suggestions toggle is initially OFF checkToggleStartsOff() @@ -117,7 +117,7 @@ class SearchSuggestionsPromptTest: BaseTestCase { checkToggle(isOn: false) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2524591 + // https://mozilla.testrail.io/index.php?/cases/view/2524591 func testEnableThroughToggle() { // Check search suggestions toggle is initially OFF checkToggleStartsOff() @@ -140,7 +140,7 @@ class SearchSuggestionsPromptTest: BaseTestCase { checkSuggestions() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2524592 + // https://mozilla.testrail.io/index.php?/cases/view/2524592 func testEnableThenDisable() { // Check search suggestions toggle is initially OFF checkToggleStartsOff() diff --git a/focus-ios/focus-ios-tests/XCUITest/SettingTest.swift b/focus-ios/focus-ios-tests/XCUITest/SettingTest.swift index c17fba2743d4..c53b36a453a6 100644 --- a/focus-ios/focus-ios-tests/XCUITest/SettingTest.swift +++ b/focus-ios/focus-ios-tests/XCUITest/SettingTest.swift @@ -9,7 +9,7 @@ class SettingTest: BaseTestCase { // Smoketest // Check for the basic appearance of the Settings Menu - // https://testrail.stage.mozaws.net/index.php?/cases/view/394976 + // https://mozilla.testrail.io/index.php?/cases/view/394976 func testCheckSetting() { dismissURLBarFocused() @@ -120,7 +120,7 @@ class SettingTest: BaseTestCase { waitForExistence(app.navigationBars["Settings"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2574974 + // https://mozilla.testrail.io/index.php?/cases/view/2574974 func testOpenInSafari() { let safariapp = XCUIApplication(privateWithPath: nil, bundleID: "com.apple.mobilesafari")! loadWebPage("https://www.google.com", waitForLoadToFinish: true) @@ -150,7 +150,7 @@ class SettingTest: BaseTestCase { waitForExistence(app.staticTexts["Browsing history cleared"]) } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2574975 + // https://mozilla.testrail.io/index.php?/cases/view/2574975 func testEnableDisableAutocomplete() { dismissURLBarFocused() @@ -179,7 +179,7 @@ class SettingTest: BaseTestCase { toggle.tap() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/2574976 + // https://mozilla.testrail.io/index.php?/cases/view/2574976 func testAddRemoveCustomDomain() { dismissURLBarFocused() // Navigate to Settings @@ -234,7 +234,7 @@ class SettingTest: BaseTestCase { } // Smoketest - // https://testrail.stage.mozaws.net/index.php?/cases/view/1569297 + // https://mozilla.testrail.io/index.php?/cases/view/1569297 func testSafariIntegration() { dismissURLBarFocused() @@ -303,7 +303,7 @@ class SettingTest: BaseTestCase { } // Smoketest - // https://testrail.stage.mozaws.net/index.php?/cases/view/2584834 + // https://mozilla.testrail.io/index.php?/cases/view/2584834 func testVisitWebsite() { dismissURLBarFocused() @@ -334,7 +334,7 @@ class SettingTest: BaseTestCase { checkForHomeScreen() } - // https://testrail.stage.mozaws.net/index.php?/cases/view/394967 + // https://mozilla.testrail.io/index.php?/cases/view/394967 func testDisableAutocomplete() { let urlTextField = app.urlTextField let searchSuggestionsOverlay = app.searchSuggestionsOverlay @@ -351,7 +351,7 @@ class SettingTest: BaseTestCase { XCTAssertEqual(urlTextField.value as? String, "mozilla") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/394967 + // https://mozilla.testrail.io/index.php?/cases/view/394967 func testReEnableAutoComplete() { let urlTextField = app.urlTextField let searchSuggestionsOverlay = app.searchSuggestionsOverlay @@ -369,7 +369,7 @@ class SettingTest: BaseTestCase { XCTAssertEqual(urlTextField.value as? String, "mozilla.org/") } - // https://testrail.stage.mozaws.net/index.php?/cases/view/394967 + // https://mozilla.testrail.io/index.php?/cases/view/394967 func testAutocompleteCustomDomain() { dismissURLBarFocused() app.buttons["HomeView.settingsButton"].tap() diff --git a/focus-ios/focus-ios-tests/XCUITest/TrackingProtectionTest.swift b/focus-ios/focus-ios-tests/XCUITest/TrackingProtectionTest.swift index 81ed8aa9dab0..74017b1df662 100644 --- a/focus-ios/focus-ios-tests/XCUITest/TrackingProtectionTest.swift +++ b/focus-ios/focus-ios-tests/XCUITest/TrackingProtectionTest.swift @@ -5,7 +5,7 @@ import XCTest class TrackingProtectionTest: BaseTestCase { - // https://testrail.stage.mozaws.net/index.php?/cases/view/2544056 + // https://mozilla.testrail.io/index.php?/cases/view/2544056 func testInactiveSettings() { // Go to in-app settings // Check the new options in TP Settings menu @@ -34,7 +34,7 @@ class TrackingProtectionTest: BaseTestCase { } // Smoketest - // https://testrail.stage.mozaws.net/index.php?/cases/view/394999 + // https://mozilla.testrail.io/index.php?/cases/view/394999 func testProtectionSidebar() { // Visit https://www.mozilla.org loadWebPage("mozilla.org") @@ -61,7 +61,7 @@ class TrackingProtectionTest: BaseTestCase { } // Smoke test - // https://testrail.stage.mozaws.net/index.php?/cases/view/1569890 + // https://mozilla.testrail.io/index.php?/cases/view/1569890 func testAdBlocking() { // Load URL loadWebPage("https://blockads.fivefilters.org/") @@ -73,7 +73,7 @@ class TrackingProtectionTest: BaseTestCase { } // Smoke test - // https://testrail.stage.mozaws.net/index.php?/cases/view/1569869 + // https://mozilla.testrail.io/index.php?/cases/view/1569869 func testShieldMenuSetting() { // Load URL loadWebPage("https://blockads.fivefilters.org/") diff --git a/focus-ios/focus-ios-tests/XCUITest/URLValidationTest.swift b/focus-ios/focus-ios-tests/XCUITest/URLValidationTest.swift index 909dc19c740b..8bd92dee7bcc 100644 --- a/focus-ios/focus-ios-tests/XCUITest/URLValidationTest.swift +++ b/focus-ios/focus-ios-tests/XCUITest/URLValidationTest.swift @@ -15,7 +15,7 @@ class URLValidationTest: BaseTestCase { "mozilla.org/en-US", "https://mozilla.org/", "https://mozilla.org/en", "https://mozilla.org/en-US"] let urlHttpTypes=["http://example.com", "http://example.com/"] - // https://testrail.stage.mozaws.net/index.php?/cases/view/2460275 + // https://mozilla.testrail.io/index.php?/cases/view/2460275 func testDifferentURLTypes() { for i in urlTypes { loadAndValidateURL(URL: i) From 31994351be81f13dd7a74406fbff7e95fe6f8823 Mon Sep 17 00:00:00 2001 From: Daniel Dervishi <58835213+DanielDervishi@users.noreply.github.com> Date: Tue, 6 Aug 2024 09:46:56 -0400 Subject: [PATCH 049/128] Bugfix FXIOS-9731 - BottomSheetViewController was not properly showing a dimmed background (#21381) * Injected WindowUUID into BottomSheetViewController * Addressed Comments --------- Co-authored-by: Daniel Dervishi --- .../BottomSheet/BottomSheetViewController.swift | 8 +++++--- .../BottomSheet/BottomSheetComponentViewModel.swift | 7 +++++-- .../Client/Coordinators/AddressAutofillCoordinator.swift | 6 ++++-- .../Coordinators/CredentialAutofillCoordinator.swift | 6 ++++-- .../Client/Frontend/Home/HomepageViewController.swift | 3 ++- .../Onboarding/Protocols/OnboardingCardDelegate.swift | 3 ++- 6 files changed, 22 insertions(+), 11 deletions(-) diff --git a/BrowserKit/Sources/ComponentLibrary/BottomSheet/BottomSheetViewController.swift b/BrowserKit/Sources/ComponentLibrary/BottomSheet/BottomSheetViewController.swift index 85fda3bc2af9..8b361322e922 100644 --- a/BrowserKit/Sources/ComponentLibrary/BottomSheet/BottomSheetViewController.swift +++ b/BrowserKit/Sources/ComponentLibrary/BottomSheet/BottomSheetViewController.swift @@ -60,11 +60,13 @@ public class BottomSheetViewController: UIViewController, private lazy var scrollContentView: UIView = .build { _ in } private var contentViewBottomConstraint: NSLayoutConstraint! private var viewTranslation = CGPoint(x: 0, y: 0) + private let windowUUID: WindowUUID // MARK: Init public init(viewModel: BottomSheetViewModel, childViewController: BottomSheetChild, usingDimmedBackground: Bool = false, + windowUUID: WindowUUID, notificationCenter: NotificationProtocol = NotificationCenter.default, themeManager: ThemeManager = AppContainer.shared.resolve()) { self.viewModel = viewModel @@ -72,6 +74,7 @@ public class BottomSheetViewController: UIViewController, self.notificationCenter = notificationCenter self.themeManager = themeManager self.useDimmedBackground = usingDimmedBackground + self.windowUUID = windowUUID super.init(nibName: nil, bundle: nil) @@ -136,8 +139,7 @@ public class BottomSheetViewController: UIViewController, // MARK: - Theme public func applyTheme() { - guard let uuid = (self.view as? ThemeUUIDIdentifiable)?.currentWindowUUID else { return } - contentView.backgroundColor = themeManager.getCurrentTheme(for: uuid).colors.layer1 + contentView.backgroundColor = themeManager.getCurrentTheme(for: windowUUID).colors.layer1 sheetView.layer.shadowOpacity = viewModel.shadowOpacity if useDimmedBackground { @@ -147,7 +149,7 @@ public class BottomSheetViewController: UIViewController, } public var currentWindowUUID: WindowUUID? { - return (self.view as? ThemeUUIDIdentifiable)?.currentWindowUUID + return windowUUID } // MARK: - UIGestureRecognizerDelegate diff --git a/SampleComponentLibraryApp/SampleComponentLibraryApp/BottomSheet/BottomSheetComponentViewModel.swift b/SampleComponentLibraryApp/SampleComponentLibraryApp/BottomSheet/BottomSheetComponentViewModel.swift index f13eb00c5b91..d391f1ef173b 100644 --- a/SampleComponentLibraryApp/SampleComponentLibraryApp/BottomSheet/BottomSheetComponentViewModel.swift +++ b/SampleComponentLibraryApp/SampleComponentLibraryApp/BottomSheet/BottomSheetComponentViewModel.swift @@ -12,13 +12,16 @@ struct BottomSheetComponentViewModel: ComponentViewModel { private var viewModel: BottomSheetViewModel init() { - viewModel = BottomSheetViewModel(closeButtonA11yLabel: "Close button", closeButtonA11yIdentifier: "a11yCloseButton") + viewModel = BottomSheetViewModel( + closeButtonA11yLabel: "Close button", + closeButtonA11yIdentifier: "a11yCloseButton") viewModel.shouldDismissForTapOutside = true viewController = BottomSheetViewController( viewModel: viewModel, childViewController: BottomSheetChildViewController(), - usingDimmedBackground: true + usingDimmedBackground: true, + windowUUID: defaultSampleComponentUUID ) } diff --git a/firefox-ios/Client/Coordinators/AddressAutofillCoordinator.swift b/firefox-ios/Client/Coordinators/AddressAutofillCoordinator.swift index e8b071b2f7ab..b40f7eb54b75 100644 --- a/firefox-ios/Client/Coordinators/AddressAutofillCoordinator.swift +++ b/firefox-ios/Client/Coordinators/AddressAutofillCoordinator.swift @@ -85,8 +85,10 @@ class AddressAutofillCoordinator: BaseCoordinator { object: .addressAutofillPromptDismissed ) } - let bottomSheetVC = BottomSheetViewController(viewModel: bottomSheetViewModel, - childViewController: hostingController) + let bottomSheetVC = BottomSheetViewController( + viewModel: bottomSheetViewModel, + childViewController: hostingController, + windowUUID: tabManager.windowUUID) TelemetryWrapper.recordEvent( category: .action, method: .tap, diff --git a/firefox-ios/Client/Coordinators/CredentialAutofillCoordinator.swift b/firefox-ios/Client/Coordinators/CredentialAutofillCoordinator.swift index 7fc48c194562..89a5751e3844 100644 --- a/firefox-ios/Client/Coordinators/CredentialAutofillCoordinator.swift +++ b/firefox-ios/Client/Coordinators/CredentialAutofillCoordinator.swift @@ -112,7 +112,8 @@ class CredentialAutofillCoordinator: BaseCoordinator { let bottomSheetVC = BottomSheetViewController( viewModel: bottomSheetViewModel, - childViewController: viewController + childViewController: viewController, + windowUUID: windowUUID ) router.present(bottomSheetVC) if state == .save { @@ -187,7 +188,8 @@ class CredentialAutofillCoordinator: BaseCoordinator { let bottomSheetVC = BottomSheetViewController( viewModel: bottomSheetViewModel, - childViewController: viewController + childViewController: viewController, + windowUUID: windowUUID ) router.present(bottomSheetVC) TelemetryWrapper.recordEvent( diff --git a/firefox-ios/Client/Frontend/Home/HomepageViewController.swift b/firefox-ios/Client/Frontend/Home/HomepageViewController.swift index a9cd29f7ba7c..e8d63540432e 100644 --- a/firefox-ios/Client/Frontend/Home/HomepageViewController.swift +++ b/firefox-ios/Client/Frontend/Home/HomepageViewController.swift @@ -417,7 +417,8 @@ class HomepageViewController: bottomSheetViewModel.shouldDismissForTapOutside = false let bottomSheetVC = BottomSheetViewController( viewModel: bottomSheetViewModel, - childViewController: viewController + childViewController: viewController, + windowUUID: windowUUID ) self.present(bottomSheetVC, animated: false, completion: nil) diff --git a/firefox-ios/Client/Frontend/Onboarding/Protocols/OnboardingCardDelegate.swift b/firefox-ios/Client/Frontend/Onboarding/Protocols/OnboardingCardDelegate.swift index 4cad527d0a24..97c0d19cb1d0 100644 --- a/firefox-ios/Client/Frontend/Onboarding/Protocols/OnboardingCardDelegate.swift +++ b/firefox-ios/Client/Frontend/Onboarding/Protocols/OnboardingCardDelegate.swift @@ -115,7 +115,8 @@ extension OnboardingCardDelegate where Self: OnboardingViewControllerProtocol, let bottomSheetVC = BottomSheetViewController( viewModel: bottomSheetViewModel, childViewController: instructionsVC, - usingDimmedBackground: true) + usingDimmedBackground: true, + windowUUID: windowUUID) instructionsVC.dismissDelegate = bottomSheetVC From dd4833281887fd8f47c7377e4ac24718c56794a4 Mon Sep 17 00:00:00 2001 From: dicarobinho <61138287+dicarobinho@users.noreply.github.com> Date: Tue, 6 Aug 2024 17:40:35 +0300 Subject: [PATCH 050/128] =?UTF-8?q?Add=20FXIOS-9195=20=E2=81=83=20Enhanced?= =?UTF-8?q?=20Tracking=20Protection=20screen=20status=20enabled=20design?= =?UTF-8?q?=20(#21458)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * FXIOS-9195 #20363 ⁃ Enhanced Tracking Protection screen status enabled design Extracted some code to a new getTrackerString method. --- firefox-ios/Client/Frontend/Strings.swift | 2 +- .../TrackingProtectionViewController.swift | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/firefox-ios/Client/Frontend/Strings.swift b/firefox-ios/Client/Frontend/Strings.swift index d4231419d3d7..1f9fc846d45d 100644 --- a/firefox-ios/Client/Frontend/Strings.swift +++ b/firefox-ios/Client/Frontend/Strings.swift @@ -4127,7 +4127,7 @@ extension String { comment: "Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked") public static let noTrackersLabel = MZLocalizedString( - key: "Menu.EnhancedTrackingProtection.Details.Trackers.v128", + key: "Menu.EnhancedTrackingProtection.Details.NoTrackers.v131", tableName: "EnhancedTrackingProtection", value: "No trackers found", comment: "Text to let users know that no trackers were found on the current website.") diff --git a/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionViewController.swift b/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionViewController.swift index 64b5c5f80f5e..4ac83d036002 100644 --- a/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionViewController.swift +++ b/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionViewController.swift @@ -737,11 +737,10 @@ class TrackingProtectionViewController: UIViewController, Themeable, Notifiable, siteDomainLabel.text = viewModel.websiteTitle siteDisplayTitleLabel.text = viewModel.displayTitle - let totalTrackerBlocked = String(viewModel.contentBlockerStats?.total ?? 0) - let trackersText = String(format: .Menu.EnhancedTrackingProtection.trackersBlockedLabel, totalTrackerBlocked) - trackersLabel.text = trackersText + trackersLabel.text = getTrackerString() shieldImage.image = UIImage(imageLiteralResourceName: StandardImageIdentifiers.Large.shield) .withRenderingMode(.alwaysTemplate) + connectionStatusImage.image = viewModel.getConnectionStatusImage(themeType: currentTheme().type) connectionStatusLabel.text = viewModel.connectionStatusString toggleSwitch.isOn = viewModel.isSiteETPEnabled viewModel.isProtectionEnabled = toggleSwitch.isOn @@ -753,6 +752,15 @@ class TrackingProtectionViewController: UIViewController, Themeable, Notifiable, foxStatusImage.image = viewModel.connectionDetailsImage } + private func getTrackerString() -> String { + if let trackersNumber = viewModel.contentBlockerStats?.total, trackersNumber > 0 { + return String(format: .Menu.EnhancedTrackingProtection.trackersBlockedLabel, + String(trackersNumber)) + } else { + return .Menu.EnhancedTrackingProtection.noTrackersLabel + } + } + private func setupViewActions() { closeButton.addTarget(self, action: #selector(closeButtonTapped), for: .touchUpInside) connectionButton.addTarget(self, action: #selector(connectionDetailsTapped), for: .touchUpInside) From 29bcb3ca241c2573acc1a452409d8c47491f788f Mon Sep 17 00:00:00 2001 From: Cyndi Chin Date: Tue, 6 Aug 2024 16:26:36 -0400 Subject: [PATCH 051/128] Add FXIOS-9782 [Microsurvey] Turn off feature flag (#21475) --- firefox-ios/nimbus-features/microsurveyFeature.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firefox-ios/nimbus-features/microsurveyFeature.yaml b/firefox-ios/nimbus-features/microsurveyFeature.yaml index 6f3741c587ec..42470c8873d5 100644 --- a/firefox-ios/nimbus-features/microsurveyFeature.yaml +++ b/firefox-ios/nimbus-features/microsurveyFeature.yaml @@ -13,7 +13,7 @@ features: defaults: - channel: beta value: - enabled: true + enabled: false - channel: developer value: enabled: true From f7cd5ff5cbd9e7100c2cb9ae7b7278f3958dfa3f Mon Sep 17 00:00:00 2001 From: Cyndi Chin Date: Tue, 6 Aug 2024 16:27:19 -0400 Subject: [PATCH 052/128] Bugfix FXIOS-9771 [Unit Tests] Missing MockDependency for TelemetryWrapperTests (#21462) --- .../Tests/ClientTests/TelemetryWrapperTests.swift | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/TelemetryWrapperTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/TelemetryWrapperTests.swift index 1f4da7206d2a..d60ebb7fa1e6 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/TelemetryWrapperTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/TelemetryWrapperTests.swift @@ -13,14 +13,16 @@ class TelemetryWrapperTests: XCTestCase { override func setUp() { super.setUp() + DependencyHelperMock().bootstrapDependencies() Glean.shared.resetGlean(clearStores: true) Experiments.events.clearEvents() } override func tearDown() { - super.tearDown() Glean.shared.resetGlean(clearStores: true) Experiments.events.clearEvents() + DependencyHelperMock().reset() + super.tearDown() } // MARK: - Bookmarks @@ -770,6 +772,7 @@ class TelemetryWrapperTests: XCTestCase { func test_backgroundWallpaperMetric_themedWallpaperIsSent() { let profile = MockProfile() + LegacyFeatureFlagsManager.shared.initializeDeveloperFeatures(with: profile) TelemetryWrapper.shared.setup(profile: profile) let themedWallpaper = Wallpaper(id: "amethyst", @@ -1446,7 +1449,7 @@ class TelemetryWrapperTests: XCTestCase { ) } - func test_syncLogin_NimbusIsCalled() throws { + func test_syncLogin_NimbusIsCalled() { XCTAssertFalse( try Experiments.createJexlHelper()!.evalJexl( expression: "'sync.login_completed_view'|eventSum('Days', 1, 0) > 0" From 5b3b23e9140857dbec38c53deb21e1eed629aec7 Mon Sep 17 00:00:00 2001 From: Cyndi Chin Date: Tue, 6 Aug 2024 20:13:57 -0400 Subject: [PATCH 053/128] Bugfix FXIOS-9763 [Unit Tests] Fix flakey TabToolbarHelperTests (#21461) --- .../ClientTests/TabToolbarHelperTests.swift | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/TabToolbarHelperTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/TabToolbarHelperTests.swift index 5a60ed7db9c2..a228c2a61cfb 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/TabToolbarHelperTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/TabToolbarHelperTests.swift @@ -10,9 +10,6 @@ import Common import Shared class TabToolbarHelperTests: XCTestCase { - var subject: TabToolbarHelper! - var mockToolbar: MockTabToolbar! - let backButtonImage = UIImage.templateImageNamed(StandardImageIdentifiers.Large.back)? .imageFlippedForRightToLeftLayoutDirection() let forwardButtonImage = UIImage.templateImageNamed(StandardImageIdentifiers.Large.forward)? @@ -25,36 +22,41 @@ class TabToolbarHelperTests: XCTestCase { override func setUp() { super.setUp() DependencyHelperMock().bootstrapDependencies() - mockToolbar = MockTabToolbar() - subject = TabToolbarHelper(toolbar: mockToolbar) - Glean.shared.resetGlean(clearStores: true) } override func tearDown() { + DependencyHelperMock().reset() super.tearDown() - AppContainer.shared.reset() - mockToolbar = nil - subject = nil } func testSetsInitialImages() { + let mockToolbar = MockTabToolbar() + _ = TabToolbarHelper(toolbar: mockToolbar) XCTAssertEqual(mockToolbar.backButton.image(for: .normal), backButtonImage) XCTAssertEqual(mockToolbar.forwardButton.image(for: .normal), forwardButtonImage) } func testSearchStateImages() { + let mockToolbar = MockTabToolbar() + let subject = TabToolbarHelper(toolbar: mockToolbar) subject.setMiddleButtonState(.search) XCTAssertEqual(mockToolbar.multiStateButton.image(for: .normal), searchButtonImage) } func testTapHome() { + let mockToolbar = MockTabToolbar() + let subject = TabToolbarHelper(toolbar: mockToolbar) subject.setMiddleButtonState(.home) XCTAssertEqual(mockToolbar.multiStateButton.image(for: .normal), imageHome) } func testTelemetryForSiteMenu() { + Glean.shared.resetGlean(clearStores: true) + let mockToolbar = MockTabToolbar() + _ = TabToolbarHelper(toolbar: mockToolbar) mockToolbar.tabToolbarDelegate?.tabToolbarDidPressMenu(mockToolbar, button: mockToolbar.appMenuButton) testCounterMetricRecordingSuccess(metric: GleanMetrics.AppMenu.siteMenu) + Glean.shared.resetGlean(clearStores: true) } func test_tabToolBarHelper_basicCreation_doesntLeak() { @@ -123,8 +125,7 @@ class MockTabToolbar: TabToolbarProtocol { init() { profile = MockProfile() - tabManager = TabManagerImplementation(profile: profile, - uuid: ReservedWindowUUID(uuid: .XCTestDefaultUUID, isNew: false)) + tabManager = MockTabManager() LegacyFeatureFlagsManager.shared.initializeDeveloperFeatures(with: profile) _tabToolBarDelegate = BrowserViewController(profile: profile, tabManager: tabManager) } From dfa256c8505c407353edb400b0948688f8fdee46 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 6 Aug 2024 20:46:16 -0400 Subject: [PATCH 054/128] Auto update SPM with latest rust-component release 131.0.20240806050256 (#21471) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- firefox-ios/Client.xcodeproj/project.pbxproj | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- focus-ios/Blockzilla.xcodeproj/project.pbxproj | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/firefox-ios/Client.xcodeproj/project.pbxproj b/firefox-ios/Client.xcodeproj/project.pbxproj index a179bfd86989..de07c8c6a39f 100644 --- a/firefox-ios/Client.xcodeproj/project.pbxproj +++ b/firefox-ios/Client.xcodeproj/project.pbxproj @@ -23117,7 +23117,7 @@ repositoryURL = "https://github.com/mozilla/rust-components-swift.git"; requirement = { kind = exactVersion; - version = 130.0.20240802050337; + version = 131.0.20240806050256; }; }; 435C85EE2788F4D00072B526 /* XCRemoteSwiftPackageReference "glean-swift" */ = { diff --git a/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 9a5a09dc2c1a..fe51540c1b44 100644 --- a/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -95,8 +95,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/mozilla/rust-components-swift.git", "state" : { - "revision" : "4450df67aab6bc140d68a321d13a0a9edd297066", - "version" : "130.0.20240802050337" + "revision" : "842e406e43184710547089a318af8e55fbb6e436", + "version" : "131.0.20240806050256" } }, { diff --git a/focus-ios/Blockzilla.xcodeproj/project.pbxproj b/focus-ios/Blockzilla.xcodeproj/project.pbxproj index 5c52815e0fcc..13e10dc59a51 100644 --- a/focus-ios/Blockzilla.xcodeproj/project.pbxproj +++ b/focus-ios/Blockzilla.xcodeproj/project.pbxproj @@ -7159,7 +7159,7 @@ repositoryURL = "https://github.com/mozilla/rust-components-swift"; requirement = { kind = exactVersion; - version = 130.0.20240802050337; + version = 131.0.20240806050256; }; }; 8A0E7F2C2BA0F0E0006BC6B6 /* XCRemoteSwiftPackageReference "Fuzi" */ = { diff --git a/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 3eb239af581e..3b53873a5ad5 100644 --- a/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -51,8 +51,8 @@ "repositoryURL": "https://github.com/mozilla/rust-components-swift", "state": { "branch": null, - "revision": "4450df67aab6bc140d68a321d13a0a9edd297066", - "version": "130.0.20240802050337" + "revision": "842e406e43184710547089a318af8e55fbb6e436", + "version": "131.0.20240806050256" } }, { From c2628f08eacb67c979889987766d3537d6420afb Mon Sep 17 00:00:00 2001 From: dragosb01 <134391433+dragosb01@users.noreply.github.com> Date: Wed, 7 Aug 2024 14:48:22 +0300 Subject: [PATCH 055/128] Preliminary work for multi window ipad (#21479) --- firefox-ios/Client.xcodeproj/project.pbxproj | 4 + .../ExperimentIntegrationTests.xctestplan | 1 + .../Tests/PerformanceTestPlan.xctestplan | 1 + .../Tests/Smoketest1.xctestplan | 1 + .../Tests/Smoketest2.xctestplan | 1 + .../Tests/Smoketest3.xctestplan | 1 + .../Tests/Smoketest4.xctestplan | 1 + .../Tests/SyncIntegrationTestPlan.xctestplan | 1 + .../Tests/XCUITests/MultiWindowTests.swift | 76 +++++++++++++++++++ 9 files changed, 87 insertions(+) create mode 100644 firefox-ios/firefox-ios-tests/Tests/XCUITests/MultiWindowTests.swift diff --git a/firefox-ios/Client.xcodeproj/project.pbxproj b/firefox-ios/Client.xcodeproj/project.pbxproj index de07c8c6a39f..710e8b2cf3ee 100644 --- a/firefox-ios/Client.xcodeproj/project.pbxproj +++ b/firefox-ios/Client.xcodeproj/project.pbxproj @@ -1046,6 +1046,7 @@ B12DDFED2A8DE825008CE9CF /* ToolbarMenuTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B12DDFEC2A8DE825008CE9CF /* ToolbarMenuTests.swift */; }; B15058812AA0A878008B7382 /* OpeningScreenTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B15058802AA0A878008B7382 /* OpeningScreenTests.swift */; }; B1664E9E2B163B7A005D4C71 /* CreditCardsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1664E9D2B163B7A005D4C71 /* CreditCardsTests.swift */; }; + B1CA62822C0DB43600D31625 /* MultiWindowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1CA62812C0DB43600D31625 /* MultiWindowTests.swift */; }; B1F90EC12BB3F6B600A4D431 /* ZoomingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1F90EC02BB3F6B600A4D431 /* ZoomingTests.swift */; }; B236204B2B851FE1000B1DE7 /* AddressAutoFillBottomSheetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B236204A2B851FE0000B1DE7 /* AddressAutoFillBottomSheetView.swift */; }; B236204D2B8673DE000B1DE7 /* AddressScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B236204C2B8673DE000B1DE7 /* AddressScrollView.swift */; }; @@ -7101,6 +7102,7 @@ B18D4F2291BA5459431EDCA9 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/Shared.strings"; sourceTree = ""; }; B19648D5B3667FE0CB25D069 /* my */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = my; path = my.lproj/Menu.strings; sourceTree = ""; }; B1C044CA95EB3F5258D2EC51 /* bg */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bg; path = bg.lproj/InfoPlist.strings; sourceTree = ""; }; + B1CA62812C0DB43600D31625 /* MultiWindowTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiWindowTests.swift; sourceTree = ""; }; B1D14C77AD55FE126B7904D8 /* oc */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = oc; path = oc.lproj/PrivateBrowsing.strings; sourceTree = ""; }; B1D74C6B9DE786A50986BB1A /* ur */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ur; path = "ur.lproj/Default Browser.strings"; sourceTree = ""; }; B1F04E16A0BF365D67AD0C6F /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/Search.strings; sourceTree = ""; }; @@ -9559,6 +9561,7 @@ 3BF4B8DA1D38493300493393 /* Utils */, EB7A651020699BD200B52A5F /* WebPagesForTesting.swift */, 0B9D40781E8D5AC80059E664 /* XCUITests-Bridging-Header.h */, + B1CA62812C0DB43600D31625 /* MultiWindowTests.swift */, ); path = XCUITests; sourceTree = ""; @@ -14438,6 +14441,7 @@ 0B3D670E1E09B90B00C1EFC7 /* AuthenticationTest.swift in Sources */, D4C4BDCE2253725E00986F04 /* LibraryTests.swift in Sources */, 2CCF17532105E4FD00705AE5 /* DisplaySettingsTests.swift in Sources */, + B1CA62822C0DB43600D31625 /* MultiWindowTests.swift in Sources */, 2C97EC711E72C80E0092EC18 /* TopTabsTest.swift in Sources */, 39EB469A1E26DDB4006346E8 /* FxScreenGraph.swift in Sources */, 2CC1B3F01E9B861400814EEC /* DomainAutocompleteTests.swift in Sources */, diff --git a/firefox-ios/firefox-ios-tests/Tests/ExperimentIntegrationTests.xctestplan b/firefox-ios/firefox-ios-tests/Tests/ExperimentIntegrationTests.xctestplan index 311a29fcdaab..fb9a36660e40 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ExperimentIntegrationTests.xctestplan +++ b/firefox-ios/firefox-ios-tests/Tests/ExperimentIntegrationTests.xctestplan @@ -74,6 +74,7 @@ "LibraryTestsIpad", "LoginTest", "MicrosurveyTests", + "MultiWindowTests", "NightModeTests", "OpeningScreenTests", "PerformanceTests", diff --git a/firefox-ios/firefox-ios-tests/Tests/PerformanceTestPlan.xctestplan b/firefox-ios/firefox-ios-tests/Tests/PerformanceTestPlan.xctestplan index 8fef4e59b4ab..7584e48b6a38 100644 --- a/firefox-ios/firefox-ios-tests/Tests/PerformanceTestPlan.xctestplan +++ b/firefox-ios/firefox-ios-tests/Tests/PerformanceTestPlan.xctestplan @@ -49,6 +49,7 @@ "LibraryTestsIpad", "LoginTest", "MicrosurveyTests", + "MultiWindowTests", "NavigationTest", "NewTabSettingsTest", "NightModeTests", diff --git a/firefox-ios/firefox-ios-tests/Tests/Smoketest1.xctestplan b/firefox-ios/firefox-ios-tests/Tests/Smoketest1.xctestplan index 80aca5d60b77..e0899f6ef42a 100644 --- a/firefox-ios/firefox-ios-tests/Tests/Smoketest1.xctestplan +++ b/firefox-ios/firefox-ios-tests/Tests/Smoketest1.xctestplan @@ -145,6 +145,7 @@ "LibraryTestsIphone", "LoginTest", "MicrosurveyTests", + "MultiWindowTests", "NavigationTest", "NavigationTest\/testCopyLink()", "NavigationTest\/testCopyLinkPrivateMode()", diff --git a/firefox-ios/firefox-ios-tests/Tests/Smoketest2.xctestplan b/firefox-ios/firefox-ios-tests/Tests/Smoketest2.xctestplan index 6a16587bdf4f..4a5a6d213ff7 100644 --- a/firefox-ios/firefox-ios-tests/Tests/Smoketest2.xctestplan +++ b/firefox-ios/firefox-ios-tests/Tests/Smoketest2.xctestplan @@ -66,6 +66,7 @@ "LibraryTestsIphone", "LoginTest", "MicrosurveyTests", + "MultiWindowTests", "NavigationTest", "NewTabSettingsTest\/testChangeNewTabSettingsLabel()", "NewTabSettingsTest\/testChangeNewTabSettingsShowBlankPage()", diff --git a/firefox-ios/firefox-ios-tests/Tests/Smoketest3.xctestplan b/firefox-ios/firefox-ios-tests/Tests/Smoketest3.xctestplan index a22027a1b845..15304943a624 100644 --- a/firefox-ios/firefox-ios-tests/Tests/Smoketest3.xctestplan +++ b/firefox-ios/firefox-ios-tests/Tests/Smoketest3.xctestplan @@ -93,6 +93,7 @@ "LibraryTestsIpad", "LoginTest", "MicrosurveyTests", + "MultiWindowTests", "NavigationTest\/testBookmarkLink()", "NavigationTest\/testCopyLink()", "NavigationTest\/testCopyLinkPrivateMode()", diff --git a/firefox-ios/firefox-ios-tests/Tests/Smoketest4.xctestplan b/firefox-ios/firefox-ios-tests/Tests/Smoketest4.xctestplan index d5444c7f19b1..3d7dff4351d1 100644 --- a/firefox-ios/firefox-ios-tests/Tests/Smoketest4.xctestplan +++ b/firefox-ios/firefox-ios-tests/Tests/Smoketest4.xctestplan @@ -83,6 +83,7 @@ "LoginTest\/testSavedLoginSelectUnselect()", "LoginTest\/testSearchLogin()", "MicrosurveyTests", + "MultiWindowTests", "NavigationTest\/testBookmarkLink()", "NavigationTest\/testCopyLink()", "NavigationTest\/testCopyLinkPrivateMode()", diff --git a/firefox-ios/firefox-ios-tests/Tests/SyncIntegrationTestPlan.xctestplan b/firefox-ios/firefox-ios-tests/Tests/SyncIntegrationTestPlan.xctestplan index 31efb7a39c70..e047d13a4b5f 100644 --- a/firefox-ios/firefox-ios-tests/Tests/SyncIntegrationTestPlan.xctestplan +++ b/firefox-ios/firefox-ios-tests/Tests/SyncIntegrationTestPlan.xctestplan @@ -69,6 +69,7 @@ "LibraryTestsIpad", "LibraryTestsIphone", "LoginTest", + "MultiWindowTests", "NavigationTest", "NewTabSettingsTest", "NightModeTests", diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/MultiWindowTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/MultiWindowTests.swift new file mode 100644 index 000000000000..83ca126ddb6b --- /dev/null +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/MultiWindowTests.swift @@ -0,0 +1,76 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/ + +import Foundation +import Common + +class MultiWindowTests: IpadOnlyTestCase { + let dotMenu = springboard.buttons["top-affordance:org.mozilla.ios.Fennec"] + let splitView = springboard.buttons["top-affordance-split-view-button"] + let dotMenuIdentifier = springboard.buttons.matching(identifier: "top-affordance:org.mozilla.ios.Fennec") + + override func setUp() { + super.setUp() + if dotMenuIdentifier.element(boundBy: 1).exists { + closeSplitViewWindow(windowToClose: 1) + } + } + + override func tearDown() { + if dotMenuIdentifier.element(boundBy: 1).exists { + closeSplitViewWindow(windowToClose: 1) + } + super.tearDown() + } + + func testMultiWindowFromHomeScreen() { + dismissSurveyPrompt() + splitViewFromHomeScreen() + // Tap menu button on first and second window + let menuButton = AccessibilityIdentifiers.Toolbar.settingsMenuButton + app.buttons.matching(identifier: menuButton).element(boundBy: 0).tap() + app.buttons.matching(identifier: menuButton).element(boundBy: 1).tap() + // Tap on settings on first and second window + let settings = StandardImageIdentifiers.Large.settings + let settingsOption = app.tables.otherElements.matching(identifier: settings).element(boundBy: 0) + settingsOption.tap() + settingsOption.tap() + } + + func testOpenWindowFromTabSwitcher() { + openWindowFromTabSwitcher(windowsNumber: 1) + // selectTabFromSwitcher() + } + + private func splitViewFromHomeScreen() { + mozWaitForElementToExist(dotMenu) + dotMenu.tap() + mozWaitForElementToExist(splitView) + splitView.tap() + springboard.icons.elementContainingText("split view with Fennec").tap() + } + + // Param windowsNumber - number of tab windows to open from switcher + private func openWindowFromTabSwitcher(windowsNumber: Int) { + for _ in 1...windowsNumber { + mozWaitForElementToExist(dotMenu) + dotMenu.tap() + let cardOrgMozillaIosFennecButton = springboard.buttons["card:org.mozilla.ios.Fennec:"] + cardOrgMozillaIosFennecButton.tap() + } + } + + // Param windowToClose - 0 for the first window, 1 for the second window + func closeSplitViewWindow(windowToClose: Int) { + mozWaitForElementToExist(dotMenuIdentifier.element(boundBy: windowToClose)) + dotMenuIdentifier.element(boundBy: windowToClose).tap() + mozWaitForElementToExist(springboard.buttons["top-affordance-close-window"]) + springboard.buttons["top-affordance-close-window"].tap() + } + + // Coudn't find a way to select a tab from switcher +// private func selectTabFromSwitcher() { +// let tabIdentifier = "card:org.mozilla.ios.Fennec:sceneID:org.mozilla.ios.Fennec" +// } +} From 143ac7182387640b263d98a57270f6bc72ad3a98 Mon Sep 17 00:00:00 2001 From: Cyndi Chin Date: Wed, 7 Aug 2024 08:41:54 -0400 Subject: [PATCH 056/128] Bugfix FXIOS-9772 [Unit Tests] Update AccountSync tests (#21460) --- .../Helpers/AccountSyncHandlerTests.swift | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Helpers/AccountSyncHandlerTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Helpers/AccountSyncHandlerTests.swift index 7831d5dbd272..cf386c6d476f 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Helpers/AccountSyncHandlerTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Helpers/AccountSyncHandlerTests.swift @@ -45,24 +45,21 @@ class AccountSyncHandlerTests: XCTestCase { XCTAssertEqual(syncManager.syncNamedCollectionsCalled, 1) } - func testTabDidGainFocus_highThrottleTime_doesntSync() { - let subject = AccountSyncHandler(with: profile, throttleTime: 1000, queue: DispatchQueue.global()) + func testTabDidGainFocus_highThrottleTime_executedAtMostOnce() { + let threshold: Double = 1000 + let stepWaitTime = 2.0 + let subject = AccountSyncHandler(with: profile, throttleTime: threshold, queue: DispatchQueue.global()) let tab = createTab(profile: profile) - subject.tabDidGainFocus(tab) - - XCTAssertEqual(syncManager.syncNamedCollectionsCalled, 0) - } - func testTabDidGainFocus_multipleThrottle_withoutWaitdoesntSync() { - let subject = AccountSyncHandler(with: profile, throttleTime: 0.2, queue: DispatchQueue.global()) - let tab = createTab(profile: profile) - subject.tabDidGainFocus(tab) - subject.tabDidGainFocus(tab) - subject.tabDidGainFocus(tab) subject.tabDidGainFocus(tab) subject.tabDidGainFocus(tab) - XCTAssertEqual(syncManager.syncNamedCollectionsCalled, 0) + let expectation = XCTestExpectation(description: "SyncNamedCollectionsCalled value expectation") + DispatchQueue.main.asyncAfter(deadline: .now() + stepWaitTime) { + XCTAssertEqual(self.syncManager.syncNamedCollectionsCalled, 1) + expectation.fulfill() + } + wait(for: [expectation], timeout: stepWaitTime * 2) } func testTabDidGainFocus_multipleThrottle_withWaitSyncOnce() { From 48ea39314d3cacc994a04dc6baec90cb39e5e382 Mon Sep 17 00:00:00 2001 From: Benjamin Forehand Jr Date: Wed, 7 Aug 2024 11:28:27 -0500 Subject: [PATCH 057/128] Bugfix EXP-4749: Fix experiment integration smoke test generator. (#21481) --- .../generate_smoke_tests.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/firefox-ios/firefox-ios-tests/Tests/ExperimentIntegrationTests/generate_smoke_tests.py b/firefox-ios/firefox-ios-tests/Tests/ExperimentIntegrationTests/generate_smoke_tests.py index 986799d14e64..6e69f2f37213 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ExperimentIntegrationTests/generate_smoke_tests.py +++ b/firefox-ios/firefox-ios-tests/Tests/ExperimentIntegrationTests/generate_smoke_tests.py @@ -38,8 +38,11 @@ def search_for_smoke_tests(tests_name): test_names.append(code[locations[0] + 1].strip(":")) for location in locations: - test_name = code[location + 2] - test_names.append(test_name) + for count in range(5): # loop forward to get 'func' location and then test name + if "func" in code[location + count]: + test_name = code[location + count + 1] + test_names.append(test_name) + break return test_names @@ -100,5 +103,8 @@ def test_smoke_{test_name}(xcodebuild, setup_experiment, start_app, experiment_b tests = yaml.safe_load(file) test_modules = [test for test in tests.get("smoke_tests")] for item in test_modules: - tests = search_for_smoke_tests(item) - generate_smoke_tests(tests) \ No newline at end of file + try: # incase a test file gets deleted this will alllow the program to run + tests = search_for_smoke_tests(item) + except TypeError: + continue + generate_smoke_tests(tests) From 3b07ff807f3e9a3f96d564524d377948754d9c1e Mon Sep 17 00:00:00 2001 From: "Ben Hearsum (he/him)" Date: Wed, 7 Aug 2024 12:58:26 -0400 Subject: [PATCH 058/128] remove unnecessary support for `releases` branches in taskcluster.yml (#21357) As far as I can tell, there's never been any branches starting with `releases`. It's possible that this was meant to be `release` (of which there are many branches...), but seeing as it hasn't been needed, we can probably just remove it? This is being done partly in support of https://bugzilla.mozilla.org/show_bug.cgi?id=1907217, where we're becoming more explicit about which branches we grant scopes to in Github repositories. --- .taskcluster.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.taskcluster.yml b/.taskcluster.yml index d053e622797a..d6aa1d32a9ac 100644 --- a/.taskcluster.yml +++ b/.taskcluster.yml @@ -108,7 +108,7 @@ tasks: $if: > tasks_for in ["action", "cron"] || (isPullRequest && pullRequestAction in ["opened", "reopened", "synchronize"]) - || (tasks_for == "github-push" && (short_head_branch == "main" || short_head_branch[:8] == "releases")) + || (tasks_for == "github-push" && short_head_branch == "main") || (tasks_for == "github-release" && releaseAction == "published") then: taskId: From 80e5f9f212c85ea4a079651f838dc6aa462cd7e8 Mon Sep 17 00:00:00 2001 From: Isabella Date: Wed, 7 Aug 2024 17:45:07 -0600 Subject: [PATCH 059/128] Temporary workaround for FXIOS-9785 fix (PR 21328 partial revert). (#21486) * Temporary workaround for FXIOS-9785 fix (PR 21328 partial revert). * Added documentation. --- .../Views/BrowserViewController.swift | 1 + .../Frontend/Browser/TabScrollController.swift | 1 + .../TabManagement/TabManagerImplementation.swift | 16 ++++++++++++++++ 3 files changed, 18 insertions(+) diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift index dd7c5ba7722d..afcb590a3e72 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift @@ -3532,6 +3532,7 @@ extension BrowserViewController: TabManagerDelegate { updateFindInPageVisibility(isVisible: false, tab: previous) setupMiddleButtonStatus(isLoading: selected?.loading ?? false) + // [FXIOS-9785 Note #2] Back button can't be enabled unless the webView is already initialized if isToolbarRefactorEnabled { dispatchBackForwardToolbarAction(selected?.canGoBack, windowUUID, .backButtonStateChanged) dispatchBackForwardToolbarAction(selected?.canGoForward, windowUUID, .forwardButtonStateChanged) diff --git a/firefox-ios/Client/Frontend/Browser/TabScrollController.swift b/firefox-ios/Client/Frontend/Browser/TabScrollController.swift index c478989ed481..4a3f62799b62 100644 --- a/firefox-ios/Client/Frontend/Browser/TabScrollController.swift +++ b/firefox-ios/Client/Frontend/Browser/TabScrollController.swift @@ -32,6 +32,7 @@ class TabScrollingController: NSObject, FeatureFlaggable, SearchBarLocationProvi didSet { self.scrollView?.addGestureRecognizer(panGesture) + // [FXIOS-9785 Note #3] Toolbar delegate can't be set unless the webView is already initialized scrollView?.delegate = self scrollView?.keyboardDismissMode = .onDrag configureRefreshControl(isEnabled: true) diff --git a/firefox-ios/Client/TabManagement/TabManagerImplementation.swift b/firefox-ios/Client/TabManagement/TabManagerImplementation.swift index a7d98491966b..24f08fb9441a 100644 --- a/firefox-ios/Client/TabManagement/TabManagerImplementation.swift +++ b/firefox-ios/Client/TabManagement/TabManagerImplementation.swift @@ -440,6 +440,22 @@ class TabManagerImplementation: LegacyTabManager, Notifiable, WindowSimpleTabsPr private func selectTabWithSession(tab: Tab, previous: Tab?, sessionData: Data?) { selectedTab?.createWebview(with: sessionData) selectedTab?.lastExecutedTime = Date.now() + + // [FXIOS-9785 Note 1] Workaround to resolve Aug 7, 2024 incident (PR #21486) + // NOTE: This needs more work because the change from PR #21328 fixed another issue, + // and thus couldn't be completely rolled back. + // However, now we are repeating this delegate notification which is less than ideal and may have unexpected + // consequences. + // See ticket for more information. + // Broadcast updates for any listeners + delegates.forEach { + $0.get()?.tabManager( + self, + didSelectedTabChange: tab, + previous: previous, + isRestoring: !tabRestoreHasFinished + ) + } } // MARK: - Screenshots From e25574812ec2604967efcc66c1e9051f6b5c4e1f Mon Sep 17 00:00:00 2001 From: dragosb01 <134391433+dragosb01@users.noreply.github.com> Date: Thu, 8 Aug 2024 10:48:31 +0300 Subject: [PATCH 060/128] Updates MTE-3282 - for multi window tests (#21490) --- .../Tests/XCUITests/MultiWindowTests.swift | 6 ++++++ .../firefox-ios-tests/Tests/XCUITests/NavigationTest.swift | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/MultiWindowTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/MultiWindowTests.swift index 83ca126ddb6b..5666e3844f76 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/MultiWindowTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/MultiWindowTests.swift @@ -12,6 +12,7 @@ class MultiWindowTests: IpadOnlyTestCase { override func setUp() { super.setUp() + super.setUpLaunchArguments() if dotMenuIdentifier.element(boundBy: 1).exists { closeSplitViewWindow(windowToClose: 1) } @@ -25,11 +26,15 @@ class MultiWindowTests: IpadOnlyTestCase { } func testMultiWindowFromHomeScreen() { + if skipPlatform { return } dismissSurveyPrompt() splitViewFromHomeScreen() + XCTAssertEqual(dotMenuIdentifier.count, 2, "There are not 2 instances opened") // Tap menu button on first and second window let menuButton = AccessibilityIdentifiers.Toolbar.settingsMenuButton + mozWaitForElementToExist(app.buttons.matching(identifier: menuButton).element(boundBy: 0)) app.buttons.matching(identifier: menuButton).element(boundBy: 0).tap() + mozWaitForElementToExist(app.buttons.matching(identifier: menuButton).element(boundBy: 1)) app.buttons.matching(identifier: menuButton).element(boundBy: 1).tap() // Tap on settings on first and second window let settings = StandardImageIdentifiers.Large.settings @@ -39,6 +44,7 @@ class MultiWindowTests: IpadOnlyTestCase { } func testOpenWindowFromTabSwitcher() { + if skipPlatform { return } openWindowFromTabSwitcher(windowsNumber: 1) // selectTabFromSwitcher() } diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/NavigationTest.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/NavigationTest.swift index f90fad4483ea..0f629761da47 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/NavigationTest.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/NavigationTest.swift @@ -368,7 +368,7 @@ class NavigationTest: BaseTestCase { navigator.nowAt(NewTabScreen) navigator.openURL("https://expired.badssl.com/") - mozWaitForElementToExist(app.buttons["Advanced"]) + mozWaitForElementToExist(app.buttons["Advanced"], timeout: TIMEOUT_LONG) app.buttons["Advanced"].tap() mozWaitForElementToExist(app.links["Visit site anyway"]) From 3f373c00f6efb99876bc3898de99a6099e33a1f1 Mon Sep 17 00:00:00 2001 From: petruSt24 <126153378+petruSt24@users.noreply.github.com> Date: Thu, 8 Aug 2024 16:48:31 +0300 Subject: [PATCH 061/128] Bugfix FXIOS-9780 The site info sheet can no longer be dismissed (#21472) (#21492) --- .../EnhancedTrackingProtectionCoordinator.swift | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/firefox-ios/Client/Coordinators/EnhancedTrackingProtectionCoordinator.swift b/firefox-ios/Client/Coordinators/EnhancedTrackingProtectionCoordinator.swift index c30aac68d667..4f4598f39896 100644 --- a/firefox-ios/Client/Coordinators/EnhancedTrackingProtectionCoordinator.swift +++ b/firefox-ios/Client/Coordinators/EnhancedTrackingProtectionCoordinator.swift @@ -48,8 +48,9 @@ class EnhancedTrackingProtectionCoordinator: BaseCoordinator, contentBlockerStats: contentBlockerStats ) - self.enhancedTrackingProtectionMenuVC = TrackingProtectionViewController(viewModel: etpViewModel, - windowUUID: tabManager.windowUUID) + enhancedTrackingProtectionMenuVC = TrackingProtectionViewController(viewModel: etpViewModel, + windowUUID: tabManager.windowUUID) + enhancedTrackingProtectionMenuVC?.enhancedTrackingProtectionMenuDelegate = self } else { let oldEtpViewModel = EnhancedTrackingProtectionMenuVM( url: url, @@ -59,10 +60,10 @@ class EnhancedTrackingProtectionCoordinator: BaseCoordinator, contentBlockerStatus: contentBlockerStatus ) - self.legacyEnhancedTrackingProtectionMenuVC = EnhancedTrackingProtectionMenuVC(viewModel: oldEtpViewModel, - windowUUID: tabManager.windowUUID) + legacyEnhancedTrackingProtectionMenuVC = EnhancedTrackingProtectionMenuVC(viewModel: oldEtpViewModel, + windowUUID: tabManager.windowUUID) + legacyEnhancedTrackingProtectionMenuVC?.enhancedTrackingProtectionMenuDelegate = self } - enhancedTrackingProtectionMenuVC?.enhancedTrackingProtectionMenuDelegate = self } func start(sourceView: UIView) { From ce505bf4d802c44cb02ef14770c6f78213213974 Mon Sep 17 00:00:00 2001 From: Cyndi Chin Date: Thu, 8 Aug 2024 11:46:14 -0400 Subject: [PATCH 062/128] Bugfix FXIOS-9762 [Unit Tests] Add more checks for PasswordManagerViewModelTests (#21482) * Bugfix FXIOS-9762 [Unit Tests] Add more checks for PasswordManagerViewModelTests * refactor tests by using loginprovider instead of rust logins directly * add glean metrics --- firefox-ios/Client.xcodeproj/project.pbxproj | 8 ++ .../PasswordManagement/LoginProvider.swift | 16 ++++ .../PasswordManagerListViewController.swift | 3 +- .../PasswordManagerViewModel.swift | 9 +- .../Telemetry/AppStartupTelemetry.swift | 3 +- .../Mocks/MockLoginViewModelDelegate.swift | 49 ++++++++++ .../PasswordManagerViewModelTests.swift | 90 +++++++++---------- 7 files changed, 124 insertions(+), 54 deletions(-) create mode 100644 firefox-ios/Client/Frontend/PasswordManagement/LoginProvider.swift create mode 100644 firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockLoginViewModelDelegate.swift diff --git a/firefox-ios/Client.xcodeproj/project.pbxproj b/firefox-ios/Client.xcodeproj/project.pbxproj index 710e8b2cf3ee..b81afb3a616d 100644 --- a/firefox-ios/Client.xcodeproj/project.pbxproj +++ b/firefox-ios/Client.xcodeproj/project.pbxproj @@ -780,6 +780,7 @@ 8A8629E2288096C40096DDB1 /* BookmarksFolderCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A8629E1288096C40096DDB1 /* BookmarksFolderCell.swift */; }; 8A8629E72880B7330096DDB1 /* BookmarksPanelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A8629E52880B69C0096DDB1 /* BookmarksPanelTests.swift */; }; 8A86DAD8277298DE00D7BFFF /* ClosedTabsStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A86DAD7277298DE00D7BFFF /* ClosedTabsStoreTests.swift */; }; + 8A880C442C63CFE200B77F23 /* MockLoginViewModelDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A880C432C63CFE200B77F23 /* MockLoginViewModelDelegate.swift */; }; 8A88815A2B20FFE0009635AE /* GCDWebServers in Frameworks */ = {isa = PBXBuildFile; productRef = 8A8881592B20FFE0009635AE /* GCDWebServers */; }; 8A88815C2B2103AD009635AE /* WebEngine in Frameworks */ = {isa = PBXBuildFile; productRef = 8A88815B2B2103AD009635AE /* WebEngine */; }; 8A88815E2B21071E009635AE /* GCDWebServers in Frameworks */ = {isa = PBXBuildFile; productRef = 8A88815D2B21071E009635AE /* GCDWebServers */; }; @@ -820,6 +821,7 @@ 8AAAB0592C1B7240008830B3 /* MockRustFirefoxSuggest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AAAB0582C1B723F008830B3 /* MockRustFirefoxSuggest.swift */; }; 8AAAB05B2C1B7268008830B3 /* ClientTabsSearchWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AAAB05A2C1B7268008830B3 /* ClientTabsSearchWrapper.swift */; }; 8AAAB05F2C1B72C9008830B3 /* SearchHighlightItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AAAB05E2C1B72C9008830B3 /* SearchHighlightItem.swift */; }; + 8AABB92D2C64F77000F1FE51 /* LoginProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AABB92C2C64F77000F1FE51 /* LoginProvider.swift */; }; 8AABBCFC2A0010900089941E /* GleanWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AABBCFB2A0010900089941E /* GleanWrapper.swift */; }; 8AABBCFF2A0017960089941E /* MockGleanWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AABBCFD2A0017560089941E /* MockGleanWrapper.swift */; }; 8AABBD012A001ADF0089941E /* ApplicationHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AABBD002A001ADF0089941E /* ApplicationHelper.swift */; }; @@ -6540,6 +6542,7 @@ 8A8629E52880B69C0096DDB1 /* BookmarksPanelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarksPanelTests.swift; sourceTree = ""; }; 8A86DAD7277298DE00D7BFFF /* ClosedTabsStoreTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClosedTabsStoreTests.swift; sourceTree = ""; }; 8A87AEE02C1B4D17007428B2 /* SearchViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchViewModelTests.swift; sourceTree = ""; }; + 8A880C432C63CFE200B77F23 /* MockLoginViewModelDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockLoginViewModelDelegate.swift; sourceTree = ""; }; 8A8917682B57283B008B01EA /* HomepageHeaderCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomepageHeaderCell.swift; sourceTree = ""; }; 8A8BAE152B2119E600D774EB /* InternalURL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InternalURL.swift; sourceTree = ""; }; 8A8DDEBE276259A900E7B97A /* RatingPromptManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RatingPromptManager.swift; sourceTree = ""; }; @@ -6579,6 +6582,7 @@ 8AAAB0582C1B723F008830B3 /* MockRustFirefoxSuggest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockRustFirefoxSuggest.swift; sourceTree = ""; }; 8AAAB05A2C1B7268008830B3 /* ClientTabsSearchWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientTabsSearchWrapper.swift; sourceTree = ""; }; 8AAAB05E2C1B72C9008830B3 /* SearchHighlightItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchHighlightItem.swift; sourceTree = ""; }; + 8AABB92C2C64F77000F1FE51 /* LoginProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginProvider.swift; sourceTree = ""; }; 8AABBCFB2A0010900089941E /* GleanWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GleanWrapper.swift; sourceTree = ""; }; 8AABBCFD2A0017560089941E /* MockGleanWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockGleanWrapper.swift; sourceTree = ""; }; 8AABBD002A001ADF0089941E /* ApplicationHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationHelper.swift; sourceTree = ""; }; @@ -11405,6 +11409,7 @@ BA1C68BB2B7ED153000D9397 /* MockWebKit.swift */, 1D558A562BED7ECB001EF527 /* MockWindowManager.swift */, 0AC659282BF493CE005C614A /* MockFxAWebViewModel.swift */, + 8A880C432C63CFE200B77F23 /* MockLoginViewModelDelegate.swift */, ); path = Mocks; sourceTree = ""; @@ -12369,6 +12374,7 @@ E1E5BE242A28F7BE00248F77 /* PasswordDetailViewControllerModel.swift */, CAA3B7E52497DCB60094E3C1 /* LoginDataSource.swift */, CA520E7924913C1B00CCAB48 /* PasswordManagerViewModel.swift */, + 8AABB92C2C64F77000F1FE51 /* LoginProvider.swift */, CA7FC7D224A6A9B70012F347 /* PasswordManagerDataSourceHelper.swift */, CA90753724929B22005B794D /* NoLoginsView.swift */, CAC458F0249429C20042561A /* PasswordManagerSelectionHelper.swift */, @@ -15089,6 +15095,7 @@ EBB89507219398E500EB91A0 /* ContentBlocker.swift in Sources */, 216A0D792A40E85A008077BA /* ThemeSettingsState.swift in Sources */, 5A3A2A0D287F742C00B79EAC /* BackgroundSyncUtility.swift in Sources */, + 8AABB92D2C64F77000F1FE51 /* LoginProvider.swift in Sources */, 21AFCFEE2AE80B700027E9CE /* TabsCoordinator.swift in Sources */, 8A1CBB952BE017D3008BE4D4 /* MicrosurveyPromptAction.swift in Sources */, 23ED80FF25C89C9800D0E9D5 /* DefaultBrowserOnboardingViewController.swift in Sources */, @@ -15678,6 +15685,7 @@ 8A95FF672B1E97A800AC303D /* TelemetryContextualIdentifierTests.swift in Sources */, 965C3C9829343445006499ED /* MockAppSessionManager.swift in Sources */, 8AFCE50929DE136300B1B253 /* MockLaunchFinishedLoadingDelegate.swift in Sources */, + 8A880C442C63CFE200B77F23 /* MockLoginViewModelDelegate.swift in Sources */, 8AE1E1DB27B1C1320024C45E /* SearchBarSettingsViewModelTests.swift in Sources */, CA24B53924ABFE250093848C /* PasswordManagerSelectionHelperTests.swift in Sources */, C8610DA82A0EBD4100B79FF1 /* OnboardingButtonActionTests.swift in Sources */, diff --git a/firefox-ios/Client/Frontend/PasswordManagement/LoginProvider.swift b/firefox-ios/Client/Frontend/PasswordManagement/LoginProvider.swift new file mode 100644 index 000000000000..f1c57d8b3c08 --- /dev/null +++ b/firefox-ios/Client/Frontend/PasswordManagement/LoginProvider.swift @@ -0,0 +1,16 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/ + +import Foundation +import MozillaAppServices +import Storage + +protocol LoginProvider: AnyObject { + func searchLoginsWithQuery( + _ query: String?, + completionHandler: @escaping (Result<[EncryptedLogin], Error>) -> Void) + func addLogin(login: LoginEntry, completionHandler: @escaping (Result) -> Void) +} + +extension RustLogins: LoginProvider {} diff --git a/firefox-ios/Client/Frontend/PasswordManagement/PasswordManagerListViewController.swift b/firefox-ios/Client/Frontend/PasswordManagement/PasswordManagerListViewController.swift index ce2b65d9ed96..f0cd216d0735 100644 --- a/firefox-ios/Client/Frontend/PasswordManagement/PasswordManagerListViewController.swift +++ b/firefox-ios/Client/Frontend/PasswordManagement/PasswordManagerListViewController.swift @@ -47,7 +47,8 @@ class PasswordManagerListViewController: SensitiveViewController, Themeable { self.viewModel = PasswordManagerViewModel( profile: profile, searchController: searchController, - theme: themeManager.getCurrentTheme(for: windowUUID) + theme: themeManager.getCurrentTheme(for: windowUUID), + loginProvider: profile.logins ) self.loginDataSource = LoginDataSource(viewModel: viewModel) self.themeManager = themeManager diff --git a/firefox-ios/Client/Frontend/PasswordManagement/PasswordManagerViewModel.swift b/firefox-ios/Client/Frontend/PasswordManagement/PasswordManagerViewModel.swift index 6cbd2fc1b45b..5d276a78a8a2 100644 --- a/firefox-ios/Client/Frontend/PasswordManagement/PasswordManagerViewModel.swift +++ b/firefox-ios/Client/Frontend/PasswordManagement/PasswordManagerViewModel.swift @@ -6,7 +6,6 @@ import Common import Foundation import Storage import Shared -import AuthenticationServices import struct MozillaAppServices.EncryptedLogin import struct MozillaAppServices.LoginEntry @@ -22,6 +21,7 @@ final class PasswordManagerViewModel { private(set) var isDuringSearchControllerDismiss = false private(set) var count = 0 private(set) var hasData = false + private let loginProvider: LoginProvider weak var searchController: UISearchController? weak var delegate: LoginViewModelDelegate? private(set) var titles = [Character]() @@ -46,10 +46,11 @@ final class PasswordManagerViewModel { var hasLoadedBreaches = false var theme: Theme - init(profile: Profile, searchController: UISearchController, theme: Theme) { + init(profile: Profile, searchController: UISearchController, theme: Theme, loginProvider: LoginProvider) { self.profile = profile self.searchController = searchController self.theme = theme + self.loginProvider = loginProvider } func loadLogins(_ query: String? = nil, loginDataSource: LoginDataSource) { @@ -78,7 +79,7 @@ final class PasswordManagerViewModel { /// Searches SQLite database for logins that match query. /// Wraps the SQLiteLogins method to allow us to cancel it from our end. func queryLogins(_ query: String, completion: @escaping ([EncryptedLogin]) -> Void) { - profile.logins.searchLoginsWithQuery(query) { result in + loginProvider.searchLoginsWithQuery(query) { result in ensureMainThread { switch result { case .success(let logins): @@ -155,7 +156,7 @@ final class PasswordManagerViewModel { } public func save(loginRecord: LoginEntry, completion: @escaping ((String?) -> Void)) { - profile.logins.addLogin(login: loginRecord, completionHandler: { result in + loginProvider.addLogin(login: loginRecord, completionHandler: { result in switch result { case .success(let encryptedLogin): self.sendLoginsSavedTelemetry() diff --git a/firefox-ios/Client/Telemetry/AppStartupTelemetry.swift b/firefox-ios/Client/Telemetry/AppStartupTelemetry.swift index 176f6ce4d744..5dd25a41c9b2 100644 --- a/firefox-ios/Client/Telemetry/AppStartupTelemetry.swift +++ b/firefox-ios/Client/Telemetry/AppStartupTelemetry.swift @@ -41,7 +41,8 @@ final class AppStartupTelemetry { let loginsViewModel = PasswordManagerViewModel( profile: profile, searchController: searchController, - theme: LightTheme() + theme: LightTheme(), + loginProvider: profile.logins ) let dataSource = LoginDataSource(viewModel: loginsViewModel) loginsViewModel.loadLogins(loginDataSource: dataSource) diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockLoginViewModelDelegate.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockLoginViewModelDelegate.swift new file mode 100644 index 000000000000..c4725834ea15 --- /dev/null +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockLoginViewModelDelegate.swift @@ -0,0 +1,49 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/ + +import Foundation +import MozillaAppServices +@testable import Client + +class MockLoginViewModelDelegate: LoginViewModelDelegate { + var loginSectionsDidUpdateCalledCount = 0 + var breachPathDidUpdateCalledCount = 0 + func loginSectionsDidUpdate() { + loginSectionsDidUpdateCalledCount += 1 + } + + func breachPathDidUpdate() { + breachPathDidUpdateCalledCount += 1 + } +} + +class MockLoginProvider: LoginProvider { + var searchLoginsWithQueryCalledCount = 0 + var addLoginCalledCount = 0 + func searchLoginsWithQuery( + _ query: String?, + completionHandler: @escaping ( + Result< + [MozillaAppServices.EncryptedLogin], + any Error + > + ) -> Void + ) { + searchLoginsWithQueryCalledCount += 1 + completionHandler(.success([])) + } + + func addLogin( + login: MozillaAppServices.LoginEntry, + completionHandler: @escaping ( + Result< + MozillaAppServices.EncryptedLogin?, + any Error + > + ) -> Void + ) { + addLoginCalledCount += 1 + completionHandler(.success(nil)) + } +} diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/PasswordManagerViewModelTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/PasswordManagerViewModelTests.swift index c583f3354f7c..d7904214a1db 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/PasswordManagerViewModelTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/PasswordManagerViewModelTests.swift @@ -7,96 +7,90 @@ import MozillaAppServices import Shared import Storage import XCTest +import Glean @testable import Client class PasswordManagerViewModelTests: XCTestCase { var viewModel: PasswordManagerViewModel! var dataSource: LoginDataSource! + var mockDelegate: MockLoginViewModelDelegate! + var mockLoginProvider: MockLoginProvider! override func setUp() { super.setUp() DependencyHelperMock().bootstrapDependencies() let mockProfile = MockProfile() + self.mockLoginProvider = MockLoginProvider() let searchController = UISearchController() self.viewModel = PasswordManagerViewModel( profile: mockProfile, searchController: searchController, - theme: LightTheme() + theme: LightTheme(), + loginProvider: mockLoginProvider ) - self.dataSource = LoginDataSource(viewModel: self.viewModel) + self.mockDelegate = MockLoginViewModelDelegate() + self.viewModel.delegate = mockDelegate self.viewModel.setBreachAlertsManager(MockBreachAlertsClient()) + Glean.shared.resetGlean(clearStores: true) } override func tearDown() { - super.tearDown() - DependencyHelperMock().reset() + Glean.shared.resetGlean(clearStores: true) viewModel = nil - dataSource = nil - } - - private func setupLogins() { - _ = self.viewModel.profile.logins.wipeLocalEngine() - - var expectations: [XCTestExpectation] = [] - for i in (0..<10) { - let addExp = XCTestExpectation(description: "Adding login \(i) \(#function)\(#line)") - expectations.append(addExp) - - let login = LoginEntry(fromJSONDict: [ - "hostname": "https://example\(i).com", - "formSubmitUrl": "https://example.com", - "username": "username\(i)", - "password": "password\(i)" - ]) - self.viewModel.profile.logins.addLogin(login: login) { result in - switch result { - case .success(let logins): - XCTAssertEqual(logins?.fields.origin, "https://example\(i).com") - addExp.fulfill() - case .failure: - XCTFail("Should not have failed") - } - } - } - wait(for: expectations, timeout: 10.0) + mockLoginProvider = nil + mockDelegate = nil + DependencyHelperMock().reset() + super.tearDown() } - func testQueryLoginsWithEmptyString() { - setupLogins() + func testaddLoginWithEmptyString() { + let login = LoginEntry(fromJSONDict: [ + "hostname": "https://example.com", + "formSubmitUrl": "https://example.com", + "username": "username", + "password": "password" + ]) let expectation = XCTestExpectation(description: "Waiting for login query to complete") - viewModel.queryLogins("") { emptyQueryResult in - XCTAssertEqual(emptyQueryResult.count, 10) + viewModel.save(loginRecord: login) { exampleQueryResult in + XCTAssertEqual(self.mockLoginProvider.addLoginCalledCount, 1) expectation.fulfill() } wait(for: [expectation], timeout: 1) + testCounterMetricRecordingSuccess(metric: GleanMetrics.Logins.saved) } - func testQueryLoginsWithExampleString() { - setupLogins() + func testaddLoginWithString() { + let login = LoginEntry(fromJSONDict: [ + "hostname": "https://example.com", + "formSubmitUrl": "https://example.com", + "username": "username", + "password": "password" + ]) let expectation = XCTestExpectation(description: "Waiting for login query to complete") - viewModel.queryLogins("example") { exampleQueryResult in - XCTAssertEqual(exampleQueryResult.count, 10) + viewModel.save(loginRecord: login) { exampleQueryResult in + XCTAssertEqual(self.mockLoginProvider.addLoginCalledCount, 1) expectation.fulfill() } wait(for: [expectation], timeout: 1) + testCounterMetricRecordingSuccess(metric: GleanMetrics.Logins.saved) } - func testQueryLoginsWithNumericString() { - setupLogins() + func testQueryLoginsWithEmptyString() { let expectation = XCTestExpectation(description: "Waiting for login query to complete") - viewModel.queryLogins("3") { threeQueryResult in - XCTAssertEqual(threeQueryResult.count, 1) + viewModel.queryLogins("") { emptyQueryResult in + XCTAssertEqual(self.mockDelegate.loginSectionsDidUpdateCalledCount, 0) + XCTAssertEqual(self.mockLoginProvider.searchLoginsWithQueryCalledCount, 1) expectation.fulfill() } wait(for: [expectation], timeout: 1) } - func testQueryLoginsWithNoResults() { - setupLogins() + func testQueryLoginsWithExampleString() { let expectation = XCTestExpectation(description: "Waiting for login query to complete") - viewModel.queryLogins("yxz") { zQueryResult in - XCTAssertEqual(zQueryResult.count, 0) + viewModel.queryLogins("example") { exampleQueryResult in + XCTAssertEqual(self.mockDelegate.loginSectionsDidUpdateCalledCount, 0) + XCTAssertEqual(self.mockLoginProvider.searchLoginsWithQueryCalledCount, 1) expectation.fulfill() } wait(for: [expectation], timeout: 1) From 1585fef101c67bf51b1a567db154a12613daa4c9 Mon Sep 17 00:00:00 2001 From: Tushar Chitnavis <64319078+tusharC95@users.noreply.github.com> Date: Thu, 8 Aug 2024 12:03:14 -0400 Subject: [PATCH 063/128] Add FXIOS-9628 [Native Error Page] Feature flag for error page setup (#21484) * Add FXIOS-9628 [Native Error Page] Feature flag for error page setup * updated based on review comments * Removed print statement --- .../FeatureFlags/NimbusFlaggableFeature.swift | 2 ++ .../Views/BrowserViewController.swift | 7 +++++++ .../Nimbus/NimbusFeatureFlagLayer.swift | 7 +++++++ .../nativeErrorPageFeature.yaml | 19 +++++++++++++++++++ firefox-ios/nimbus.fml.yaml | 1 + 5 files changed, 36 insertions(+) create mode 100644 firefox-ios/nimbus-features/nativeErrorPageFeature.yaml diff --git a/firefox-ios/Client/FeatureFlags/NimbusFlaggableFeature.swift b/firefox-ios/Client/FeatureFlags/NimbusFlaggableFeature.swift index 752d4e2a9b08..b5af01560936 100644 --- a/firefox-ios/Client/FeatureFlags/NimbusFlaggableFeature.swift +++ b/firefox-ios/Client/FeatureFlags/NimbusFlaggableFeature.swift @@ -27,6 +27,7 @@ enum NimbusFeatureFlagID: String, CaseIterable { case loginAutofill case menuRefactor case microsurvey + case nativeErrorPage case nightMode case preferSwitchToOpenTabOverDuplicate case reduxSearchSettings @@ -88,6 +89,7 @@ struct NimbusFlaggableFeature: HasNimbusSearchBar { .loginAutofill, .microsurvey, .menuRefactor, + .nativeErrorPage, .nightMode, .preferSwitchToOpenTabOverDuplicate, .reduxSearchSettings, diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift index afcb590a3e72..fdc2e3700af7 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift @@ -1369,6 +1369,13 @@ class BrowserViewController: UIViewController, updateBarBordersForMicrosurvey() updateViewConstraints() } + + // MARK: - Native Error Page + + private func setupNativeErrorPage() { + guard featureFlags.isFeatureEnabled(.nativeErrorPage, checking: .buildOnly) else { return } + } + // MARK: - Update content func updateContentInHomePanel(_ browserViewType: BrowserViewType) { diff --git a/firefox-ios/Client/Nimbus/NimbusFeatureFlagLayer.swift b/firefox-ios/Client/Nimbus/NimbusFeatureFlagLayer.swift index 47c35edab601..7e2675a4254f 100644 --- a/firefox-ios/Client/Nimbus/NimbusFeatureFlagLayer.swift +++ b/firefox-ios/Client/Nimbus/NimbusFeatureFlagLayer.swift @@ -58,6 +58,9 @@ final class NimbusFeatureFlagLayer { case .microsurvey: return checkMicrosurveyFeature(from: nimbus) + case .nativeErrorPage: + return checkNativeErrorPageFeature(from: nimbus) + case .nightMode: return checkNightModeFeature(from: nimbus) @@ -297,4 +300,8 @@ final class NimbusFeatureFlagLayer { let config = nimbus.features.remoteTabManagement.value() return config.closeTabsEnabled } + + private func checkNativeErrorPageFeature(from nimbus: FxNimbus) -> Bool { + return nimbus.features.nativeErrorPageFeature.value().enabled + } } diff --git a/firefox-ios/nimbus-features/nativeErrorPageFeature.yaml b/firefox-ios/nimbus-features/nativeErrorPageFeature.yaml new file mode 100644 index 000000000000..c83ff6ce52e1 --- /dev/null +++ b/firefox-ios/nimbus-features/nativeErrorPageFeature.yaml @@ -0,0 +1,19 @@ +# The configuration for the nativeErrorPageFeature feature +features: + native-error-page-feature: + description: > + This feature is for managing the roll out of the native error page feature + variables: + enabled: + description: > + If true, the feature is active. + type: Boolean + default: false + + defaults: + - channel: beta + value: + enabled: false + - channel: developer + value: + enabled: false diff --git a/firefox-ios/nimbus.fml.yaml b/firefox-ios/nimbus.fml.yaml index 23d6bf97be79..8765fe727dee 100644 --- a/firefox-ios/nimbus.fml.yaml +++ b/firefox-ios/nimbus.fml.yaml @@ -26,6 +26,7 @@ include: - nimbus-features/menuRefactorFeature.yaml - nimbus-features/messagingFeature.yaml - nimbus-features/microsurveyFeature.yaml + - nimbus-features/nativeErrorPageFeature.yaml - nimbus-features/nightModeFeature.yaml - nimbus-features/onboardingFrameworkFeature.yaml - nimbus-features/reduxSearchSettingsFeature.yaml From 128da4f69c547800e5660c92e7e917d04ef17a7f Mon Sep 17 00:00:00 2001 From: dragosb01 <134391433+dragosb01@users.noreply.github.com> Date: Thu, 8 Aug 2024 19:28:08 +0300 Subject: [PATCH 064/128] Add MTE-3283 - close tracking protection menu test (#21491) --- .../Tests/FullFunctionalTestPlan.xctestplan | 1 + .../Tests/Smoketest2.xctestplan | 3 +++ .../XCUITests/TrackingProtectionTests.swift | 23 ++++++++++++++++++- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/firefox-ios/firefox-ios-tests/Tests/FullFunctionalTestPlan.xctestplan b/firefox-ios/firefox-ios-tests/Tests/FullFunctionalTestPlan.xctestplan index 668f2af06da9..23695ca0e8e9 100644 --- a/firefox-ios/firefox-ios-tests/Tests/FullFunctionalTestPlan.xctestplan +++ b/firefox-ios/firefox-ios-tests/Tests/FullFunctionalTestPlan.xctestplan @@ -158,6 +158,7 @@ "TopTabsTestIphone\/testSwitchBetweenTabsNoPrivatePrivateToastButton()", "TopTabsTestIphone\/testSwitchBetweenTabsToastButton()", "TrackingProtectionTests\/testEnableDisableTPforSite()", + "TrackingProtectionTests\/testStandardProtectionLevel()", "TrackingProtectionTests\/testTrackingProtection()", "URLValidationTests", "ZoomingTests\/testZommingActions()", diff --git a/firefox-ios/firefox-ios-tests/Tests/Smoketest2.xctestplan b/firefox-ios/firefox-ios-tests/Tests/Smoketest2.xctestplan index 4a5a6d213ff7..41e0cd6d0ddb 100644 --- a/firefox-ios/firefox-ios-tests/Tests/Smoketest2.xctestplan +++ b/firefox-ios/firefox-ios-tests/Tests/Smoketest2.xctestplan @@ -125,7 +125,10 @@ "TopTabsTestIpad", "TrackingProtectionTests\/testBasicMoreInfo()", "TrackingProtectionTests\/testETPLockMenu()", + "TrackingProtectionTests\/testLockIconCloseMenu()", + "TrackingProtectionTests\/testLockIconMenu()", "TrackingProtectionTests\/testLockIconSecureConnection()", + "TrackingProtectionTests\/testProtectionLevelMoreInfoMenu()", "URLValidationTests", "UrlBarTests", "WhatsNewTest", diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/TrackingProtectionTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/TrackingProtectionTests.swift index f7103eca67b5..c7d3aeda3e00 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/TrackingProtectionTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/TrackingProtectionTests.swift @@ -148,7 +148,7 @@ class TrackingProtectionTests: BaseTestCase { // https://mozilla.testrail.io/index.php?/cases/view/2307061 func testLockIconSecureConnection() { - navigator.openURL("https://www.Mozilla.org") + navigator.openURL("https://www.mozilla.org") waitUntilPageLoad() // iOS 15 displays a toast for the paste. The toast may cover areas to be // tapped in the next step. @@ -178,4 +178,25 @@ class TrackingProtectionTests: BaseTestCase { mozWaitForElementToExist(app.staticTexts.elementContainingText("Firefox has not connected to this website.")) XCTAssertEqual(app.buttons[AccessibilityIdentifiers.Toolbar.trackingProtection].label, "Connection not secure") } + + // https://mozilla.testrail.io/index.php?/cases/view/2693741 + func testLockIconCloseMenu() { + navigator.openURL("https://www.mozilla.org") + waitUntilPageLoad() + // iOS 15 displays a toast for the paste. The toast may cover areas to be + // tapped in the next step. + if #unavailable(iOS 16) { + sleep(2) + } + // Tap "Secure connection" + navigator.nowAt(BrowserTab) + navigator.goto(TrackingProtectionContextMenuDetails) + mozWaitForElementToExist(app.staticTexts["Secure connection"]) + if iPad() { + app.popovers.scrollViews.buttons.element(boundBy: 2).tap() + } else { + app.buttons["Close"].tap() + } + mozWaitForElementToNotExist(app.staticTexts["Secure connection"]) + } } From 3abc2709c80fde6de612678a9da9d79d8ad1f7ed Mon Sep 17 00:00:00 2001 From: mattreaganmozilla <145381717+mattreaganmozilla@users.noreply.github.com> Date: Thu, 8 Aug 2024 16:18:25 -0700 Subject: [PATCH 065/128] Bugfix FXIOS-9406 Fix intermittent blank homepage (#21496) * [9406] Remove use of Actor for tab session store. This fixes an issue causing blank homepages due to our use of an async Task in the selectTab code. * [9406] Remove unnecessary task * [9406] Remove redundant delegate callback that was added in previous workaround * [9406] Unit test fixes * [9406] Fix unit tests --- .../TabDataStore/TabSessionStore.swift | 15 +++++--- .../TabSessionStoreTests.swift | 16 ++++----- .../TabManagerImplementation.swift | 36 +++++-------------- .../Mocks/MockTabSessionStore.swift | 8 ++--- 4 files changed, 30 insertions(+), 45 deletions(-) diff --git a/BrowserKit/Sources/TabDataStore/TabSessionStore.swift b/BrowserKit/Sources/TabDataStore/TabSessionStore.swift index 4e15de0cd2ba..59ce84658605 100644 --- a/BrowserKit/Sources/TabDataStore/TabSessionStore.swift +++ b/BrowserKit/Sources/TabDataStore/TabSessionStore.swift @@ -10,21 +10,22 @@ public protocol TabSessionStore { /// - Parameters: /// - tabID: an ID that uniquely identifies the tab /// - sessionData: the data associated with a session, encoded as a Data object - func saveTabSession(tabID: UUID, sessionData: Data) async + func saveTabSession(tabID: UUID, sessionData: Data) /// Fetches the session data associated with a tab /// - Parameter tabID: an ID that uniquely identifies the tab /// - Returns: the data associated with a session, encoded as a Data object - func fetchTabSession(tabID: UUID) async -> Data? + func fetchTabSession(tabID: UUID) -> Data? /// Cleans up any tab session data files for tabs that are no longer open. func deleteUnusedTabSessionData(keeping: [UUID]) async } -public actor DefaultTabSessionStore: TabSessionStore { +public class DefaultTabSessionStore: TabSessionStore { let fileManager: TabFileManager let logger: Logger let filePrefix = "tab-" + private let lock = NSRecursiveLock() public init(fileManager: TabFileManager = DefaultTabFileManager(), logger: Logger = DefaultLogger.shared) { @@ -32,7 +33,7 @@ public actor DefaultTabSessionStore: TabSessionStore { self.logger = logger } - public func saveTabSession(tabID: UUID, sessionData: Data) async { + public func saveTabSession(tabID: UUID, sessionData: Data) { guard let directory = fileManager.tabSessionDataDirectory() else { return } if !fileManager.fileExists(atPath: directory) { @@ -41,6 +42,8 @@ public actor DefaultTabSessionStore: TabSessionStore { let path = directory.appendingPathComponent(filePrefix + tabID.uuidString) do { + lock.lock() + defer { lock.unlock() } try sessionData.write(to: path, options: .atomicWrite) } catch { logger.log("Failed to save session data with error: \(error.localizedDescription)", @@ -49,11 +52,13 @@ public actor DefaultTabSessionStore: TabSessionStore { } } - public func fetchTabSession(tabID: UUID) async -> Data? { + public func fetchTabSession(tabID: UUID) -> Data? { guard let path = fileManager.tabSessionDataDirectory()?.appendingPathComponent(filePrefix + tabID.uuidString) else { return nil } do { + lock.lock() + defer { lock.unlock() } return try Data(contentsOf: path) } catch { logger.log("Failed to decode session data with error: \(error.localizedDescription)", diff --git a/BrowserKit/Tests/TabDataStoreTests/TabSessionStoreTests.swift b/BrowserKit/Tests/TabDataStoreTests/TabSessionStoreTests.swift index 2967077eb662..c7f23ec9cbc8 100644 --- a/BrowserKit/Tests/TabDataStoreTests/TabSessionStoreTests.swift +++ b/BrowserKit/Tests/TabDataStoreTests/TabSessionStoreTests.swift @@ -21,24 +21,24 @@ final class TabSessionStoreTests: XCTestCase { // MARK: Save - func testSaveWithoutDirectory() async { + func testSaveWithoutDirectory() { let subject = createSubject() let uuid = UUID() let dataFile = Data(count: 100) - await subject.saveTabSession(tabID: uuid, sessionData: dataFile) + subject.saveTabSession(tabID: uuid, sessionData: dataFile) XCTAssertEqual(mockFileManager.tabSessionDataDirectoryCalledCount, 1) XCTAssertEqual(mockFileManager.fileExistsCalledCount, 0) XCTAssertEqual(mockFileManager.createDirectoryAtPathCalledCount, 0) } - func testSaveTabSession() async { + func testSaveTabSession() { let subject = createSubject() let uuid = UUID() let dataFile = Data(count: 100) mockFileManager.primaryDirectoryURL = URL(string: "some/directory") mockFileManager.fileExists = false - await subject.saveTabSession(tabID: uuid, sessionData: dataFile) + subject.saveTabSession(tabID: uuid, sessionData: dataFile) XCTAssertEqual(mockFileManager.tabSessionDataDirectoryCalledCount, 1) XCTAssertEqual(mockFileManager.fileExistsCalledCount, 1) @@ -47,21 +47,21 @@ final class TabSessionStoreTests: XCTestCase { // MARK: Fetch - func testFetchTabSessionWithoutDirectory() async { + func testFetchTabSessionWithoutDirectory() { let subject = createSubject() let uuid = UUID() - _ = await subject.fetchTabSession(tabID: uuid) + _ = subject.fetchTabSession(tabID: uuid) XCTAssertEqual(mockFileManager.tabSessionDataDirectoryCalledCount, 1) } - func testFetchTabSession() async { + func testFetchTabSession() { let subject = createSubject() let uuid = UUID() mockFileManager.primaryDirectoryURL = URL(string: "some/directory") - _ = await subject.fetchTabSession(tabID: uuid) + _ = subject.fetchTabSession(tabID: uuid) XCTAssertEqual(mockFileManager.tabSessionDataDirectoryCalledCount, 1) } diff --git a/firefox-ios/Client/TabManagement/TabManagerImplementation.swift b/firefox-ios/Client/TabManagement/TabManagerImplementation.swift index 24f08fb9441a..acd41512462c 100644 --- a/firefox-ios/Client/TabManagement/TabManagerImplementation.swift +++ b/firefox-ios/Client/TabManagement/TabManagerImplementation.swift @@ -308,9 +308,7 @@ class TabManagerImplementation: LegacyTabManager, Notifiable, WindowSimpleTabsPr let tabID = UUID(uuidString: tab.tabUUID) else { return } - Task { - await self.tabSessionStore.saveTabSession(tabID: tabID, sessionData: tabSession) - } + self.tabSessionStore.saveTabSession(tabID: tabID, sessionData: tabSession) } private func saveAllTabData() { @@ -360,15 +358,13 @@ class TabManagerImplementation: LegacyTabManager, Notifiable, WindowSimpleTabsPr preserveTabs() - Task(priority: .high) { - var sessionData: Data? - if !tab.isFxHomeTab { - sessionData = await tabSessionStore.fetchTabSession(tabID: tabUUID) - } - await selectTabWithSession(tab: tab, - previous: previous, - sessionData: sessionData) + var sessionData: Data? + if !tab.isFxHomeTab { + sessionData = tabSessionStore.fetchTabSession(tabID: tabUUID) } + selectTabWithSession(tab: tab, + previous: previous, + sessionData: sessionData) // Default to false if the feature flag is not enabled var isPrivate = false @@ -436,26 +432,10 @@ class TabManagerImplementation: LegacyTabManager, Notifiable, WindowSimpleTabsPr store.dispatch(action) } - @MainActor private func selectTabWithSession(tab: Tab, previous: Tab?, sessionData: Data?) { + assert(Thread.isMainThread, "Currently expected to be called only on main thread.") selectedTab?.createWebview(with: sessionData) selectedTab?.lastExecutedTime = Date.now() - - // [FXIOS-9785 Note 1] Workaround to resolve Aug 7, 2024 incident (PR #21486) - // NOTE: This needs more work because the change from PR #21328 fixed another issue, - // and thus couldn't be completely rolled back. - // However, now we are repeating this delegate notification which is less than ideal and may have unexpected - // consequences. - // See ticket for more information. - // Broadcast updates for any listeners - delegates.forEach { - $0.get()?.tabManager( - self, - didSelectedTabChange: tab, - previous: previous, - isRestoring: !tabRestoreHasFinished - ) - } } // MARK: - Screenshots diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/TabManagement/Mocks/MockTabSessionStore.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/TabManagement/Mocks/MockTabSessionStore.swift index 5f4a04301a4a..bd7c16c091b6 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/TabManagement/Mocks/MockTabSessionStore.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/TabManagement/Mocks/MockTabSessionStore.swift @@ -10,17 +10,17 @@ class MockTabSessionStore: TabSessionStore { var tabID: UUID? var sessionData: Data? - func saveTabSession(tabID: UUID, sessionData: Data) async { + func saveTabSession(tabID: UUID, sessionData: Data) { saveTabSessionCallCount += 1 self.tabID = tabID self.sessionData = sessionData } - func fetchTabSession(tabID: UUID) async -> Data? { + func fetchTabSession(tabID: UUID) -> Data? { return Data() } - func clearAllData() async {} + func clearAllData() {} - func deleteUnusedTabSessionData(keeping: [UUID]) async {} + func deleteUnusedTabSessionData(keeping: [UUID]) {} } From 718edb4d4db5d4f5ad3e210ec8cdcb544fcc140d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 9 Aug 2024 10:25:15 +0200 Subject: [PATCH 066/128] Auto update SPM with latest rust-component release 131.0.20240808050223 (#21494) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- firefox-ios/Client.xcodeproj/project.pbxproj | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- focus-ios/Blockzilla.xcodeproj/project.pbxproj | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/firefox-ios/Client.xcodeproj/project.pbxproj b/firefox-ios/Client.xcodeproj/project.pbxproj index b81afb3a616d..02dfa6b09a5a 100644 --- a/firefox-ios/Client.xcodeproj/project.pbxproj +++ b/firefox-ios/Client.xcodeproj/project.pbxproj @@ -23129,7 +23129,7 @@ repositoryURL = "https://github.com/mozilla/rust-components-swift.git"; requirement = { kind = exactVersion; - version = 131.0.20240806050256; + version = 131.0.20240808050223; }; }; 435C85EE2788F4D00072B526 /* XCRemoteSwiftPackageReference "glean-swift" */ = { diff --git a/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index fe51540c1b44..61409fc51c43 100644 --- a/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -95,8 +95,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/mozilla/rust-components-swift.git", "state" : { - "revision" : "842e406e43184710547089a318af8e55fbb6e436", - "version" : "131.0.20240806050256" + "revision" : "f04ad3ebdca06c93e14091efa7756473adb7c51a", + "version" : "131.0.20240808050223" } }, { diff --git a/focus-ios/Blockzilla.xcodeproj/project.pbxproj b/focus-ios/Blockzilla.xcodeproj/project.pbxproj index 13e10dc59a51..a92134818366 100644 --- a/focus-ios/Blockzilla.xcodeproj/project.pbxproj +++ b/focus-ios/Blockzilla.xcodeproj/project.pbxproj @@ -7159,7 +7159,7 @@ repositoryURL = "https://github.com/mozilla/rust-components-swift"; requirement = { kind = exactVersion; - version = 131.0.20240806050256; + version = 131.0.20240808050223; }; }; 8A0E7F2C2BA0F0E0006BC6B6 /* XCRemoteSwiftPackageReference "Fuzi" */ = { diff --git a/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 3b53873a5ad5..bb14bbd50f51 100644 --- a/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -51,8 +51,8 @@ "repositoryURL": "https://github.com/mozilla/rust-components-swift", "state": { "branch": null, - "revision": "842e406e43184710547089a318af8e55fbb6e436", - "version": "131.0.20240806050256" + "revision": "f04ad3ebdca06c93e14091efa7756473adb7c51a", + "version": "131.0.20240808050223" } }, { From c28ea86545cb37962b36cf928efd88e6854814bc Mon Sep 17 00:00:00 2001 From: Litianu Razvan Date: Fri, 9 Aug 2024 12:13:11 +0300 Subject: [PATCH 067/128] FXIOS-9654 #21256 Country set to Afghanistan after updating any field (#21493) --- .../Client/Frontend/Autofill/Address/AddressListViewModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firefox-ios/Client/Frontend/Autofill/Address/AddressListViewModel.swift b/firefox-ios/Client/Frontend/Autofill/Address/AddressListViewModel.swift index 78233fab93bc..daed44531b3d 100644 --- a/firefox-ios/Client/Frontend/Autofill/Address/AddressListViewModel.swift +++ b/firefox-ios/Client/Frontend/Autofill/Address/AddressListViewModel.swift @@ -135,12 +135,12 @@ final class AddressListViewModel: ObservableObject, FeatureFlaggable { } func saveEditButtonTap() { - toggleEditMode() saveAction? { [weak self] updatedAddress in guard let self else { return } guard case .edit(let currentAddress) = self.destination else { return } self.updateLocal(id: currentAddress.guid, updatedAddress: updatedAddress) } + toggleEditMode() } private func updateLocal(id: String, updatedAddress: UpdatableAddressFields) { From 540b2593b22def54b684e43e0347761974fc20f8 Mon Sep 17 00:00:00 2001 From: Cyndi Chin Date: Fri, 9 Aug 2024 13:59:35 -0400 Subject: [PATCH 068/128] Bugfix FXIOS-9351 [Unit Tests] Add more timeout to ContentBlockerTests (#21483) --- .../Tests/ClientTests/ContentBlockerTests.swift | 10 ++++------ .../firefox-ios-tests/Tests/UnitTest.xctestplan | 1 + 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/ContentBlockerTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/ContentBlockerTests.swift index 14a4fd31e687..56f5e2c978e8 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/ContentBlockerTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/ContentBlockerTests.swift @@ -20,12 +20,10 @@ final class ContentBlockerTests: XCTestCase { } func testCompileListsNotInStore_callsCompletionHandlerSuccessfully() { - measure { - let expectation = XCTestExpectation() - ContentBlocker.shared.compileListsNotInStore { - expectation.fulfill() - } - wait(for: [expectation], timeout: 1.0) + let expectation = XCTestExpectation() + ContentBlocker.shared.compileListsNotInStore { + expectation.fulfill() } + wait(for: [expectation], timeout: 5.0) } } diff --git a/firefox-ios/firefox-ios-tests/Tests/UnitTest.xctestplan b/firefox-ios/firefox-ios-tests/Tests/UnitTest.xctestplan index 6b1d809ddb5f..7e648b90ce68 100644 --- a/firefox-ios/firefox-ios-tests/Tests/UnitTest.xctestplan +++ b/firefox-ios/firefox-ios-tests/Tests/UnitTest.xctestplan @@ -94,6 +94,7 @@ }, { "skippedTests" : [ + "ContentBlockerTests", "ETPCoverSheetTests", "GleanPlumbMessageManagerTests\/testManagerOnMessagePressed_withMalformedURL()", "HistoryHighlightsDataAdaptorTests", From 3499e561b58880b5ded748f9407933ef79f8bbd4 Mon Sep 17 00:00:00 2001 From: Isabella Date: Fri, 9 Aug 2024 13:50:03 -0600 Subject: [PATCH 069/128] [FXIOS-9789] Refactor the TabManagerDelegate methods to take a non-optional selectedTab. Refactor naming for clarity. Add asserts for critical code paths. (#21507) --- .../Views/BrowserViewController.swift | 114 +++++++++--------- .../Frontend/Browser/TabDisplayManager.swift | 15 +-- .../Browser/TabScrollController.swift | 3 +- .../Legacy/LegacyTabManager.swift | 5 +- firefox-ios/Client/TabManagement/Tab.swift | 6 + .../TabManagerImplementation.swift | 2 +- 6 files changed, 73 insertions(+), 72 deletions(-) diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift index fdc2e3700af7..78c2bb32806f 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift @@ -3467,104 +3467,104 @@ extension BrowserViewController: SearchViewControllerDelegate { } extension BrowserViewController: TabManagerDelegate { - func tabManager(_ tabManager: TabManager, didSelectedTabChange selected: Tab?, previous: Tab?, isRestoring: Bool) { + func tabManager(_ tabManager: TabManager, didSelectedTabChange selectedTab: Tab, previousTab: Tab?, isRestoring: Bool) { + // Failing to have a non-nil webView by this point will cause the toolbar scrolling behaviour to regress, back/foward + // buttons never to become enabled, etc. on tab restore after launch. [FXIOS-9785, FXIOS-9781] + assert(selectedTab.webView != nil, "Setup will fail if the webView is not initialized for selectedTab") + // Remove the old accessibilityLabel. Since this webview shouldn't be visible, it doesn't need it // and having multiple views with the same label confuses tests. - if let webView = previous?.webView { - webView.endEditing(true) - webView.accessibilityLabel = nil - webView.accessibilityElementsHidden = true - webView.accessibilityIdentifier = nil - webView.removeFromSuperview() + if let previousWebView = previousTab?.webView { + previousWebView.endEditing(true) + previousWebView.accessibilityLabel = nil + previousWebView.accessibilityElementsHidden = true + previousWebView.accessibilityIdentifier = nil + previousWebView.removeFromSuperview() } - if let tab = selected, previous == nil || tab.isPrivate != previous?.isPrivate { + if previousTab == nil || selectedTab.isPrivate != previousTab?.isPrivate { applyTheme() if !isToolbarRefactorEnabled { let ui: [PrivateModeUI?] = [toolbar, topTabsViewController, urlBar] - ui.forEach { $0?.applyUIMode(isPrivate: tab.isPrivate, theme: currentTheme()) } + ui.forEach { $0?.applyUIMode(isPrivate: selectedTab.isPrivate, theme: currentTheme()) } } } else { // Theme is applied to the tab and webView in the else case // because in the if block is applied already to all the tabs and web views - selected?.applyTheme(theme: currentTheme()) - selected?.webView?.applyTheme(theme: currentTheme()) + selectedTab.applyTheme(theme: currentTheme()) + selectedTab.webView?.applyTheme(theme: currentTheme()) } - if let tab = selected { - updateURLBarDisplayURL(tab) - if isToolbarRefactorEnabled, addressToolbarContainer.inOverlayMode, tab.url?.displayURL != nil { - addressToolbarContainer.leaveOverlayMode(reason: .finished, shouldCancelLoading: false) - } else if !isToolbarRefactorEnabled, urlBar.inOverlayMode, tab.url?.displayURL != nil { - urlBar.leaveOverlayMode(reason: .finished, shouldCancelLoading: false) - } + updateURLBarDisplayURL(selectedTab) + if isToolbarRefactorEnabled, addressToolbarContainer.inOverlayMode, selectedTab.url?.displayURL != nil { + addressToolbarContainer.leaveOverlayMode(reason: .finished, shouldCancelLoading: false) + } else if !isToolbarRefactorEnabled, urlBar.inOverlayMode, selectedTab.url?.displayURL != nil { + urlBar.leaveOverlayMode(reason: .finished, shouldCancelLoading: false) + } - readerModeCache = tab.isPrivate ? MemoryReaderModeCache.sharedInstance : DiskReaderModeCache.sharedInstance - if let privateModeButton = topTabsViewController?.privateModeButton, - previous != nil && previous?.isPrivate != tab.isPrivate { - privateModeButton.setSelected(tab.isPrivate, animated: true) - } - ReaderModeHandlers.readerModeCache = readerModeCache + if let privateModeButton = topTabsViewController?.privateModeButton, + previousTab != nil && previousTab?.isPrivate != selectedTab.isPrivate { + privateModeButton.setSelected(selectedTab.isPrivate, animated: true) + } + readerModeCache = selectedTab.isPrivate ? MemoryReaderModeCache.sharedInstance : DiskReaderModeCache.sharedInstance + ReaderModeHandlers.readerModeCache = readerModeCache - scrollController.tab = tab + scrollController.tab = selectedTab - if let webView = tab.webView { - webView.accessibilityLabel = .WebViewAccessibilityLabel - webView.accessibilityIdentifier = "contentView" - webView.accessibilityElementsHidden = false + if let webView = selectedTab.webView { + webView.accessibilityLabel = .WebViewAccessibilityLabel + webView.accessibilityIdentifier = "contentView" + webView.accessibilityElementsHidden = false - browserDelegate?.show(webView: webView) + browserDelegate?.show(webView: webView) - if webView.url == nil { - // The web view can go gray if it was zombified due to memory pressure. - // When this happens, the URL is nil, so try restoring the page upon selection. - tab.reload() - } + if webView.url == nil { + // The webView can go gray if it was zombified due to memory pressure. + // When this happens, the URL is nil, so try restoring the page upon selection. + selectedTab.reload() } - - // Update Fakespot sidebar if necessary - updateFakespot(tab: tab) } + // Update Fakespot sidebar if necessary + updateFakespot(tab: selectedTab) + updateTabCountUsingTabManager(tabManager) bottomContentStackView.removeAllArrangedViews() - if let bars = selected?.bars { - bars.forEach { bar in - bottomContentStackView.addArrangedViewToBottom(bar, completion: { self.view.layoutIfNeeded() }) - } + + selectedTab.bars.forEach { bar in + bottomContentStackView.addArrangedViewToBottom(bar, completion: { self.view.layoutIfNeeded() }) } - updateFindInPageVisibility(isVisible: false, tab: previous) - setupMiddleButtonStatus(isLoading: selected?.loading ?? false) + updateFindInPageVisibility(isVisible: false, tab: previousTab) + setupMiddleButtonStatus(isLoading: selectedTab.loading) - // [FXIOS-9785 Note #2] Back button can't be enabled unless the webView is already initialized if isToolbarRefactorEnabled { - dispatchBackForwardToolbarAction(selected?.canGoBack, windowUUID, .backButtonStateChanged) - dispatchBackForwardToolbarAction(selected?.canGoForward, windowUUID, .forwardButtonStateChanged) + dispatchBackForwardToolbarAction(selectedTab.canGoBack, windowUUID, .backButtonStateChanged) + dispatchBackForwardToolbarAction(selectedTab.canGoForward, windowUUID, .forwardButtonStateChanged) } else { - navigationToolbar.updateBackStatus(selected?.canGoBack ?? false) - navigationToolbar.updateForwardStatus(selected?.canGoForward ?? false) + navigationToolbar.updateBackStatus(selectedTab.canGoBack) + navigationToolbar.updateForwardStatus(selectedTab.canGoForward) } - if let url = selected?.webView?.url, !InternalURL.isValid(url: url) { + if let url = selectedTab.webView?.url, !InternalURL.isValid(url: url) { if isToolbarRefactorEnabled { - addressToolbarContainer.updateProgressBar(progress: selected?.estimatedProgress ?? 0) + addressToolbarContainer.updateProgressBar(progress: selectedTab.estimatedProgress) } else { - urlBar.updateProgressBar(Float(selected?.estimatedProgress ?? 0)) + urlBar.updateProgressBar(Float(selectedTab.estimatedProgress)) } } - if let readerMode = selected?.getContentScript(name: ReaderMode.name()) as? ReaderMode { - updateReaderModeState(for: selected, readerModeState: readerMode.state) + if let readerMode = selectedTab.getContentScript(name: ReaderMode.name()) as? ReaderMode { + updateReaderModeState(for: selectedTab, readerModeState: readerMode.state) if readerMode.state == .active { showReaderModeBar(animated: false) } else { hideReaderModeBar(animated: false) } } else { - updateReaderModeState(for: selected, readerModeState: .unavailable) + updateReaderModeState(for: selectedTab, readerModeState: .unavailable) } if topTabsVisible { @@ -3572,8 +3572,8 @@ extension BrowserViewController: TabManagerDelegate { } /// If the selectedTab is showing an error page trigger a reload - if let url = selected?.url, let internalUrl = InternalURL(url), internalUrl.isErrorPage { - selected?.reloadPage() + if let url = selectedTab.url, let internalUrl = InternalURL(url), internalUrl.isErrorPage { + selectedTab.reloadPage() return } } diff --git a/firefox-ios/Client/Frontend/Browser/TabDisplayManager.swift b/firefox-ios/Client/Frontend/Browser/TabDisplayManager.swift index edb8dc42304e..a66cc71853ce 100644 --- a/firefox-ios/Client/Frontend/Browser/TabDisplayManager.swift +++ b/firefox-ios/Client/Frontend/Browser/TabDisplayManager.swift @@ -937,19 +937,12 @@ extension LegacyTabDisplayManager: TabEventHandler { // MARK: - TabManagerDelegate extension LegacyTabDisplayManager: TabManagerDelegate { - func tabManager( - _ tabManager: TabManager, - didSelectedTabChange selected: Tab?, - previous: Tab?, - isRestoring: Bool - ) { + func tabManager(_ tabManager: TabManager, didSelectedTabChange selectedTab: Tab, previousTab: Tab?, isRestoring: Bool) { cancelDragAndGestures() - if let selected = selected { - // A tab can be re-selected during deletion - let changed = selected != previous - updateCellFor(tab: selected, selectedTabChanged: changed) - } + // A tab can be re-selected during deletion + let changedTab = selectedTab != previousTab + updateCellFor(tab: selectedTab, selectedTabChanged: changedTab) // Rather than using 'previous' Tab to deselect, just check if the selected tab // is different, and update the required cells. The refreshStore() cancels diff --git a/firefox-ios/Client/Frontend/Browser/TabScrollController.swift b/firefox-ios/Client/Frontend/Browser/TabScrollController.swift index 4a3f62799b62..b32aa73043b0 100644 --- a/firefox-ios/Client/Frontend/Browser/TabScrollController.swift +++ b/firefox-ios/Client/Frontend/Browser/TabScrollController.swift @@ -31,8 +31,9 @@ class TabScrollingController: NSObject, FeatureFlaggable, SearchBarLocationProvi } didSet { + // FXIOS-9781 This could result in scrolling not closing the toolbar + assert(scrollView != nil, "Can't set the scrollView delegate if the webView.scrollView is nil") self.scrollView?.addGestureRecognizer(panGesture) - // [FXIOS-9785 Note #3] Toolbar delegate can't be set unless the webView is already initialized scrollView?.delegate = self scrollView?.keyboardDismissMode = .onDrag configureRefreshControl(isEnabled: true) diff --git a/firefox-ios/Client/TabManagement/Legacy/LegacyTabManager.swift b/firefox-ios/Client/TabManagement/Legacy/LegacyTabManager.swift index 442af4dde7a8..da4982b03056 100644 --- a/firefox-ios/Client/TabManagement/Legacy/LegacyTabManager.swift +++ b/firefox-ios/Client/TabManagement/Legacy/LegacyTabManager.swift @@ -10,7 +10,8 @@ import Shared // MARK: - TabManagerDelegate protocol TabManagerDelegate: AnyObject { - func tabManager(_ tabManager: TabManager, didSelectedTabChange selected: Tab?, previous: Tab?, isRestoring: Bool) + // Must be called on the main thread + func tabManager(_ tabManager: TabManager, didSelectedTabChange selectedTab: Tab, previousTab: Tab?, isRestoring: Bool) func tabManager(_ tabManager: TabManager, didAddTab tab: Tab, placeNextToParentTab: Bool, isRestoring: Bool) func tabManager(_ tabManager: TabManager, didRemoveTab tab: Tab, isRestoring: Bool) @@ -21,7 +22,7 @@ protocol TabManagerDelegate: AnyObject { } extension TabManagerDelegate { - func tabManager(_ tabManager: TabManager, didSelectedTabChange selected: Tab?, previous: Tab?, isRestoring: Bool) {} + func tabManager(_ tabManager: TabManager, didSelectedTabChange selectedTab: Tab, previousTab: Tab?, isRestoring: Bool) {} func tabManager(_ tabManager: TabManager, didAddTab tab: Tab, placeNextToParentTab: Bool, isRestoring: Bool) {} func tabManager(_ tabManager: TabManager, didRemoveTab tab: Tab, isRestoring: Bool) {} diff --git a/firefox-ios/Client/TabManagement/Tab.swift b/firefox-ios/Client/TabManagement/Tab.swift index c5e3dec17d38..e93de32f1b9f 100644 --- a/firefox-ios/Client/TabManagement/Tab.swift +++ b/firefox-ios/Client/TabManagement/Tab.swift @@ -236,10 +236,16 @@ class Tab: NSObject, ThemeApplicable { } var canGoBack: Bool { + // FXIOS-9785 This could result in the back button never being enabled for restored tabs + assert(webView != nil, "We should not be trying to enable or disable the back button before the webView is set") + return webView?.canGoBack ?? false } var canGoForward: Bool { + // FXIOS-9785 This could result in the forward button never being enabled for restored tabs + assert(webView != nil, "We should not be trying to enable or disable the forward button before the webView is set") + return webView?.canGoForward ?? false } diff --git a/firefox-ios/Client/TabManagement/TabManagerImplementation.swift b/firefox-ios/Client/TabManagement/TabManagerImplementation.swift index acd41512462c..180de1aa4d84 100644 --- a/firefox-ios/Client/TabManagement/TabManagerImplementation.swift +++ b/firefox-ios/Client/TabManagement/TabManagerImplementation.swift @@ -385,7 +385,7 @@ class TabManagerImplementation: LegacyTabManager, Notifiable, WindowSimpleTabsPr $0.get()?.tabManager( self, didSelectedTabChange: tab, - previous: previous, + previousTab: previous, isRestoring: !tabRestoreHasFinished ) } From d96b0965b5c0e272874d562f2e26c8a6f4734997 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 12 Aug 2024 11:13:46 -0400 Subject: [PATCH 070/128] Localize [v131] String import 2024-08-12 (#21513) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- firefox-ios/Client.xcodeproj/project.pbxproj | 20 +++ firefox-ios/Client/hr.lproj/InfoPlist.strings | 3 + .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 6 +- .../EnhancedTrackingProtection.strings | 6 +- .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 6 +- .../EnhancedTrackingProtection.strings | 6 +- .../EnhancedTrackingProtection.strings | 6 +- .../EnhancedTrackingProtection.strings | 6 +- .../en-CA.lproj/Microsurvey.strings | 3 + .../en-CA.lproj/Toolbar.strings | 3 + .../EnhancedTrackingProtection.strings | 6 +- .../EnhancedTrackingProtection.strings | 6 +- .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 6 +- .../EnhancedTrackingProtection.strings | 6 +- .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 6 +- .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 6 +- .../Supporting Files/hr.lproj/Alerts.strings | 3 + .../hr.lproj/ContextualHints.strings | 3 + .../hr.lproj/CredentialProvider.strings | 9 ++ .../hr.lproj/Credentials.strings | 6 + .../hr.lproj/CustomizeFirefoxHome.strings | 3 + .../EnhancedTrackingProtection.strings | 31 ++++- .../hr.lproj/FirefoxHomepage.strings | 6 + .../hr.lproj/Microsurvey.strings | 3 + .../hr.lproj/Onboarding.strings | 39 ++++++ .../hr.lproj/PasswordAutofill.strings | 15 ++ .../Supporting Files/hr.lproj/QRCode.strings | 3 + .../hr.lproj/RememberCard.strings | 9 ++ .../hr.lproj/ResearchSurface.strings | 9 ++ .../hr.lproj/ScanQRCode.strings | 9 ++ .../hr.lproj/SearchHeaderTitle.strings | 3 + .../hr.lproj/SelectCreditCard.strings | 2 +- .../hr.lproj/Settings.strings | 39 ++++++ .../Supporting Files/hr.lproj/Share.strings | 6 + .../hr.lproj/Shopping.strings | 129 ++++++++++++++++++ .../hr.lproj/TabToolbar.strings | 3 + .../hr.lproj/TabsTray.strings | 3 + .../Supporting Files/hr.lproj/Toolbar.strings | 3 + .../hr.lproj/ToolbarLocation.strings | 6 + .../Supporting Files/hr.lproj/Upgrade.strings | 12 ++ .../EnhancedTrackingProtection.strings | 6 +- .../hu.lproj/EditAddress.strings | 6 + .../EnhancedTrackingProtection.strings | 25 +++- .../hu.lproj/Microsurvey.strings | 3 + .../Supporting Files/hu.lproj/Toolbar.strings | 6 + .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 6 +- .../EnhancedTrackingProtection.strings | 6 +- .../EnhancedTrackingProtection.strings | 6 +- .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 6 +- .../EnhancedTrackingProtection.strings | 6 +- .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 6 +- .../nn.lproj/ScanQRCode.strings | 2 +- .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 6 +- .../EnhancedTrackingProtection.strings | 6 +- .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 6 +- .../EnhancedTrackingProtection.strings | 6 +- .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 6 +- .../sq.lproj/Microsurvey.strings | 3 + .../Supporting Files/sq.lproj/Toolbar.strings | 3 + .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 6 +- .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 6 +- .../EnhancedTrackingProtection.strings | 6 +- .../EnhancedTrackingProtection.strings | 6 +- .../EnhancedTrackingProtection.strings | 6 +- .../zh-CN.lproj/Microsurvey.strings | 3 + .../zh-CN.lproj/Toolbar.strings | 3 + .../EnhancedTrackingProtection.strings | 3 +- .../Shared/hr.lproj/Default Browser.strings | 9 ++ .../Shared/hr.lproj/Localizable.strings | 21 +++ 88 files changed, 597 insertions(+), 104 deletions(-) create mode 100644 firefox-ios/Shared/Supporting Files/hr.lproj/ContextualHints.strings create mode 100644 firefox-ios/Shared/Supporting Files/hr.lproj/Credentials.strings create mode 100644 firefox-ios/Shared/Supporting Files/hr.lproj/PasswordAutofill.strings create mode 100644 firefox-ios/Shared/Supporting Files/hr.lproj/QRCode.strings create mode 100644 firefox-ios/Shared/Supporting Files/hr.lproj/ResearchSurface.strings create mode 100644 firefox-ios/Shared/Supporting Files/hr.lproj/ScanQRCode.strings create mode 100644 firefox-ios/Shared/Supporting Files/hr.lproj/Share.strings create mode 100644 firefox-ios/Shared/Supporting Files/hr.lproj/TabToolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/hr.lproj/ToolbarLocation.strings create mode 100644 firefox-ios/Shared/Supporting Files/hu.lproj/Toolbar.strings diff --git a/firefox-ios/Client.xcodeproj/project.pbxproj b/firefox-ios/Client.xcodeproj/project.pbxproj index 02dfa6b09a5a..1cfa2775f550 100644 --- a/firefox-ios/Client.xcodeproj/project.pbxproj +++ b/firefox-ios/Client.xcodeproj/project.pbxproj @@ -5046,6 +5046,15 @@ 43C993B42B30609900C813F4 /* ia */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ia; path = ia.lproj/FirefoxLogins.strings; sourceTree = ""; }; 43C993B52B30609900C813F4 /* ia */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ia; path = ia.lproj/LoginsHelper.strings; sourceTree = ""; }; 43C9AE552ACADF5500159B34 /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/Share.strings; sourceTree = ""; }; + 43C9CD422C6A26D8002F86B4 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/ContextualHints.strings; sourceTree = ""; }; + 43C9CD432C6A26D9002F86B4 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/Credentials.strings; sourceTree = ""; }; + 43C9CD442C6A26D9002F86B4 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/PasswordAutofill.strings; sourceTree = ""; }; + 43C9CD452C6A26D9002F86B4 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/QRCode.strings; sourceTree = ""; }; + 43C9CD462C6A26D9002F86B4 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/ResearchSurface.strings; sourceTree = ""; }; + 43C9CD472C6A26D9002F86B4 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/ScanQRCode.strings; sourceTree = ""; }; + 43C9CD482C6A26D9002F86B4 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/Share.strings; sourceTree = ""; }; + 43C9CD492C6A26D9002F86B4 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/TabToolbar.strings; sourceTree = ""; }; + 43C9CD4A2C6A26D9002F86B4 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/ToolbarLocation.strings; sourceTree = ""; }; 43CA0389293E0AB30056EF4B /* eu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eu; path = eu.lproj/Alerts.strings; sourceTree = ""; }; 43CA038A293E0AB30056EF4B /* eu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eu; path = eu.lproj/SearchHeaderTitle.strings; sourceTree = ""; }; 43CA038B293E0AB30056EF4B /* eu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eu; path = eu.lproj/TabsTray.strings; sourceTree = ""; }; @@ -5460,6 +5469,7 @@ 43E69EAF254D064E00B591C2 /* SimpleTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleTab.swift; sourceTree = ""; }; 43E6BE132C57AF7600C2152C /* bs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bs; path = bs.lproj/ScanQRCode.strings; sourceTree = ""; }; 43E6BE152C57AF7600C2152C /* bs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bs; path = bs.lproj/Toolbar.strings; sourceTree = ""; }; + 43E7071E2C6A26FC00A29AE4 /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/Toolbar.strings; sourceTree = ""; }; 43E730C22C20522100892124 /* is */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = is; path = is.lproj/ActivityStream.strings; sourceTree = ""; }; 43E730C32C20522100892124 /* is */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = is; path = is.lproj/AddressToolbar.strings; sourceTree = ""; }; 43E730C42C20522100892124 /* is */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = is; path = is.lproj/EnhancedTrackingProtection.strings; sourceTree = ""; }; @@ -16934,6 +16944,7 @@ 439761772A0BCB860062C60C /* gl */, 4364EA9C2B1DE9FB003A1240 /* bs */, 43EB5FAE2B2728080063D23E /* ug */, + 43C9CD4A2C6A26D9002F86B4 /* hr */, ); name = ToolbarLocation.strings; sourceTree = ""; @@ -17520,6 +17531,7 @@ 431B95FA2C453A89003B17BF /* en-CA */, 4375F0E52C453BC4001F3A55 /* hu */, 437E67452C57B4AB00A8791A /* th */, + 43C9CD452C6A26D9002F86B4 /* hr */, ); name = QRCode.strings; sourceTree = ""; @@ -17730,6 +17742,7 @@ 4364EA932B1DE9FB003A1240 /* bs */, 43EB5FA52B2728080063D23E /* ug */, 437E34352C3C03870025BFA9 /* ro */, + 43C9CD462C6A26D9002F86B4 /* hr */, ); name = ResearchSurface.strings; sourceTree = ""; @@ -18138,6 +18151,7 @@ 4357B4922C168FF1003518CF /* su */, 43CCB4D72C32C527001F2EBB /* ca */, 43EC79AB2C3C00BF00519D98 /* es-MX */, + 43C9CD442C6A26D9002F86B4 /* hr */, ); name = PasswordAutofill.strings; sourceTree = ""; @@ -18203,6 +18217,7 @@ 43B890FA2C32C60A0049F033 /* es-MX */, 43D79A832C4539FD0057C720 /* br */, 4361DF2A2C453DB200CE1295 /* sat-Olck */, + 43C9CD422C6A26D8002F86B4 /* hr */, ); name = ContextualHints.strings; sourceTree = ""; @@ -18333,6 +18348,7 @@ 43CCB4D12C32C526001F2EBB /* ca */, 43B890FC2C32C60B0049F033 /* es-MX */, 433020F72C57B40600AF5EE2 /* sat-Olck */, + 43C9CD432C6A26D9002F86B4 /* hr */, ); name = Credentials.strings; sourceTree = ""; @@ -18526,6 +18542,7 @@ 43F851162C168FBB00FA74A7 /* si */, 4357B4952C168FF1003518CF /* su */, 43CCB4D92C32C527001F2EBB /* ca */, + 43C9CD492C6A26D9002F86B4 /* hr */, ); name = TabToolbar.strings; sourceTree = ""; @@ -18583,6 +18600,7 @@ 43B3869C2C57B446007728B6 /* sl */, 437E67462C57B4AB00A8791A /* th */, 433D64C62C60EE1100CEC389 /* nb */, + 43C9CD472C6A26D9002F86B4 /* hr */, ); name = ScanQRCode.strings; sourceTree = ""; @@ -18912,6 +18930,7 @@ 43D74AE12BCD4286000D0251 /* en-CA */, 4357B4932C168FF1003518CF /* su */, 43EC79AD2C3C00BF00519D98 /* es-MX */, + 43C9CD482C6A26D9002F86B4 /* hr */, ); name = Share.strings; sourceTree = ""; @@ -19107,6 +19126,7 @@ 4304EDF32C60EABA00F3C9DE /* cy */, 43E0BE422C60EC4C004FED65 /* hr */, 433D64C72C60EE1100CEC389 /* nb */, + 43E7071E2C6A26FC00A29AE4 /* hu */, ); name = Toolbar.strings; sourceTree = ""; diff --git a/firefox-ios/Client/hr.lproj/InfoPlist.strings b/firefox-ios/Client/hr.lproj/InfoPlist.strings index 38330417b1dd..162b57994d64 100644 --- a/firefox-ios/Client/hr.lproj/InfoPlist.strings +++ b/firefox-ios/Client/hr.lproj/InfoPlist.strings @@ -7,6 +7,9 @@ /* Privacy - Camera Usage Description */ "NSCameraUsageDescription" = "Ovo vam omogućava slikanje i prijenos fotografija."; +/* Privacy - Face ID Usage Description */ +"NSFaceIDUsageDescription" = "Firefox zahtijeva Face ID za pristup tvojim spremljenim lozinkama i načinima plaćanja."; + /* Privacy - Location When In Use Usage Description */ "NSLocationWhenInUseUsageDescription" = "Web stranice koje posjećuješ mogu zatražiti tvoju lokaciju."; diff --git a/firefox-ios/Shared/Supporting Files/bs.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/bs.lproj/EnhancedTrackingProtection.strings index 5689d9147d96..d18a0b0b9e20 100644 --- a/firefox-ios/Shared/Supporting Files/bs.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/bs.lproj/EnhancedTrackingProtection.strings @@ -31,8 +31,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Programi za praćenje na društvenim mrežama: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Tragači blokirani: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/ca.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/ca.lproj/EnhancedTrackingProtection.strings index 762f0e10c271..d67a4d1c475e 100644 --- a/firefox-ios/Shared/Supporting Files/ca.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/ca.lproj/EnhancedTrackingProtection.strings @@ -31,8 +31,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Elements de seguiment de xarxes socials: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Elements de seguiment blocats: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/co.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/co.lproj/EnhancedTrackingProtection.strings index 36a2948be7e2..4feb67ce2738 100644 --- a/firefox-ios/Shared/Supporting Files/co.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/co.lproj/EnhancedTrackingProtection.strings @@ -31,8 +31,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Perseguitatori di rete suciale : %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Perseguitatori bluccati : %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/cs.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/cs.lproj/EnhancedTrackingProtection.strings index 7d745c23a7f8..e84882d3b573 100644 --- a/firefox-ios/Shared/Supporting Files/cs.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/cs.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Spojení není zabezpečené"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Nebyly nalezeny žádné sledovací prvky"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Sledovací cross-site cookies: %@"; @@ -31,8 +34,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Sledovací prvky sociálních sítí: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Zablokované sledovací prvky: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/cy.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/cy.lproj/EnhancedTrackingProtection.strings index 6dc710435931..1ba16ceece97 100644 --- a/firefox-ios/Shared/Supporting Files/cy.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/cy.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Nid yw’r cysylltiad yn ddiogel"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Heb ganfod tracwyr"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Cwcis tracio traws-gwefan: %@"; @@ -31,8 +34,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Tracwyr cyfryngau cymdeithasol: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Tracwyr wedi'u rhwystro: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/da.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/da.lproj/EnhancedTrackingProtection.strings index e5f81a15b529..0dcc6696114b 100644 --- a/firefox-ios/Shared/Supporting Files/da.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/da.lproj/EnhancedTrackingProtection.strings @@ -31,8 +31,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Sporing via sociale medier: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Forsøg på sporing blokeret: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/de.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/de.lproj/EnhancedTrackingProtection.strings index 870a5483ade0..6a5e61cee85e 100644 --- a/firefox-ios/Shared/Supporting Files/de.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/de.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Verbindung nicht sicher"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Keine Tracker gefunden"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Cookies zur seitenübergreifenden Aktivitätenverfolgung: %@"; @@ -31,8 +34,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Skripte zur Aktivitätenverfolgung durch soziale Netzwerke: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Blockierte Tracker: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/dsb.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/dsb.lproj/EnhancedTrackingProtection.strings index f24d67961a7c..7f70e84de583 100644 --- a/firefox-ios/Shared/Supporting Files/dsb.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/dsb.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Zwisk njejo wěsty"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Žedne pśeslědowaki namakane"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Sedła pśesegujucy slědujucy cookie: %@"; @@ -31,8 +34,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Pśeslědowaki socialnych medijow: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Pśeslědowaki blokěrowane: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/el.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/el.lproj/EnhancedTrackingProtection.strings index 4469538291b3..d89bd44bd3ab 100644 --- a/firefox-ios/Shared/Supporting Files/el.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/el.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Μη ασφαλής σύνδεση"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Δεν βρέθηκαν ιχνηλάτες"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Cookie καταγραφής μεταξύ ιστοτόπων: %@"; @@ -31,8 +34,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Ιχνηλάτες μέσων κοινωνικής δικτύωσης: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Αποκλεισμένοι ιχνηλάτες: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/en-CA.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/en-CA.lproj/EnhancedTrackingProtection.strings index 327625e3ed14..6cce6fc2d9ac 100644 --- a/firefox-ios/Shared/Supporting Files/en-CA.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/en-CA.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Connection not secure"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "No trackers found"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Cross-site tracking cookies: %@"; @@ -31,8 +34,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Social media trackers: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Trackers blocked: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/en-CA.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/en-CA.lproj/Microsurvey.strings index 9806c1dfb754..aa8a84e71e1f 100644 --- a/firefox-ios/Shared/Supporting Files/en-CA.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/en-CA.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Unselected"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Survey"; + diff --git a/firefox-ios/Shared/Supporting Files/en-CA.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/en-CA.lproj/Toolbar.strings index 7784884c18f8..e3c35a24ad4b 100644 --- a/firefox-ios/Shared/Supporting Files/en-CA.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/en-CA.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "New Tab"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Close This Tab"; + diff --git a/firefox-ios/Shared/Supporting Files/en-GB.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/en-GB.lproj/EnhancedTrackingProtection.strings index 42cc67390eb1..553df1876512 100644 --- a/firefox-ios/Shared/Supporting Files/en-GB.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/en-GB.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Connection not secure"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "No trackers found"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Cross-site tracking cookies: %@"; @@ -31,8 +34,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Social media trackers: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Trackers blocked: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/en-US.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/en-US.lproj/EnhancedTrackingProtection.strings index 327625e3ed14..6cce6fc2d9ac 100644 --- a/firefox-ios/Shared/Supporting Files/en-US.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/en-US.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Connection not secure"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "No trackers found"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Cross-site tracking cookies: %@"; @@ -31,8 +34,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Social media trackers: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Trackers blocked: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/eo.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/eo.lproj/EnhancedTrackingProtection.strings index 682177812f82..46aad18b23d1 100644 --- a/firefox-ios/Shared/Supporting Files/eo.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/eo.lproj/EnhancedTrackingProtection.strings @@ -22,8 +22,7 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Nesekura konekto"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Blokitaj spuriloj: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/es-AR.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/es-AR.lproj/EnhancedTrackingProtection.strings index e85ec2637be5..1ad8a0417440 100644 --- a/firefox-ios/Shared/Supporting Files/es-AR.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/es-AR.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Conexión insegura"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "No se encontraron rastreadores"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Cookies de rastreo de sitios cruzados: %@"; @@ -31,8 +34,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Rastreadores de redes sociales: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Rastreadores bloqueados: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/es-CL.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/es-CL.lproj/EnhancedTrackingProtection.strings index 3753514e7f9e..eca8546e3277 100644 --- a/firefox-ios/Shared/Supporting Files/es-CL.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/es-CL.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Conexión no segura"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "No se encontraron rastreadores"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Cookies de rastreo de sitios cruzados: %@"; @@ -31,8 +34,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Rastreadores de redes sociales: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Rastreadores bloqueados: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/es.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/es.lproj/EnhancedTrackingProtection.strings index b2c1b44a8624..53785323b4d8 100644 --- a/firefox-ios/Shared/Supporting Files/es.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/es.lproj/EnhancedTrackingProtection.strings @@ -31,8 +31,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Rastreadores de redes sociales: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Rastreadores bloqueados: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/eu.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/eu.lproj/EnhancedTrackingProtection.strings index 5aad23d451a1..c4ff339d6544 100644 --- a/firefox-ios/Shared/Supporting Files/eu.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/eu.lproj/EnhancedTrackingProtection.strings @@ -31,8 +31,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Sare sozialetako jarraipen-elementuak: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Blokeatutako jarraipen-elementuak: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/fi.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/fi.lproj/EnhancedTrackingProtection.strings index 7b696a6129c5..8856d3e79ed0 100644 --- a/firefox-ios/Shared/Supporting Files/fi.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/fi.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Yhteys ei ole suojattu"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Seuraimia ei löytynyt"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Sivustorajat ylittävät seurainevästeet: %@"; @@ -31,8 +34,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Sosiaalisen median seuraimet: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Seuraimia estetty: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/fr.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/fr.lproj/EnhancedTrackingProtection.strings index 9632216e4bf8..635ee4707b32 100644 --- a/firefox-ios/Shared/Supporting Files/fr.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/fr.lproj/EnhancedTrackingProtection.strings @@ -31,8 +31,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Traqueurs de réseaux sociaux : %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Traqueurs bloqués : %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/he.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/he.lproj/EnhancedTrackingProtection.strings index 51fdbbf14606..a441fa95994d 100644 --- a/firefox-ios/Shared/Supporting Files/he.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/he.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "החיבור אינו מאובטח"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "לא נמצאו רכיבי מעקב"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "עוגיות מעקב חוצות אתרים: %@"; @@ -31,8 +34,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "רכיבי מעקב של מדיה חברתית: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "רכיבי מעקב שנחסמו: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/Alerts.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/Alerts.strings index e98c744c04b3..ba590442cd8a 100644 --- a/firefox-ios/Shared/Supporting Files/hr.lproj/Alerts.strings +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/Alerts.strings @@ -16,6 +16,9 @@ /* The title for the affirmative action of the restore tabs pop-up alert. This alert shows when opening up Firefox after it crashed, and will restore existing tabs. */ "Alerts.RestoreTabs.Button.Yes.v109" = "Vrati kartice"; +/* The body of the restore tabs pop-up alert. This alert shows when opening up Firefox after it crashed. */ +"Alerts.RestoreTabs.Message.v109" = "Oprosti. Obnovi kartice da nastaviš tamo gdje si stao/la."; + /* The title of the restore tabs pop-up alert. This alert shows when opening up Firefox after it crashed. The placeholder will be the Firefox name. */ "Alerts.RestoreTabs.Title.v109.v2" = "%@ se srušio. Želiš li vratiti tvoje kartice?"; diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/ContextualHints.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/ContextualHints.strings new file mode 100644 index 000000000000..002345733444 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/ContextualHints.strings @@ -0,0 +1,3 @@ +/* Contextual hints are little popups that appear for the users informing them of new features. This is a call to action for the popup that appears to educate users about what the fire button in the toolbar does, when in private mode. */ +"ContextualHints.FeltDeletion.Body.v122" = "Dodirni ovdje za početak nove privatne sesije. Izbriši svoju povijest, kolačiće – sve."; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/CredentialProvider.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/CredentialProvider.strings index 126db77a6611..a42e685930ed 100644 --- a/firefox-ios/Shared/Supporting Files/hr.lproj/CredentialProvider.strings +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/CredentialProvider.strings @@ -1,3 +1,12 @@ +/* Label shown when there are no logins to list. The placeholder will be replaced with the app name. */ +"LoginsList.NoLoginsFound.Description.v122" = "Ovdje će se prikazati s aplikacijom %@ spremljene ili sinkronizirane lozinke. Sve lozinke koje spremiš se šifriraju."; + +/* Label shown when there are no logins saved in the passwords list */ +"LoginsList.NoLoginsFound.Title.v122" = "Nijedna lozinka nije spremljena"; + +/* Label displayed when a user searches for an item, and no matches can be found against the search query */ +"LoginsList.NoMatchingResult.Title.v122" = "Nijedna lozinka nije pronađena"; + /* Placeholder text for search field in the credential provider list */ "LoginsList.Search.Placeholder.v122" = "Traži lozinke"; diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/Credentials.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/Credentials.strings new file mode 100644 index 000000000000..718e7831949f --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/Credentials.strings @@ -0,0 +1,6 @@ +/* Message shown when you enter Logins & Passwords without having a device passcode set. */ +"Logins.DevicePasscodeRequired.Message.v122" = "Za spremanje i automatsko ispunjavanje lozinki aktiviraj Face ID, Touch ID ili šifru uređaja."; + +/* Message shown when you enter Payment Methods without having a device passcode set. */ +"Logins.PaymentMethods.DevicePasscodeRequired.Message.v124.v2" = "Za spremanje i automatsko ispunjavanje kreditnih kartica aktiviraj Face ID, Touch ID ili šifru uređaja."; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/CustomizeFirefoxHome.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/CustomizeFirefoxHome.strings index 5940f02b8d5b..77314e0c58b5 100644 --- a/firefox-ios/Shared/Supporting Files/hr.lproj/CustomizeFirefoxHome.strings +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/CustomizeFirefoxHome.strings @@ -1,6 +1,9 @@ /* In the settings menu, in the Firefox homepage customization section, this is the title for the option that allows users to toggle Bookmarks section on the Firefox homepage on or off */ "Settings.Home.Option.Bookmarks.v128" = "Zabilješke"; +/* In the settings menu, in the Firefox homepage customization section, this is the subtitle for the option that allows users to turn the Pocket Recommendations section on the Firefox homepage on or off. The placeholder is the pocket app name. */ +"Settings.Home.Option.ThoughtProvokingStories.subtitle.v116" = "Članke pokreće %@"; + /* In the settings menu, in the Firefox homepage customization section, this is the title for the option that allows users to turn the Pocket Recommendations section on the Firefox homepage on or off */ "Settings.Home.Option.ThoughtProvokingStories.v116" = "Priče koje potiču na razmišljanje"; diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/EnhancedTrackingProtection.strings index 01de5efc88b2..84c3e4acd865 100644 --- a/firefox-ios/Shared/Supporting Files/hr.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/EnhancedTrackingProtection.strings @@ -4,6 +4,9 @@ /* The text for the clear cookies and site data alert button inside the enhanced tracking protection screen. */ "Menu.EnhancedTrackingProtection.ClearData.AlertOkButton.v128" = "Izbriši"; +/* The text for the clear cookies and site data alert inside the enhanced tracking protection screen. The placeholder will be replaced with the user's currently visited website */ +"Menu.EnhancedTrackingProtection.ClearData.AlertText.v128" = "Uklanjanjem kolačića i podataka web stranice, %@ će te možda odjaviti s web stranice i isprazniti košaricu."; + /* The title for the clear cookies and site data alert inside the enhanced tracking protection screen. */ "Menu.EnhancedTrackingProtection.ClearData.AlertTitle.v128" = "Izbriši kolačiće i podatke stranice"; @@ -19,19 +22,40 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Veza nije sigurna"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Nema programa za praćenje"; + +/* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Kolačići za praćenje web stranica: %@"; + +/* Text to let users know how many fingerprinters were blocked on the current website. The placeholder will show the number of fingerprinters detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.Fingerprinter.v129" = "Broj prikupljača digitalnih otisaka: %@"; + /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Programi za praćenje društvenih mreža: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Blokirani programi za praćenje: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ "Menu.EnhancedTrackingProtection.Details.Verifier.v128" = "Ovjereno od %@"; +/* Header for the enhanced tracking protection screen when the user has opted out of the feature. Placeholder will be replaced by the app name */ +"Menu.EnhancedTrackingProtection.Off.Header.v128" = "%@ je deaktiviran. Predlažemo ponovno uključivanje zaštite."; + /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Isključio/la si zaštitu"; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. + Header for the enhanced tracking protection screen when the user has selected to be protected. */ +"Menu.EnhancedTrackingProtection.On.Header.v128" = "Zaštićen/a si. Ako nešto uočimo, javit ćemo ti."; + +/* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Oprez na ovoj stranici"; + +/* Title for the enhanced tracking protection screen when the user has selected to be protected. The placeholder will have the value of the app name */ +"Menu.EnhancedTrackingProtection.On.Title.v128" = "%@ stražari"; + /* The title for the privacy settings button inside the enhanced tracking protection screen. */ "Menu.EnhancedTrackingProtection.PrivacySettings.Title.v128" = "Postavke privatnosti"; @@ -44,3 +68,6 @@ /* A switch to disable enhanced tracking protection inside the menu. */ "Menu.EnhancedTrackingProtection.SwitchOff.Text.v129" = "Zaštite su ISKLJUČENE. Predlažemo da ih ponovo uključiš."; +/* A switch to disable enhanced tracking protection inside the menu. */ +"Menu.EnhancedTrackingProtection.SwitchOn.Text.v128" = "Ako na ovoj stranici nešto izgleda pokvareno, pokušaj isključiti zaštitu."; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/FirefoxHomepage.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/FirefoxHomepage.strings index 9660fad9104c..c18da86f2c3e 100644 --- a/firefox-ios/Shared/Supporting Files/hr.lproj/FirefoxHomepage.strings +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/FirefoxHomepage.strings @@ -1,3 +1,9 @@ +/* When the user ends their private session, they are returned to the private mode homepage, and a toastbar popups confirming that their data has been erased. This is the label for that toast. */ +"FirefoxHomepage.FeltDeletion.Link.v122" = "Podaci privatnog pregledavanja izbrisani"; + +/* The body of the message for the card that educates users about how private mode works. The card shows up on the homepage when in the new privacy mode. Placeholder refers to app name. */ +"FirefoxHomepage.FeltPrivacyUI.Body.v122" = "%@ briše tvoje kolačiće, povijest i podatke web stranica kada zatvoriš sve svoje privatne kartice."; + /* The link for the card that educates users about how private mode works. The link redirects to an external site for more information. The card shows up on the homepage when in the new privacy mode. */ "FirefoxHomepage.FeltPrivacyUI.Link.v122" = "Tko bi mogao vidjeti moju aktivnost?"; diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/Microsurvey.strings index 3f26d5d41106..1b0d0ad7ef21 100644 --- a/firefox-ios/Shared/Supporting Files/hr.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Neodabrano"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Anketa"; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/Onboarding.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/Onboarding.strings index 06f575403d12..12d8df3b7e25 100644 --- a/firefox-ios/Shared/Supporting Files/hr.lproj/Onboarding.strings +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/Onboarding.strings @@ -67,24 +67,45 @@ /* On the toolbar customization onboarding card, the string used to describe the option to set the toolbar at the top of the screen. */ "Onboarding.Customization.Toolbar.Top.Action.v123" = "Gore"; +/* String used to describes what Firefox is on the first onboarding page in our Onboarding screens. Indie means small independant. */ +"Onboarding.IntroDescriptionPart1.v114" = "Neovisna. Neprofitna organizacija. Zauvijek."; + +/* String used to describes what Firefox is on the first onboarding page in our Onboarding screens. */ +"Onboarding.IntroDescriptionPart2.v114" = "Predani obećanju za bolji internet za sve."; + /* Describes an action on some of the Onboarding screen, including the wallpaper onboarding screen. This string will be on a button so user can skip that onboarding page. */ "Onboarding.LaterAction.v115" = "Preskoči"; /* String used to describe the option to continue to ask for the notification permission in Firefox Onboarding screens. */ "Onboarding.Notification.Continue.Action.v114" = "Nastavi"; +/* String used to describe the description of the notification onboarding page in our Onboarding screens. Placeholder is for the app name. */ +"Onboarding.Notification.Description.v120" = "Šalji kartice između svojih uređaja na siguran način i otkrij druge %@ funkcije privatnosti."; + /* String used to describe the option to skip the notification permission in Firefox Onboarding screens. */ "Onboarding.Notification.Skip.Action.v115" = "Preskoči"; +/* String used to describe the title of the notification onboarding page in our Onboarding screens. Placeholder is for the app name. */ +"Onboarding.Notification.Title.v120" = "Obavijesti pomažu da ostaneš sigurniji uz %@"; + /* String used to describe the option to continue to ask for the notification permission in Firefox Onboarding screens. */ "Onboarding.Notification.TurnOnNotifications.Action.v114" = "Uključi obavijesti"; +/* String used to describes the description of what Firefox is on the Sync onboarding page for current version in our Onboarding screens. Placeholder is for the app name. */ +"Onboarding.Sync.Description.v120" = "Prijava i sinkronizacija povećavaju tvoju sigurnost. %@ šifrira tvoje lozinke, zabilješke i još više."; + +/* String used to describes the description of what Firefox is on the Sync onboarding page for current version in our Onboarding screens. Placeholder is for the app name. */ +"Onboarding.Sync.Description.v123" = "%@ šifrira tvoje lozinke, zabilješke i još više kada si sinkroniziran/a."; + /* String used to describes the option to skip the Sync sign in during onboarding for the current version in Firefox Onboarding screens. */ "Onboarding.Sync.SignIn.Action.v114" = "Prijava"; /* String used to describes the option to skip the Sync sign in during onboarding for the current version in Firefox Onboarding screens. */ "Onboarding.Sync.Skip.Action.v114" = "Preskoči"; +/* String used to describes the title of what Firefox is on the Sync onboarding page for current version in our Onboarding screens. */ +"Onboarding.Sync.Title.v120" = "Šifriraj podatke kada radiš na više uređaja"; + /* Accessibility label for the wallpaper onboarding modal displayed on top of the homepage. This describes to the user that which type of wallpaper they are seeing. */ "Onboarding.Wallpaper.Accessibility.Classic.v114" = "Klasična pozadina"; @@ -109,6 +130,24 @@ /* Describes the action on the first onboarding page in our Onboarding screen. This indicates that the user will set their default browser to Firefox. */ "Onboarding.Welcome.ActionTreatementA.v114" = "Postavi kao standardni preglednik"; +/* Accessibility label for close button that dismisses the welcome onboarding screen. Placeholder is for the app name. */ +"Onboarding.Welcome.Close.AccessibilityLabel.v121" = "Zatvori i izađi iz početnog %@ ekrana"; + +/* String used to describes the description of what Firefox is on the welcome onboarding page for current version in our Onboarding screens. */ +"Onboarding.Welcome.Description.TreatementA.v120" = "Naš preglednik neprofitne organizacije pomaže spriječiti poduzeća da te potajno prate na webu."; + +/* String used to describes the description of what Firefox is on the welcome onboarding page for current version in our Onboarding screens. Placeholder is for the app name. */ +"Onboarding.Welcome.Description.v120" = "Naš preglednik neprofitne organizacije pomaže spriječiti poduzeća da te potajno prate na webu."; + +/* String used to describe the title of link button is on the welcome onboarding page for current version in our Onboarding screens. */ +"Onboarding.Welcome.Link.Action.v114" = "Saznaj više u našoj napomeni o privatnosti"; + /* Describes the action on the first onboarding page in our Onboarding screen. This string will be on a button so user can skip this onboarding card. */ "Onboarding.Welcome.Skip.v114" = "Preskoči"; +/* String used to describes the title of what Firefox is on the welcome onboarding page for current version in our Onboarding screens. */ +"Onboarding.Welcome.Title.TreatementA.v120" = "Volimo te štititi"; + +/* String used to describes the title of what Firefox is on the welcome onboarding page for current version in our Onboarding screens. */ +"Onboarding.Welcome.Title.v114" = "Dobro došao, dobro došla u neovisni internet"; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/PasswordAutofill.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/PasswordAutofill.strings new file mode 100644 index 000000000000..f4b36a88fb3c --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/PasswordAutofill.strings @@ -0,0 +1,15 @@ +/* This label is used in a cell found in the list of autofill login options in place of an actual username to denote that no username was saved for this login */ +"PasswordAutofill.LoginListCellNoUsername.v129" = "(nema korisničkog imena)"; + +/* This label is used for a button in the password list screen allowing users to manage their saved passwords. It's meant to direct users to where they can add, remove, or edit their saved passwords. */ +"PasswordAutofill.ManagePasswordsButton.v124" = "Upravljaj lozinkama"; + +/* This phrase is used as a subtitle in the header of password list screen, indicating to the user that they will be logging into a specific website (represented by %@) using a saved password. It's providing clarity on which website the saved credentials apply to. */ +"PasswordAutofill.SignInWithSavedPassword.v124" = "Prijavit ćeš se na %@"; + +/* This label is used in the password list screen header as a question, prompting the user if they want to use a saved password for logging in. */ +"PasswordAutofill.UseSavedPasswordFromHeader.v124" = "Koristiti spremljenu lozinku?"; + +/* Displayed inside the keyboard hint when a user is entering their login credentials and has at least one saved password. Indicates that there are stored passwords available for use in filling out the login form. */ +"PasswordAutofill.UseSavedPasswordFromKeyboard.v124" = "Koristi spremljenu lozinku"; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/QRCode.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/QRCode.strings new file mode 100644 index 000000000000..f8caaf3e52a7 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/QRCode.strings @@ -0,0 +1,3 @@ +/* Accessibility label of the QR code button in the toolbar */ +"QRCode.Toolbar.Button.A11y.Title.v128" = "Snimi QR kod"; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/RememberCard.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/RememberCard.strings index 8401ad68f1cf..9043de801c2f 100644 --- a/firefox-ios/Shared/Supporting Files/hr.lproj/RememberCard.strings +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/RememberCard.strings @@ -1,3 +1,12 @@ +/* This value is used as the header for the remember card page. The placeholder is for the app name. */ +"CreditCard.RememberCard.Header.v122" = "%@ šifrira broj tvoje kreditne kartice. Tvoj sigurnosni kod se neće spremiti."; + +/* This value is used as the title for the Yes button in the remember credit card page */ +"CreditCard.RememberCard.MainButtonTitle.v122" = "Spremi"; + +/* This value is used as the title for the remember credit card page */ +"CreditCard.RememberCard.MainTitle.v122" = "Spremiti ovu kreditnu karticu na siguran način?"; + /* This value is used as the title for the Not Now button in the remember credit card page */ "CreditCard.RememberCard.SecondaryButtonTitle.v115" = "Ne sada"; diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/ResearchSurface.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/ResearchSurface.strings new file mode 100644 index 000000000000..a61e358c15b6 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/ResearchSurface.strings @@ -0,0 +1,9 @@ +/* On the Research Survey popup, the text that explains what the screen is about. Placeholder is for the app name. */ +"Body.Text.v112" = "Pomogni poboljšati %@ ispunjavanjem kratke ankete."; + +/* On the Research Survey popup, the text for the button that, when tapped, will dismiss the popup and take the user to a survey. */ +"PrimaryButton.Label.v112" = "Ispuni anketu"; + +/* On the Research Survey popup, the text for the button that, when tapped, will dismiss this screen, and the user will not be taken to the survey. */ +"SecondaryButton.Label.v112" = "Ne hvala"; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/ScanQRCode.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/ScanQRCode.strings new file mode 100644 index 000000000000..fbbf003e4b14 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/ScanQRCode.strings @@ -0,0 +1,9 @@ +/* Allow button to open URL from scanned QR Code */ +"ScanQRCode.ConfirmOpenURL.AllowButton.v129" = "Dozvoli"; + +/* Deny button to cancel opening URL from scanned QR Code */ +"ScanQRCode.ConfirmOpenURL.DenyButton.v129" = "Odbij"; + +/* Text of the prompt to ask user permission to open a URL from a scanned QR code. Placeholder is app name. */ +"ScanQRCode.ConfirmOpenURL.Message.v129" = "Dozvoliti da %@ otvori URL?"; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/SearchHeaderTitle.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/SearchHeaderTitle.strings index 0824f5f8108b..0f59f091a06a 100644 --- a/firefox-ios/Shared/Supporting Files/hr.lproj/SearchHeaderTitle.strings +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/SearchHeaderTitle.strings @@ -1,3 +1,6 @@ +/* When making a new search from the awesome bar, search results appear as the user write new letters in their search. Different sections with results from the selected search engine will appear. This string will be used as a header to separate the selected engine search results from current search query. */ +"Search.EngineSection.Title.v108" = "%@ pretraga"; + /* When making a new search from the awesome bar, search results appear as the user write new letters in their search. This string will be used as a header for Google search results listed as suggestions. */ "Search.Google.Title.v108" = "Google pretraživanje"; diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/SelectCreditCard.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/SelectCreditCard.strings index 6b8d086319e7..d35decf3ba91 100644 --- a/firefox-ios/Shared/Supporting Files/hr.lproj/SelectCreditCard.strings +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/SelectCreditCard.strings @@ -1,3 +1,3 @@ /* This value is used as the title for the select a credit card from list of available cards. */ -"CreditCard.SelectCreditCard.MainTitle.v116" = "Koristiti spremljenu karticu?"; +"CreditCard.SelectCreditCard.MainTitle.v122" = "Koristi spremljenu kreditnu karticu"; diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/Settings.strings index 79c2d0867fbe..727a5fd18574 100644 --- a/firefox-ios/Shared/Supporting Files/hr.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/Settings.strings @@ -1,3 +1,9 @@ +/* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ +"Addresses.Settings.SavedAddressesSectionTitle.v124" = "SPREMLJENE ADRESE"; + +/* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ +"Addresses.Settings.Switch.Description.v124" = "Uključuje telefonske brojeve i e-mail adrese"; + /* Title label for user to use the toggle settings to allow saving and autofilling of addresses for webpages. */ "Addresses.Settings.Switch.Title.v124" = "Spremi i ispuni adrese"; @@ -7,6 +13,9 @@ /* Accessibility label for the add button in autofill settings screen. Pressing this button presents a modal that allows users to add a card by entering the credit card information. */ "CreditCard.Settings.AddCard.AccessibilityLabel.v121" = "Dodaj kreditnu karticu"; +/* Description label for when there are no credit cards shown in credit card list in autofill settings screen. */ +"CreditCard.Settings.EmptyListDescription.v112" = "Spremi podatke kreditne kartice na siguran način za brže plaćanje u budućnosti."; + /* Title label for when there are no credit cards shown in credit card list in autofill settings screen. %@ is the product name and should not be altered. */ "CreditCard.Settings.EmptyListTitle.v122" = "Spremi kreditne kartice na %@"; @@ -58,18 +67,30 @@ /* This is the title for the setting that toggles Sync related notifications in the settings menu under the Notifications section. */ "Settings.Notifications.SyncNotificationsTitle.v112" = "Sinkronizacija"; +/* This is the footer title informing the user needs to turn on notifications in iOS Settings. Both placeholders will be replaced with the app name. */ +"Settings.Notifications.SystemNotificationsDisabledMessage.v112" = "Isključene su sve %1$@ obavijesti. Uključi ih na uređaju u izborniku Postavke > Obavijesti > %2$@"; + +/* This is the description for the setting that toggles Tips and Features feature in the settings menu under the Notifications section. The placeholder will be replaced with the app name. */ +"Settings.Notifications.TipsAndFeaturesNotificationsStatus.v112" = "Saznaj više o korisnim funkcijama i kako najbolje iskoristiti %@."; + /* This is the title for the setting that toggles Tips and Features feature in the settings menu under the Notifications section. */ "Settings.Notifications.TipsAndFeaturesNotificationsTitle.v112" = "Savjeti i značajke"; /* In the settings menu, in the Privacy section, this is the title for Notifications customization section. */ "Settings.Notifications.Title.v112" = "Obavijesti"; +/* This is the title informing the user needs to turn on notifications in iOS Settings. The placeholder will be replaced with the app name. */ +"Settings.Notifications.TurnOnNotificationsMessage.v112" = "Idi na postavke uređaja za uključivanje obavijesti u %@"; + /* This is the title informing the user needs to turn on notifications in iOS Settings. */ "Settings.Notifications.TurnOnNotificationsTitle.v112" = "Uključi obavijesti"; /* Accessibility label for default search engine setting. */ "Settings.Search.Accessibility.DefaultSearchEngine.v121" = "Standardna tražilica"; +/* Accessibility label for Learn more about Firefox Suggest. */ +"Settings.Search.Accessibility.LearnAboutSuggestions.v124" = "Saznaj više o funkciji Firefox prijedlozi"; + /* Title for alternate search engines settings section in the Search page in the Settings menu. */ "Settings.Search.AlternateSearchEngines.Title.v124.v2" = "Alternativne tražilice"; @@ -103,6 +124,15 @@ /* Label for the `show search suggestions` setting, in the Search Settings page. */ "Settings.Search.ShowSuggestions.v121" = "Prikaži prijedloge pretraživanja"; +/* In the Search page of the Settings menu, the title for the Firefox Suggest settings section. */ +"Settings.Search.Suggest.AddressBarSetting.Title.v124" = "Adresna traka – Firefox prijedlozi"; + +/* In the search page of the Settings menu, the title for the link to the SUMO Page about Firefox Suggest. */ +"Settings.Search.Suggest.LearnAboutSuggestions.v124" = "Saznaj više o funkciji Firefox prijedlozi"; + +/* Description for `Show in Private Sessions` toggle, located in `Address Bar - Firefox Suggest` section in the Search page in the Settings menu. */ +"Settings.Search.Suggest.PrivateSession.Description.v125" = "Prikaži prijedloge od Firefox prijedlozi u privatnim sesijama"; + /* In the Search page of the Settings menu, the title for the setting to enable search browsing history. */ "Settings.Search.Suggest.SearchBrowsingHistory.Title.v124" = "Pretraži povijest pregledavanja"; @@ -112,12 +142,21 @@ /* In the Search page of the Settings menu, the title for the setting to enable synced tabs. */ "Settings.Search.Suggest.SearchSyncedTabs.Title.v124" = "Pretraži sinkronizirane kartice"; +/* In the Search page of the Settings menu, the description for the setting to enable Suggestions from Firefox. */ +"Settings.Search.Suggest.ShowNonSponsoredSuggestions.Description.v124" = "Dobij prijedloge s weba koji se odnose na tvoju pretragu"; + +/* In the Search page of the Settings menu, the description for the setting to enable Suggestions from Firefox. Placeholder is for the app name - Firefox. */ +"Settings.Search.Suggest.ShowNonSponsoredSuggestions.Description.v124.v2" = "Dobij prijedloge od %@a koji se odnose na tvoju pretragu"; + /* In the Search page of the Settings menu, the title for setting to enable Suggestions from Firefox. Placeholder is for the app name - Firefox. */ "Settings.Search.Suggest.ShowNonSponsoredSuggestions.Title.v124" = "Prijedlozi od %@"; /* In the Search page of the Settings menu, the title for setting to enable Suggestions from the web in Firefox. */ "Settings.Search.Suggest.ShowNonSponsoredSuggestions.Title.v124.v2" = "Prijedlozi od weba"; +/* In the Search page of the Settings menu, the description for the setting to enable Suggestions from sponsors. Placeholder is for the app name - Firefox. */ +"Settings.Search.Suggest.ShowSponsoredSuggestions.Description.v124" = "Podrži %@ s povremenim sponzoriranim prijedlozima"; + /* In the Search page of the Settings menu, the title for the setting to enable Suggestions from sponsors. */ "Settings.Search.Suggest.ShowSponsoredSuggestions.Title.v124" = "Prijedlozi od sponzora"; diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/Share.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/Share.strings new file mode 100644 index 000000000000..fd441246a660 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/Share.strings @@ -0,0 +1,6 @@ +/* Error message shown in the remote tabs panel */ +"SendTo.NoDevicesFound.Message.v119" = "Nemaš nijedan drugi uređaj povezan s ovim računom koji je dostupan za sinkronizaciju."; + +/* This message appears when a user tries to use 'Send Link to Device' action while not logged in */ +"SendTo.NotSignedIn.Title.v119" = "Nisi prijavljen/a na svoj račun."; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/Shopping.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/Shopping.strings index 044aad3fcf07..5a32bbdcb960 100644 --- a/firefox-ios/Shared/Supporting Files/hr.lproj/Shopping.strings +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/Shopping.strings @@ -1,9 +1,21 @@ +/* Contextual hints are little popups that appear for the users informing them of new features. This one indicates that a user can tap on the shopping button to start using the Shopping feature. */ +"ContextualHints.Shopping.NotOptedIn.v120" = "Saznaj možeš li vjerovati recenzijama ovog proizvoda – prije kupnje."; + /* Contextual hints are little popups that appear for the users informing them of new features. This one is a call to action for the popup describing the Shopping feature. It indicates that a user can go directly to the Shopping feature by tapping the text of the action. */ "ContextualHints.Shopping.NotOptedInAction.v120" = "Probaj provjeru recenzija"; /* Contextual hints are little popups that appear for the users informing them of new features. This is a call to action for the popup that appears after the user has opted in for the Shopping feature. It indicates that a user can directly open the review checker by tapping the text of the action. */ "ContextualHints.Shopping.OptedInAction.v120" = "Otvori provjeru recenzija"; +/* Contextual hints are little popups that appear for the users informing them of new features. This one appears after the user has opted in and informs him if he wants use the review checker by tapping the Shopping button. */ +"ContextualHints.Shopping.OptedInBody.v120" = "Jesu li ove recenzije pouzdane? Provjeri sada za prikaz prilagođene ocjene."; + +/* Footer label from the Fakespot Ad card displayed for the related product we advertise. This is displayed below the ad card, suggested as an alternative to the product reviewed. The first parameter will be replaced by the Fakespot app name */ +"Shopping.AdCard.Footer.v121" = "Oglas od %@"; + +/* Title label for the Fakespot Ad card. This is displayed above a product image, suggested as an alternative to the product reviewed. */ +"Shopping.AdCard.Title.v121" = "Alternativni proizvodi"; + /* Description adjusted of the rating card displayed in the shopping review quality bottom sheet. */ "Shopping.AdjustedRating.Description.v121" = "Na temelju pouzdanih recenzija"; @@ -40,15 +52,90 @@ /* Section title of the review highlights displayed in the shopping review quality bottom sheet. */ "Shopping.HighlightsCard.Shipping.Title.v120" = "Dostava"; +/* Title of the review highlights displayed in the shopping review quality bottom sheet. */ +"Shopping.HighlightsCard.Title.v120" = "Izdvajamo iz nedavnih recenzija"; + +/* Title for info card when Fakespot cannot analyze reviews for a certain product type */ +"Shopping.InfoCard.FakespotDoesNotAnalyzeReviews.Description.v120" = "Nažalost, ne možemo provjeriti kvalitetu recenzija za određene vrste proizvoda. Na primjer, poklon kartice i streaming videa, glazbe i igara."; + +/* Title for info card when Fakespot cannot analyze reviews for a certain product type */ +"Shopping.InfoCard.FakespotDoesNotAnalyzeReviews.Title.v120" = "Ne možemo provjeriti ove recenzije"; + +/* Description text for an information card used in the review checker section. This message is displayed when the reviews for a product are not yet available but are expected to be provided within the next 24 hours. It serves to inform users of the short wait for reviews and encourages them to return soon for the updated information. */ +"Shopping.InfoCard.InfoComingSoon.Description.v121" = "Trebali bismo imati informacije o recenzijama ovog proizvoda u roku od 24 sata. Navrati kasnije."; + +/* Title for an information card that is displayed in the review checker section when certain details about a product or feature are not currently available but are expected to be provided soon. The message should imply that the user can look forward to receiving more information shortly. */ +"Shopping.InfoCard.InfoComingSoon.Title.v121" = "Informacije stižu uskoro"; + /* Primary action title for info card when the product needs analysis */ "Shopping.InfoCard.NeedsAnalysis.PrimaryAction.v120" = "Provjeri sada"; +/* Title for info card when the product needs analysis */ +"Shopping.InfoCard.NeedsAnalysis.Title.v120" = "Nove informacije za provjeru"; + +/* Description for info card when no information is available at the moment */ +"Shopping.InfoCard.NoInfoAvailableRightNow.Description.v120" = "Radimo na rješavanju ovog problema. Navrati malo kasnije."; + +/* Title for info card when no information is available at the moment */ +"Shopping.InfoCard.NoInfoAvailableRightNow.Title.v120" = "Trenutačno nema informacija"; + +/* Description for info card when there are not enough reviews for a product */ +"Shopping.InfoCard.NotEnoughReviews.Description.v120" = "Kad ovaj proizvod bude imao više recenzija, moći ćemo provjeriti njegovu kvalitetu."; + +/* Title for info card when there are not enough reviews for a product */ +"Shopping.InfoCard.NotEnoughReviews.Title.v120" = "Još nema dovoljno recenzija"; + +/* Description for the information card displayed by the review checker feature when the product the user is looking at is out of stock. This description is used for info card where the user can report if it's back in stock. */ +"Shopping.InfoCard.ProductNotInStock.Description.v121" = "Ako vidiš da je ovaj proizvod ponovo na zalihi, prijavi ga i mi ćemo provjeriti recenzije."; + +/* Primary action label for the information card displayed by the review checker feature when the product the user is looking at is out of stock. This primary action label is used for info card button where the user can report if it's back in stock. */ +"Shopping.InfoCard.ProductNotInStock.PrimaryAction.v121" = "Prijavi proizvod koji je ponovo na zalihi"; + /* Title for the information card displayed by the review checker feature when the product the user is looking at is out of stock. This title is used for info card where the user can report if it's back in stock. */ "Shopping.InfoCard.ProductNotInStock.Title.v121" = "Proizvod nije dostupan"; /* Description for info card when the product is in analysis mode */ "Shopping.InfoCard.ProgressAnalysis.Description.v120" = "To bi moglo potrajati oko 60 sekundi."; +/* Title for info card when the product is in analysis mode */ +"Shopping.InfoCard.ProgressAnalysis.Title.v120" = "Provjera kvalitete recenzije"; + +/* Title for info card when the product is in analysis mode. The placeholder represents the percentage of the analysis progress, ranging between 1 and 100. */ +"Shopping.InfoCard.ProgressAnalysis.Title.v123" = "Provjera kvalitete recenzije (%@)"; + +/* This description appears beneath the confirmation title on the information card to inform the user that their report regarding the product stock status has been received and is being processed. It serves to set the expectation that the review information will be updated within 24 hours and invites the user to revisit the product page for updates. */ +"Shopping.InfoCard.ReportSubmittedByCurrentUser.Description.v121" = "Trebali bismo imati informacije o recenzijama ovog proizvoda u roku od 24 sata. Navrati kasnije."; + +/* This title is displayed on the information card as a confirmation message after a user reports that a previously out-of-stock product is now available. It's meant to acknowledge the user's contribution and encourage community engagement by letting them know their report has been successfully submitted. */ +"Shopping.InfoCard.ReportSubmittedByCurrentUser.Title.v121" = "Hvala na prijavi!"; + +/* Text for the analyzer button displayed when an analysis can be updated for a product. */ +"Shopping.NoAnalysisCard.AnalyzerButton.Title.v120" = "Provjeri kvalitetu recenzija"; + +/* Text for the body label, to check the reliability of a product. */ +"Shopping.NoAnalysisCard.BodyLabel.Title.v120" = "Za saznavanje o pouzdanosti recenzija ovog proizvoda provjeri kvalitetu recenzije. Traje samo nekih 60 sekundi."; + +/* Title for card displayed when a shopping product has not been analysed yet. */ +"Shopping.NoAnalysisCard.HeadlineLabel.Title.v120" = "Još nema informacija o ovim recenzijama"; + +/* Text for the disclaimer that appears underneath the rating image of the Shopping Experience Opt In onboarding Card (Fakespot). The parameter will be replaced by the Fakespot app name. After the colon, what appears are two links, each on their own line. The first link is to a Privacy policy. The second link is to Terms of use. */ +"Shopping.OptInCard.Disclaimer.Text.v120" = "Odabirom „Da, isprobaj” pristaješ na sljedeće od %@:"; + +/* Text for the disclaimer that appears underneath the rating image of the Shopping Experience Opt In onboarding Card (Fakespot). After the colon, there will be two links, each on their own line. The first link is to a Privacy policy. The second link is to Terms of use. */ +"Shopping.OptInCard.Disclaimer.Text.v123" = "Odabirom „Da, isprobaj” pristaješ na:"; + +/* Label for the first paragraph of the Shopping Experience Opt In onboarding Card (Fakespot). The first parameter will be the website the user is coming from when viewing this screen (default Amazon). The second parameter will be replaced by the app name. This string is almost identical with 'Shopping.OptInCard.FirstParagraph.Description', but without Best Buy and Walmart websites, which are not available in many locales. */ +"Shopping.OptInCard.FirstParagraph.AmazonOnly.Description.v122" = "Prije kupovine pogledaj koliko su pouzdane recenzije proizvoda na %1$@. Provjera recenzija, eksperimentalna %2$@ funkcija, ugrađena direktno u preglednik."; + +/* Label for the first paragraph of the Shopping Experience Opt In onboarding Card (Fakespot). The first parameter will be the website the user is coming from when viewing this screen (default Amazon). The second parameter will be replaced by the app name. The third and fourth parameters will be the other two websites that are currently supported (Amazon, Best Buy or Walmart) besides the one used for the first parameter. */ +"Shopping.OptInCard.FirstParagraph.Description.v120" = "Prije kupovine pogledaj koliko su pouzdane recenzije proizvoda na %1$@. Provjera recenzija, eksperimentalna %2$@ funkcija, ugrađena direktno u preglednik. Radi i na %3$@ te %4$@ stranicama."; + +/* Label for the header of the Shopping Experience Opt In onboarding Card (Fakespot) */ +"Shopping.OptInCard.HeaderLabel.Title.v120" = "Isprobaj naš pouzdani vodič za recenzije proizvoda"; + +/* Label for the Learn more button in the Shopping Experience Opt In onboarding Card (Fakespot) */ +"Shopping.OptInCard.LearnMoreButtonTitle.Title.v120" = "Saznaj više"; + /* Text for the main button of the Shopping Experience Opt In onboarding Card (Fakespot) */ "Shopping.OptInCard.MainButton.Title.v120" = "Da, probaj"; @@ -61,6 +148,9 @@ /* Text for the secondary button of the Shopping Experience Opt In onboarding Card (Fakespot) */ "Shopping.OptInCard.SecondaryButton.Title.v120" = "Ne sada"; +/* Label for the second paragraph of the Shopping Experience Opt In onboarding Card (Fakespot). The first parameter will be replaced by the Fakespot app name. The second parameter will be replaced the company name of Mozilla. */ +"Shopping.OptInCard.SecondParagraph.Description.v120" = "Koristeći %1$@ moć od %2$@ pomažemo ti da izbjegneš pristrane i neautentične recenzije. Naš model UI-a se stalno poboljšava kako bi te zaštitio dok kupuješ."; + /* Show Firefox Browser Terms of Use page from the Privacy section in the Shopping Experience Opt In onboarding Card (Fakespot). See https://www.mozilla.org/privacy/firefox/ */ "Shopping.OptInCard.TermsOfUse.Button.Title.v120" = "Uvjeti korištenja"; @@ -82,12 +172,42 @@ /* Description of the reliability ratings for rating 'D' and 'F' displayed in the shopping review quality bottom sheet. */ "Shopping.ReviewQuality.ReliabilityRating.DF.Description.v120" = "Nepouzdane recenzije"; +/* Adjusted rating label from How we determine review quality card displayed in the shopping review quality bottom sheet. The *text inside asterisks* denotes part of the string to bold, please leave the text inside the '*' so that it is bolded correctly. */ +"Shopping.ReviewQualityCard.AdjustedRating.Label.v120" = "*Prilagođena ocjena* se temelji samo na recenzijama za koje vjerujemo da su pouzdane."; + +/* Accessibility label for the up chevron, from 'How we determine review quality' card displayed in the shopping review quality bottom sheet. */ +"Shopping.ReviewQualityCard.Collapse.AccessibilityLabel.v120" = "Sklopi karticu „Kako određujemo kvalitetu recenzija”"; + +/* Accessibility label for the down chevron, from 'How we determine review quality' card displayed in the shopping review quality bottom sheet. */ +"Shopping.ReviewQualityCard.Expand.AccessibilityLabel.v120" = "Rasklopi karticu „Kako određujemo kvalitetu recenzija”"; + +/* Label of the headline from How we determine review quality card displayed in the shopping review quality bottom sheet. The first parameter will be replaced by the Fakespot app name and the second parameter by the company name of Mozilla. */ +"Shopping.ReviewQualityCard.Headline.Label.v120" = "Koristimo %1$@ UI tehnologiju od %2$@ za provjeru pouzdanosti recenzija proizvoda. To će ti pomoći procijeniti samo kvalitetu recenzija, ne kvalitetu proizvoda."; + +/* Highlights label from How we determine review quality card displayed in the shopping review quality bottom sheet. The parameter substitutes the partner website the user is coming from. The *text inside asterisks* denotes part of the string to bold, please leave the text inside the '*' so that it is bolded correctly. */ +"Shopping.ReviewQualityCard.Highlights.Label.v120" = "*Istaknuto* rezultira od %1@ recenzija u zadnjih 80 dana za koje vjerujemo da su pouzdane."; + +/* Highlights label from How we determine review quality card displayed in the shopping review quality bottom sheet. The parameter substitutes the partner website the user is coming from. The *text inside asterisks* denotes part of the string to bold, please leave the text inside the '*' so that it is bolded correctly. */ +"Shopping.ReviewQualityCard.Highlights.Label.v126" = "*Istaknuto* rezultira od %@ recenzija u zadnjih 80 dana za koje vjerujemo da su pouzdane."; + /* Title of the 'How we determine review quality' card displayed in the shopping review quality bottom sheet. */ "Shopping.ReviewQualityCard.Label.Title.v120" = "Kako određujemo kvalitetu recenzija"; +/* The title of the learn more button from How we determine review quality card displayed in the shopping review quality bottom sheet. The placeholder will be replaced with the Fakespot app name. */ +"Shopping.ReviewQualityCard.LearnMoreButton.Title.v120" = "Saznaj više o tome kako %@ određuje kvalitetu recenzija"; + +/* Mixed reviews label from How we determine review quality card displayed in the shopping review quality bottom sheet. */ +"Shopping.ReviewQualityCard.MixedReviews.Label.v120" = "Vjerujemo da postoji mješavina pouzdanih i nepouzdanih recenzija"; + +/* Reliable reviews label from How we determine review quality card displayed in the shopping review quality bottom sheet. */ +"Shopping.ReviewQualityCard.ReliableReviews.Label.v120" = "Pouzdane recenzije. Vjerujemo da su recenzije vjerojatno od stvarnih kupaca koji su ostavili iskrene, nepristrane recenzije."; + /* Label of the sub headline from How we determine review quality card displayed in the shopping review quality bottom sheet. The *text inside asterisks* denotes part of the string to bold, please leave the text inside the '*' so that it is bolded correctly. */ "Shopping.ReviewQualityCard.SubHeadline.Label.v120" = "Svakoj recenziji proizvoda dodjeljujemo *slovnu ocjenu* od A do F."; +/* Unreliable reviews label from How we determine review quality card displayed in the shopping review quality bottom sheet. */ +"Shopping.ReviewQualityCard.UnreliableReviews.Label.v120" = "Nepouzdane recenzije. Vjerujemo da su recenzije vjerojatno lažne ili od pristranih recenzenata."; + /* Accessibility label for the up chevron icon used to collapse or minimize the Settings Card within the shopping product review bottom sheet. */ "Shopping.SettingsCard.Collapse.AccessibilityLabel.v120" = "Sklopi karticu postavki"; @@ -97,6 +217,12 @@ /* Accessibility hint for the recommended products label and switch, grouped together. When the group is selected in VoiceOver mode, the hint is read to help the user understand what action can be performed. */ "Shopping.SettingsCard.Expand.GroupedRecommendedProductsAndSwitch.AccessibilityHint.v123" = "Dodirni dvaput za mijenjanje postavke."; +/* Accessibility label for the recommended products label and switch, grouped together. The first placeholder is for the recommended products label, and the second placeholder is for the state of the switch: On/Off. */ +"Shopping.SettingsCard.Expand.GroupedRecommendedProductsAndSwitch.AccessibilityLabel.v123" = "%1$@, gumb za prebacivanje %2$@."; + +/* Action title of the footer underneath the Settings Card displayed in the shopping review quality bottom sheet. The first parameter will be replaced by the Fakespot app name and the second parameter by the company name of Mozilla. */ +"Shopping.SettingsCard.Footer.Action.v120" = "Provjeru recenzija pokreće %1$@ od %2$@"; + /* Title of the settings card displayed in the shopping review quality bottom sheet. */ "Shopping.SettingsCard.Label.Title.v120" = "Postavke"; @@ -121,6 +247,9 @@ /* Label for the header of the Shopping Experience (Fakespot) sheet */ "Shopping.Sheet.Title.v120" = "Provjera recenzija"; +/* Text for body of error card displayed to the user when the device is disconnected from the network. */ +"Shopping.WarningCard.CheckNoConnection.Description.v120" = "Provjeri svoju mrežnu vezu i pokušaj ponovo učitati stranicu."; + /* Title for error card displayed to the user when the device is disconnected from the network. */ "Shopping.WarningCard.CheckNoConnection.Title.v120" = "Nema mrežne veze"; diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/TabToolbar.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/TabToolbar.strings new file mode 100644 index 000000000000..d49b69be89be --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/TabToolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the tab toolbar fire button in private mode, used to provide users a way to end and delete their private session data. */ +"TabToolbar.Accessibility.DataClearance.v122" = "Brisanje podataka"; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/TabsTray.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/TabsTray.strings index f355df56602e..d5f08de5dbf3 100644 --- a/firefox-ios/Shared/Supporting Files/hr.lproj/TabsTray.strings +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/TabsTray.strings @@ -10,6 +10,9 @@ /* This is the swipe action title for closing an inactive tab by swiping, located in the Inactive Tabs section of the Tabs Tray */ "InactiveTabs.TabTray.CloseSwipeActionTitle.v115" = "Zatvori"; +/* Users can disable syncing tabs from other devices. In the Sync Tabs panel of the Tab Tray, we inform the user tab syncing can be switched back on to view those tabs. */ +"TabsTray.Sync.SyncTabsDisabled.v116" = "Uključi sinkronizaciju kartica za pregled popisa kartica s tvojih drugih uređaja."; + /* Button label to sync tabs in your account */ "TabsTray.SyncTabs.SyncTabsButton.Title.v119" = "Sinkroniziraj kartice"; diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/Toolbar.strings index 54f9c4de7caa..82bfe2ebacda 100644 --- a/firefox-ios/Shared/Supporting Files/hr.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Nova kartica"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Zatvori ovu karticu"; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/ToolbarLocation.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/ToolbarLocation.strings new file mode 100644 index 000000000000..e3d1e903eca8 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/ToolbarLocation.strings @@ -0,0 +1,6 @@ +/* Contextual hints are little popups that appear for the users informing them of new features. This one indicates a user can navigate to the Settings page to move the search bar to the top. */ +"ContextualHints.Toolbar.Bottom.Description.v107" = "Ako želiš, pomakni alatnu traku gore."; + +/* Contextual hints are little popups that appear for the users informing them of new features. This one indicates a user can navigate to the Settings page to move the search bar to the bottom. */ +"ContextualHints.Toolbar.Top.Description.v107" = "Ako želiš, pomakni alatnu traku dolje."; + diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/Upgrade.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/Upgrade.strings index 834c9e1e9820..d52febc21c54 100644 --- a/firefox-ios/Shared/Supporting Files/hr.lproj/Upgrade.strings +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/Upgrade.strings @@ -1,6 +1,18 @@ /* Describes an action on the sync upgrade page in our Upgrade screens. This string will be on a button so user can sign up or login directly in the upgrade. */ "Upgrade.SyncSign.Action.v114" = "Prijavi se"; +/* Description string used to sign in to sync in the Upgrade screens. This screen is shown after user upgrades Firefox version. */ +"Upgrade.SyncSign.Description.v114" = "Nastavi gdje si stao/la s karticama s drugih uređaja na tvojoj početnoj stranici."; + +/* Title string used to sign in to sync in the Upgrade screens. This screen is shown after user upgrades Firefox version. */ +"Upgrade.SyncSign.Title.v114" = "Mijenjanje ekrana nikada nije bilo lakše"; + /* Describes the action on the first upgrade page in the Upgrade screen. This string will be on a button so user can continue the Upgrade. */ "Upgrade.Welcome.Action.v114" = "Postavi kao zadani preglednik"; +/* Description string used to welcome back users in the Upgrade screens. This screen is shown after user upgrades Firefox version. */ +"Upgrade.Welcome.Description.v114" = "Nove boje. Nova pogodnost. Ista predanost ljudima prije profita."; + +/* Title string used to welcome back users in the Upgrade screens. This screen is shown after user upgrades Firefox version. */ +"Upgrade.Welcome.Title.v114" = "Dobro došao, dobro došla u osobniji internet"; + diff --git a/firefox-ios/Shared/Supporting Files/hsb.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/hsb.lproj/EnhancedTrackingProtection.strings index 2143fd9c986d..88541b5313b1 100644 --- a/firefox-ios/Shared/Supporting Files/hsb.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/hsb.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Zwisk njewěsty"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Žane přesćěhowaki namakane"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Sydła přesahowace slědowace placki: %@"; @@ -31,8 +34,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Přesćěhowaki socialnych medijow: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Přesćěhowaki zablokowane: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/hu.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/hu.lproj/EditAddress.strings index 822affa971cc..15cc957b8489 100644 --- a/firefox-ios/Shared/Supporting Files/hu.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/hu.lproj/EditAddress.strings @@ -88,6 +88,9 @@ /* Label for the telephone number field, allowing users to input their contact number. This is essential for communication and service provision, ensuring contact details are autofilled correctly. */ "Addresses.EditAddress.AutofillAddressTel.v129" = "Telefon"; +/* Label for the input field for the townland, a specific type of land division used in rural areas. Enhances address detail for users in regions where townlands are a common addressing component. */ +"Addresses.EditAddress.AutofillAddressTownland.v129" = "Townland"; + /* Label for the field to input the name of a village or township. This is crucial for addresses in rural areas, ensuring the autofill feature accurately captures all necessary geographical details. */ "Addresses.EditAddress.AutofillAddressVillageTownship.v129" = "Falu vagy község"; @@ -127,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "A cím nem menthető"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "A cím nem távolítható el"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Próbálja újra"; diff --git a/firefox-ios/Shared/Supporting Files/hu.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/hu.lproj/EnhancedTrackingProtection.strings index 89cf1d1d148a..0bb2db1dc638 100644 --- a/firefox-ios/Shared/Supporting Files/hu.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/hu.lproj/EnhancedTrackingProtection.strings @@ -4,6 +4,9 @@ /* The text for the clear cookies and site data alert button inside the enhanced tracking protection screen. */ "Menu.EnhancedTrackingProtection.ClearData.AlertOkButton.v128" = "Törlés"; +/* The text for the clear cookies and site data alert inside the enhanced tracking protection screen. The placeholder will be replaced with the user's currently visited website */ +"Menu.EnhancedTrackingProtection.ClearData.AlertText.v128" = "A sütik és oldaladatok eltávolítása a(z) %@ webhelyről kijelentkeztetheti a webhelyekről, és törölheti a kosarait."; + /* The title for the clear cookies and site data alert inside the enhanced tracking protection screen. */ "Menu.EnhancedTrackingProtection.ClearData.AlertTitle.v128" = "Sütik és oldaladatok törlése"; @@ -28,22 +31,40 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Közösségimédia-követők: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Blokkolt követők: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ "Menu.EnhancedTrackingProtection.Details.Verifier.v128" = "Ellenőrizte: %@"; +/* Header for the enhanced tracking protection screen when the user has opted out of the feature. Placeholder will be replaced by the app name */ +"Menu.EnhancedTrackingProtection.Off.Header.v128" = "A %@ szolgálaton kívül van. Javasoljuk a védelmek ismételt bekapcsolását."; + /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Kikapcsolta a védelmeket"; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. + Header for the enhanced tracking protection screen when the user has selected to be protected. */ +"Menu.EnhancedTrackingProtection.On.Header.v128" = "Védve van. Ha látunk valamit, értesíteni fogjuk."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Legyen óvatos ezen az oldalon"; +/* Title for the enhanced tracking protection screen when the user has selected to be protected. The placeholder will have the value of the app name */ +"Menu.EnhancedTrackingProtection.On.Title.v128" = "A %@ résen van"; + /* The title for the privacy settings button inside the enhanced tracking protection screen. */ "Menu.EnhancedTrackingProtection.PrivacySettings.Title.v128" = "Adatvédelmi beállítások"; /* Title for the switch to enable/disable enhanced tracking protection inside the menu. */ "Menu.EnhancedTrackingProtection.Switch.Title.v128" = "Fokozott követés elleni védelem"; +/* A switch to disable enhanced tracking protection inside the menu. */ +"Menu.EnhancedTrackingProtection.SwitchOff.Text.v128" = "A védelem KI van kapcsolva. Javasoljuk, hogy kapcsolja be újra."; + +/* A switch to disable enhanced tracking protection inside the menu. */ +"Menu.EnhancedTrackingProtection.SwitchOff.Text.v129" = "A védelem KI van kapcsolva. Javasoljuk, hogy kapcsolja be újra."; + +/* A switch to disable enhanced tracking protection inside the menu. */ +"Menu.EnhancedTrackingProtection.SwitchOn.Text.v128" = "Ha valami nem működik ezen az oldalon, próbálja meg kikapcsolni."; + diff --git a/firefox-ios/Shared/Supporting Files/hu.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/hu.lproj/Microsurvey.strings index e43450218ae9..f34e1c32505a 100644 --- a/firefox-ios/Shared/Supporting Files/hu.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/hu.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Nincs kiválasztva"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Felmérés"; + diff --git a/firefox-ios/Shared/Supporting Files/hu.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/hu.lproj/Toolbar.strings new file mode 100644 index 000000000000..923b48d39b62 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hu.lproj/Toolbar.strings @@ -0,0 +1,6 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Új lap"; + +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Lap bezárása"; + diff --git a/firefox-ios/Shared/Supporting Files/hy-AM.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/hy-AM.lproj/EnhancedTrackingProtection.strings index d1464ab41b3e..fc7409c00e57 100644 --- a/firefox-ios/Shared/Supporting Files/hy-AM.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/hy-AM.lproj/EnhancedTrackingProtection.strings @@ -31,8 +31,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Սոցիալական մեդիայի հետագծումներ` %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Հետագծողներն արգելափակված են՝ %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/ia.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/ia.lproj/EnhancedTrackingProtection.strings index bc20e4c2aede..a2db7054d821 100644 --- a/firefox-ios/Shared/Supporting Files/ia.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/ia.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Connexion non secur"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Nulle traciatores trovate"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Cookies de traciamento inter sitos: %@"; @@ -31,8 +34,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Traciatores de retes social: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Traciatores blocate: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/is.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/is.lproj/EnhancedTrackingProtection.strings index bdf235da3b7d..030e1ba6bb35 100644 --- a/firefox-ios/Shared/Supporting Files/is.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/is.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Tenging er ekki örugg"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Engir rekjarar fundust"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Rakningarkökur milli vefsvæða: %@"; @@ -31,8 +34,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Samfélagsmiðlarekjarar: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Lokað á rekjara: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/it.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/it.lproj/EnhancedTrackingProtection.strings index f5d80561b253..014da643b184 100644 --- a/firefox-ios/Shared/Supporting Files/it.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/it.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Connessione non sicura"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Nessun elemento tracciante rilevato"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Cookie traccianti intersito: %@"; @@ -31,8 +34,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Traccianti dei social media: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Elementi traccianti bloccati: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/ja.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/ja.lproj/EnhancedTrackingProtection.strings index 0ad9e3f6db33..7f718b4e4418 100644 --- a/firefox-ios/Shared/Supporting Files/ja.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/ja.lproj/EnhancedTrackingProtection.strings @@ -31,8 +31,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "ソーシャルメディアトラッカー: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "ブロックされた追跡: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/kab.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/kab.lproj/EnhancedTrackingProtection.strings index f073887a1914..6d7dd4f17d0e 100644 --- a/firefox-ios/Shared/Supporting Files/kab.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/kab.lproj/EnhancedTrackingProtection.strings @@ -31,8 +31,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Ineḍfaṛen n iẓeḍwa inmettiyen: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Ineḍfaren ttusweḥlen: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/kk.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/kk.lproj/EnhancedTrackingProtection.strings index 8a1f1ac4c6c7..15d422718540 100644 --- a/firefox-ios/Shared/Supporting Files/kk.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/kk.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Байланыс қауіпсіз емес"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Трекерлер табылмады"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Сайтаралық бақылайтын cookie файлдары: %@"; @@ -31,8 +34,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Әлеуметтік желілер трекерлері: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Блокталған трекерлер: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/ko.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/ko.lproj/EnhancedTrackingProtection.strings index 90a233c938ca..6166d612cc83 100644 --- a/firefox-ios/Shared/Supporting Files/ko.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/ko.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "안전하지 않은 연결"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "추적기 없음"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "교차 사이트 추적 쿠키: %@"; @@ -31,8 +34,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "소셜 미디어 추적자: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "차단된 추적기: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/nb.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/nb.lproj/EnhancedTrackingProtection.strings index 4d028ea976b5..7ab6d5fc288c 100644 --- a/firefox-ios/Shared/Supporting Files/nb.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/nb.lproj/EnhancedTrackingProtection.strings @@ -31,8 +31,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Sporing via sosiale medier: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Sporere blokkert: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/nl.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/nl.lproj/EnhancedTrackingProtection.strings index dac209b9223b..aca50e279ff4 100644 --- a/firefox-ios/Shared/Supporting Files/nl.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/nl.lproj/EnhancedTrackingProtection.strings @@ -31,8 +31,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Sociale-mediatrackers: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Trackers geblokkeerd: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/nn.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/nn.lproj/EnhancedTrackingProtection.strings index 72ade1e691cb..cdd322017fad 100644 --- a/firefox-ios/Shared/Supporting Files/nn.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/nn.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Tilkoplinga er ikkje trygg"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Fann ingen sporarar"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Sporingsinfokapslar på tvers av nettstadar: %@"; @@ -31,8 +34,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Sosiale mediesporarar: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Sporarar blokkerte: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/nn.lproj/ScanQRCode.strings b/firefox-ios/Shared/Supporting Files/nn.lproj/ScanQRCode.strings index 293c423bdaf6..ed4d7c224809 100644 --- a/firefox-ios/Shared/Supporting Files/nn.lproj/ScanQRCode.strings +++ b/firefox-ios/Shared/Supporting Files/nn.lproj/ScanQRCode.strings @@ -5,5 +5,5 @@ "ScanQRCode.ConfirmOpenURL.DenyButton.v129" = "Avvis"; /* Text of the prompt to ask user permission to open a URL from a scanned QR code. Placeholder is app name. */ -"ScanQRCode.ConfirmOpenURL.Message.v129" = "Tillate %@ tå opne?"; +"ScanQRCode.ConfirmOpenURL.Message.v129" = "Tillate %@ å opne?"; diff --git a/firefox-ios/Shared/Supporting Files/pa-IN.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/pa-IN.lproj/EnhancedTrackingProtection.strings index c0c93e657881..356ab77d7ca5 100644 --- a/firefox-ios/Shared/Supporting Files/pa-IN.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/pa-IN.lproj/EnhancedTrackingProtection.strings @@ -31,8 +31,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "ਸਮਾਜਿਕ ਮੀਡਿਆ ਟਰੈਕਰ: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "ਪਾਬੰਦੀ ਲਾਏ ਟਰੈਕਰ: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/pl.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/pl.lproj/EnhancedTrackingProtection.strings index 6724515c143b..15290c3cf1b2 100644 --- a/firefox-ios/Shared/Supporting Files/pl.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/pl.lproj/EnhancedTrackingProtection.strings @@ -31,8 +31,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Elementy śledzące serwisów społecznościowych: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Zablokowane elementy śledzące: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/pt-BR.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/pt-BR.lproj/EnhancedTrackingProtection.strings index b9743aeabe08..967245e5d29a 100644 --- a/firefox-ios/Shared/Supporting Files/pt-BR.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/pt-BR.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Conexão não segura"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Nenhum rastreador encontrado"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Cookies de rastreamento entre sites: %@"; @@ -31,8 +34,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Rastreadores de mídias sociais: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Rastreadores bloqueados: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/pt-PT.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/pt-PT.lproj/EnhancedTrackingProtection.strings index abe11d32adfe..9e306740d0b9 100644 --- a/firefox-ios/Shared/Supporting Files/pt-PT.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/pt-PT.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Ligação insegura"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Não foram encontrados rastreadores"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Cookies de monitorização entre sites: %@"; @@ -31,8 +34,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Rastreadores de redes sociais: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Rastreadores bloqueados: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/rm.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/rm.lproj/EnhancedTrackingProtection.strings index eacec1784aea..7c3f2dbe6615 100644 --- a/firefox-ios/Shared/Supporting Files/rm.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/rm.lproj/EnhancedTrackingProtection.strings @@ -31,8 +31,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Fastizaders da social media: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Fastizaders bloccads: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/ru.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/ru.lproj/EnhancedTrackingProtection.strings index d1e3d25e5a3c..eacf941173c6 100644 --- a/firefox-ios/Shared/Supporting Files/ru.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/ru.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Незащищённое соединение"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Трекеров не найдено"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Межсайтовые отслеживающие куки: %@"; @@ -31,8 +34,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Трекеры социальных сетей: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Заблокировано трекеров: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/sk.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/sk.lproj/EnhancedTrackingProtection.strings index 46d42ca23957..2feb454e52ce 100644 --- a/firefox-ios/Shared/Supporting Files/sk.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/sk.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Pripojenie nie je zabezpečené"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Nenašli sa žiadne sledovacie prvky"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Sledovacie cookies tretích strán: %@"; @@ -31,8 +34,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Sledovacie prvky sociálnych sietí: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Zablokované sledovacie prvky: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/sl.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/sl.lproj/EnhancedTrackingProtection.strings index 73057c04b339..0fda15ff5683 100644 --- a/firefox-ios/Shared/Supporting Files/sl.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/sl.lproj/EnhancedTrackingProtection.strings @@ -31,8 +31,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Sledilcev družbenih omrežij: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Zavrnjenih sledilcev: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/sq.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/sq.lproj/EnhancedTrackingProtection.strings index 04180cb82ea4..c4174e83c610 100644 --- a/firefox-ios/Shared/Supporting Files/sq.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/sq.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Lidhje jo e sigurt"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "S’u gjetën gjurmues"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "“Cookies” gjurmimi nga sajte në sajte: %@"; @@ -31,8 +34,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Gjurmues prej mediash shoqërore: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Gjurmues të bllokuar: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/sq.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/sq.lproj/Microsurvey.strings index d04624e1274e..c9022ced3b38 100644 --- a/firefox-ios/Shared/Supporting Files/sq.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/sq.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "U shpërzgjodh"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Pyetësor"; + diff --git a/firefox-ios/Shared/Supporting Files/sq.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/sq.lproj/Toolbar.strings index 443e4894d9ed..8f83610cf20e 100644 --- a/firefox-ios/Shared/Supporting Files/sq.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/sq.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Skedë e Re"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Mbylle Këtë Skedë"; + diff --git a/firefox-ios/Shared/Supporting Files/su.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/su.lproj/EnhancedTrackingProtection.strings index f9519eef6a14..4c7b21974854 100644 --- a/firefox-ios/Shared/Supporting Files/su.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/su.lproj/EnhancedTrackingProtection.strings @@ -31,8 +31,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Pelacak média sosial: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Palacak dipeungpeuk: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/sv.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/sv.lproj/EnhancedTrackingProtection.strings index 2162cb2abf25..7bca90587bed 100644 --- a/firefox-ios/Shared/Supporting Files/sv.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/sv.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Anslutningen är inte säker"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Inga spårare hittades"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Globala spårningskakor: %@"; @@ -31,8 +34,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Sociala media-spårare: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Blockerade spårare: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/th.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/th.lproj/EnhancedTrackingProtection.strings index c1a1c27b28cc..60cd1544405d 100644 --- a/firefox-ios/Shared/Supporting Files/th.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/th.lproj/EnhancedTrackingProtection.strings @@ -31,8 +31,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "ตัวติดตามโซเชียลมีเดีย: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "ตัวติดตามที่ถูกปิดกั้น: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/tr.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/tr.lproj/EnhancedTrackingProtection.strings index 32fbab745f79..ba7dd3dc6c96 100644 --- a/firefox-ios/Shared/Supporting Files/tr.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/tr.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Bağlantı güvenli değil"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Hiç takip kodu bulunamadı"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Siteler arası takip çerezleri: %@"; @@ -31,8 +34,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Sosyal medya takip kodları: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Engellenen takip kodları: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/ug.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/ug.lproj/EnhancedTrackingProtection.strings index a3cc03fd5a5f..7ad58ec9f376 100644 --- a/firefox-ios/Shared/Supporting Files/ug.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/ug.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "باغلىنىش بىخەتەر ئەمەس"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "ھېچقانداق ئىزلىغۇچى تېپىلمىدى"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "بېكەت ھالقىغان ئىزلاش ساقلانمىسى: %@"; @@ -31,8 +34,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "ئىجتىمائىي تاراتقۇ ئىزلىغۇچ: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "ئىزلىغۇچى توسۇلدى: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/vi.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/vi.lproj/EnhancedTrackingProtection.strings index 38fa12e89396..95d3b59f1233 100644 --- a/firefox-ios/Shared/Supporting Files/vi.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/vi.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Kết nối không an toàn"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Không tìm thấy trình theo dõi"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Cookie theo dõi trên nhiều trang web: %@"; @@ -31,8 +34,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Trình theo truyền thông xã hội: %@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Trình theo dõi bị chặn: %@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/zh-CN.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/zh-CN.lproj/EnhancedTrackingProtection.strings index 079e75584a6f..38208254c721 100644 --- a/firefox-ios/Shared/Supporting Files/zh-CN.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/zh-CN.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "不安全连接"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "未发现跟踪器"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "跨站跟踪性 Cookie:%@ 个"; @@ -31,8 +34,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "社交媒体跟踪器:%@ 个"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "已拦截跟踪器:%@ 个"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/Supporting Files/zh-CN.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/zh-CN.lproj/Microsurvey.strings index 90afbc423a20..090c6691a02f 100644 --- a/firefox-ios/Shared/Supporting Files/zh-CN.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/zh-CN.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "未选中"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "问卷调查"; + diff --git a/firefox-ios/Shared/Supporting Files/zh-CN.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/zh-CN.lproj/Toolbar.strings index a33d20a5f22f..74cccebdb2aa 100644 --- a/firefox-ios/Shared/Supporting Files/zh-CN.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/zh-CN.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "新建标签页"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "关闭此标签页"; + diff --git a/firefox-ios/Shared/Supporting Files/zh-TW.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/zh-TW.lproj/EnhancedTrackingProtection.strings index e04f3bf54b63..33f39f1e2b2a 100644 --- a/firefox-ios/Shared/Supporting Files/zh-TW.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/zh-TW.lproj/EnhancedTrackingProtection.strings @@ -31,8 +31,7 @@ /* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "社交媒體追蹤器:%@"; -/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked - Text to let users know that no trackers were found on the current website. */ +/* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "追蹤器封鎖數量:%@"; /* Text to let users know the site verifier, where the placeholder represents the SSL certificate signer which is on the enhanced tracking protection screen after the user taps on the connection details. */ diff --git a/firefox-ios/Shared/hr.lproj/Default Browser.strings b/firefox-ios/Shared/hr.lproj/Default Browser.strings index 783974a59a5e..fa9269abf171 100644 --- a/firefox-ios/Shared/hr.lproj/Default Browser.strings +++ b/firefox-ios/Shared/hr.lproj/Default Browser.strings @@ -13,6 +13,15 @@ /* Description for small home tab banner shown that allows the user to switch their default browser to Firefox. */ "DefaultBrowserCard.NextLevel.Description.v108" = "Odaberi Firefox kao zadani preglednik za automatsku brzinu, sigurnost i privatnost."; +/* Title for small home tab banner shown that allows the user to switch their default browser to Firefox. */ +"DefaultBrowserCard.NextLevel.Title.v108" = "Poboljšaj svakodnevno pregledavanje"; + +/* Description for small home tab banner shown that allows the user to switch their default browser to Firefox. */ +"DefaultBrowserCard.PeaceOfMind.Description.v108" = "Firefox u prosjeku blokira više od 3000 programa za praćenje po korisniku svaki mjesec. Postavi nas kao standardni preglednik za bezbrižnu privatnost."; + +/* Title for small home tab banner shown that allows the user to switch their default browser to Firefox. */ +"DefaultBrowserCard.PeaceOfMind.Title.v108" = "Firefox pokriva privatnost"; + /* Title for small home tab banner shown that allows user to switch their default browser to Firefox. */ "DefaultBrowserCard.Title" = "Promijeni standardni preglednik"; diff --git a/firefox-ios/Shared/hr.lproj/Localizable.strings b/firefox-ios/Shared/hr.lproj/Localizable.strings index 467c8e0d23e9..af5f25d38a05 100644 --- a/firefox-ios/Shared/hr.lproj/Localizable.strings +++ b/firefox-ios/Shared/hr.lproj/Localizable.strings @@ -544,6 +544,9 @@ /* A label indicating the keyboard shortcut of finding text a user desires within a page again. This label is displayed in the Discoverability overlay when a user presses the Command key. The Discoverability overlay and shortcut become available only when a user has connected a hardware keyboard to an iPad. See https://drive.google.com/file/d/1gH3tbvDceg7yG5N67NIHS-AXgDgCzBHN/view?usp=sharing for more details. */ "Keyboard.Shortcuts.FindAgain" = "Ponovno pronađi"; +/* A label indicating the keyboard shortcut to reload a tab without it's cache. This label is displayed in the Discoverability overlay when a user presses the Command key. The Discoverability overlay and shortcut become available only when a user has connected a hardware keyboard to an iPad. */ +"Keyboard.Shortcuts.RefreshWithoutCache.v108" = "Učitaj ponovo zanemarujući predmemoriju"; + /* A label indicating a grouping of related keyboard shortcuts describing actions a user can do with Bookmarks. This label is displayed inside the Discoverability overlay when a user presses the Command key. The Discoverability overlay and shortcut become available only when a user has connected a hardware keyboard to an iPad. See https://drive.google.com/file/d/1gH3tbvDceg7yG5N67NIHS-AXgDgCzBHN/view?usp=sharing for more details. */ "Keyboard.Shortcuts.Section.Bookmark" = "Zabilješke"; @@ -1420,6 +1423,9 @@ /* Touch ID prompt subtitle when accessing logins and passwords */ "Settings.Passwords.FingerPrintReason.v103" = "Koristi otisak prsta za pristup lozinkama."; +/* Message shown when you enter Passwords screen for the first time. It explains how password are protected in the Firefox for iOS application. */ +"Settings.Passwords.OnboardingMessage.v103" = "Tvoje su lozinke sada zaštićene Face ID-om, Touch ID-om ili šifrom uređaja."; + /* Setting that appears in the Passwords screen to enable the built-in password manager so users can save their passwords. */ "Settings.Passwords.SavePasswords.v103" = "Spremi lozinke"; @@ -1474,6 +1480,9 @@ /* Label used as a toggle item in Settings. When this is off, the user is opting out of all studies. */ "Settings.Studies.Toggle.Title" = "Studije"; +/* Ddescription that appears in the settings screen to explain what Firefox Sync is useful for. */ +"Settings.Sync.ButtonDescription.v103" = "Prijavi se za sinkroniziranje kartica, zabilješki, lozinki i više."; + /* Button label that appears in the settings to prompt the user to sign in to Firefox for iOS sync service to sync and save data. */ "Settings.Sync.ButtonTitle.v103" = "Sinkroniziraj i spremi podatke"; @@ -1483,6 +1492,9 @@ /* This is the description for the setting that toggles the Inactive Tabs feature in the settings menu under the Tabs customization section. Inactive tabs are a separate section of tabs that appears in the Tab Tray, which can be enabled or not */ "Settings.Tabs.CustomizeTabsSection.InactiveTabs" = "Neaktivne kartice"; +/* This is the description for the setting that toggles the Inactive Tabs feature in the settings menu under the Tabs customization section. Inactive tabs are a separate section of tabs that appears in the Tab Tray, which can be enabled or not */ +"Settings.Tabs.CustomizeTabsSection.InactiveTabsDescription.v101" = "Kartice koje nisu pogledane u zadnja dva tjedna premještaju se u odjeljak neaktivnih kartica."; + /* In the settings menu, in the Tabs customization section, this is the title for the setting that toggles the Tab Groups feature - where tabs from related searches are grouped - on or off */ "Settings.Tabs.CustomizeTabsSection.TabGroups" = "Grupe kartica"; @@ -1504,6 +1516,9 @@ /* Dismiss button for the tracker protection alert. */ "Settings.TrackingProtection.Alert.Button" = "U redu, razumijem"; +/* Decription for the tracker protection alert. */ +"Settings.TrackingProtection.Alert.Description" = "Ako web stranica ne radi prema očekivanjima, dodirni lokot u adresnoj traci i isključi poboljšanu zaštitu od praćenja za tu stranicu."; + /* Title for the tracker protection alert. */ "Settings.TrackingProtection.Alert.Title" = "Oprez!"; @@ -1516,6 +1531,12 @@ /* Additional information about your Enhanced Tracking Protection */ "Settings.TrackingProtection.ProtectionCellFooter" = "Smanjuje broj ciljanih oglasa i pomaže spriječiti oglašivače da prate tvoje kretanje internetom."; +/* Footer information for tracker protection level. */ +"Settings.TrackingProtection.ProtectionLevel.Footer" = "Ako web stranica ne radi prema očekivanjima, dodirni lokot u adresnoj traci i isključi poboljšanu zaštitu od praćenja za tu stranicu."; + +/* Footer information for tracker protection level. */ +"Settings.TrackingProtection.ProtectionLevel.Footer.Lock" = "Ako web stranica ne radi prema očekivanjima, dodirni lokot u adresnoj traci i isključi poboljšanu zaštitu od praćenja za tu stranicu."; + /* Description for standard level tracker protection */ "Settings.TrackingProtection.ProtectionLevelStandard.Description" = "Dopušta neke programe za praćenje, kako bi web stranice mogle ispravno funkcionirati."; From 2b320d529d2b6fb890a7c4a3a335a67f6cee79f3 Mon Sep 17 00:00:00 2001 From: PARAIPAN SORIN <51127880+PARAIPAN9@users.noreply.github.com> Date: Tue, 13 Aug 2024 11:39:32 +0300 Subject: [PATCH 071/128] Add FXIOS-9764 - Url of homepage is not displayed correctly anymore (#21469) * Add individual action for reader mode state * Fix indentation and revert flag * Resolve state issues --- .../Views/BrowserViewController.swift | 4 +- .../Toolbars/Redux/AddressBarState.swift | 13 +++++++ .../Toolbars/Redux/ToolbarMiddleware.swift | 37 ++++++++++++++----- .../Browser/Toolbars/Redux/ToolbarState.swift | 19 +++++++++- 4 files changed, 60 insertions(+), 13 deletions(-) diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift index 78c2bb32806f..51b17b983987 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift @@ -1715,6 +1715,7 @@ class BrowserViewController: UIViewController, if isToolbarRefactorEnabled { let action = ToolbarMiddlewareAction( isLoading: loading, + url: tab.url?.displayURL, windowUUID: windowUUID, actionType: ToolbarMiddlewareActionType.websiteLoadingStateDidChange ) @@ -1814,6 +1815,7 @@ class BrowserViewController: UIViewController, if isToolbarRefactorEnabled { let action = ToolbarMiddlewareAction( lockIconImageName: lockIconImageName(for: tab), + url: tab?.url?.displayURL, readerModeState: readerModeState, windowUUID: windowUUID, actionType: ToolbarMiddlewareActionType.readerModeStateChanged @@ -1828,8 +1830,6 @@ class BrowserViewController: UIViewController, /// Call this whenever the page URL changes. fileprivate func updateURLBarDisplayURL(_ tab: Tab) { guard !isToolbarRefactorEnabled else { - guard tab.webView?.hasOnlySecureContent == true else { return } - let action = ToolbarMiddlewareAction( isShowingNavigationToolbar: ToolbarHelper().shouldShowNavigationToolbar(for: traitCollection), lockIconImageName: lockIconImageName(for: tab), diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/AddressBarState.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/AddressBarState.swift index 12c9df104ac0..2a11dd205893 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/AddressBarState.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/AddressBarState.swift @@ -91,6 +91,19 @@ struct AddressBarState: StateType, Equatable { isEditing: state.isEditing ) + case ToolbarActionType.readerModeStateChanged: + guard let addressToolbarModel = (action as? ToolbarAction)?.addressToolbarModel else { return state } + + return AddressBarState( + windowUUID: state.windowUUID, + navigationActions: state.navigationActions, + pageActions: addressToolbarModel.pageActions ?? state.pageActions, + browserActions: state.browserActions, + borderPosition: state.borderPosition, + url: addressToolbarModel.url, + lockIconImageName: addressToolbarModel.lockIconImageName + ) + case ToolbarActionType.addressToolbarActionsDidChange: guard let addressToolbarModel = (action as? ToolbarAction)?.addressToolbarModel else { return state } diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift index 8614054cd53e..192e45b7098d 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift @@ -133,10 +133,12 @@ final class ToolbarMiddleware: FeatureFlaggable { case ToolbarMiddlewareActionType.didTapButton: resolveToolbarMiddlewareButtonTapActions(action: action, state: state) - case ToolbarMiddlewareActionType.urlDidChange, - ToolbarMiddlewareActionType.readerModeStateChanged: + case ToolbarMiddlewareActionType.urlDidChange: updateUrlAndActions(action: action, state: state) + case ToolbarMiddlewareActionType.readerModeStateChanged: + updateReaderModeState(action: action, state: state) + case ToolbarMiddlewareActionType.didStartEditingUrl: updateAddressToolbarNavigationActions(action: action, state: state, @@ -394,6 +396,23 @@ final class ToolbarMiddleware: FeatureFlaggable { store.dispatch(toolbarAction) } + private func updateReaderModeState(action: ToolbarMiddlewareAction, + state: AppState) { + guard let readerModeState = action.readerModeState, + let addressToolbarModel = generateAddressToolbarActions( + action: action, + state: state, + lockIconImageName: action.lockIconImageName, + isEditing: false + ) else { return } + + let toolbarAction = ToolbarAction(addressToolbarModel: addressToolbarModel, + readerModeState: readerModeState, + windowUUID: action.windowUUID, + actionType: ToolbarActionType.readerModeStateChanged) + store.dispatch(toolbarAction) + } + private func updateNumberOfTabs(action: ToolbarMiddlewareAction, state: AppState) { guard let numberOfTabs = action.numberOfTabs, @@ -523,18 +542,15 @@ final class ToolbarMiddleware: FeatureFlaggable { ) -> [ToolbarActionState] { var actions = [ToolbarActionState]() - let isUrlChangeAction = action.actionType as? ToolbarMiddlewareActionType == .urlDidChange - let url = isUrlChangeAction ? action.url : toolbarState.addressToolbar.url + let isReaderModeAction = action.actionType as? ToolbarMiddlewareActionType == .readerModeStateChanged + let readerModeState = isReaderModeAction ? action.readerModeState : toolbarState.readerModeState + readerModeAction.shouldDisplayAsHighlighted = readerModeState == .active - guard url != nil, !isEditing else { + guard action.url != nil, !isEditing else { // On homepage we only show the QR code button return [qrCodeScanAction] } - let isReaderModeAction = action.actionType as? ToolbarMiddlewareActionType == .readerModeStateChanged - let readerModeState = isReaderModeAction ? action.readerModeState : toolbarState.readerModeState - readerModeAction.shouldDisplayAsHighlighted = readerModeState == .active - switch readerModeState { case .active, .available: actions.append(readerModeAction) @@ -590,7 +606,8 @@ final class ToolbarMiddleware: FeatureFlaggable { let pageActions = addressToolbarPageActions(action: action, toolbarState: toolbarState, isEditing: editing) let browserActions = addressToolbarBrowserActions(action: action, state: state) let isUrlChangeAction = action.actionType as? ToolbarMiddlewareActionType == .urlDidChange - let url = isUrlChangeAction ? action.url : toolbarState.addressToolbar.url + let isReaderModeAction = action.actionType as? ToolbarMiddlewareActionType == .readerModeStateChanged + let url = (isUrlChangeAction || isReaderModeAction) ? action.url : toolbarState.addressToolbar.url let addressToolbarModel = AddressToolbarModel( navigationActions: navigationActions, diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarState.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarState.swift index 803b4b77bcf5..38c5a1440b1a 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarState.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarState.swift @@ -116,7 +116,7 @@ struct ToolbarState: ScreenState, Equatable { navigationToolbar: NavigationBarState.reducer(state.navigationToolbar, toolbarAction), isShowingNavigationToolbar: toolbarAction.isShowingNavigationToolbar ?? state.isShowingNavigationToolbar, isShowingTopTabs: toolbarAction.isShowingTopTabs ?? state.isShowingTopTabs, - readerModeState: toolbarAction.readerModeState ?? state.readerModeState, + readerModeState: state.readerModeState, badgeImageName: state.badgeImageName, maskImageName: state.maskImageName, canGoBack: toolbarAction.canGoBack ?? state.canGoBack, @@ -191,6 +191,23 @@ struct ToolbarState: ScreenState, Equatable { canGoForward: state.canGoForward, numberOfTabs: state.numberOfTabs) + case ToolbarActionType.readerModeStateChanged: + guard let toolbarAction = action as? ToolbarAction else { return state } + return ToolbarState( + windowUUID: state.windowUUID, + toolbarPosition: state.toolbarPosition, + isPrivateMode: state.isPrivateMode, + addressToolbar: AddressBarState.reducer(state.addressToolbar, toolbarAction), + navigationToolbar: NavigationBarState.reducer(state.navigationToolbar, toolbarAction), + isShowingNavigationToolbar: state.isShowingNavigationToolbar, + isShowingTopTabs: state.isShowingTopTabs, + readerModeState: toolbarAction.readerModeState, + badgeImageName: state.badgeImageName, + maskImageName: state.maskImageName, + canGoBack: state.canGoBack, + canGoForward: state.canGoForward, + numberOfTabs: state.numberOfTabs) + default: return ToolbarState( windowUUID: state.windowUUID, From cc9a004daa996170a3976c2df9ffe111d46f611c Mon Sep 17 00:00:00 2001 From: PARAIPAN SORIN <51127880+PARAIPAN9@users.noreply.github.com> Date: Tue, 13 Aug 2024 19:21:25 +0300 Subject: [PATCH 072/128] Add overlay mode for paste a11y action (#21520) --- .../BrowserViewController/Views/BrowserViewController.swift | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift index 51b17b983987..fa05bd0eaa97 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift @@ -751,7 +751,11 @@ class BrowserViewController: UIViewController, pasteAction = AccessibleAction(name: .PasteTitle, handler: { [weak self] () -> Bool in guard let self, let pasteboardContents = UIPasteboard.general.string else { return false } // Enter overlay mode and make the search controller appear. - overlayManager.openSearch(with: pasteboardContents) + if isToolbarRefactorEnabled { + addressToolbarContainer.enterOverlayMode(pasteboardContents, pasted: true, search: true) + } else { + overlayManager.openSearch(with: pasteboardContents) + } searchController?.searchTelemetry?.interactionType = .pasted return true }) From 1dd1804cefc9f5a9ba0f46d6e438e3b5506ac5f8 Mon Sep 17 00:00:00 2001 From: Ione Souza Junior Date: Wed, 14 Aug 2024 04:06:10 -0300 Subject: [PATCH 073/128] Refactor FXIOS-7301 - Remove 1 closure_body_length violation from Experiments.swift (3/3) (#21338) * Extract the NimbusBuilder to a new function * Use the build nimbus function * Change access modifier --- .../Client/Experiments/Experiments.swift | 42 ++++++++++++------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/firefox-ios/Client/Experiments/Experiments.swift b/firefox-ios/Client/Experiments/Experiments.swift index c0b7566142ec..582df5953ed2 100644 --- a/firefox-ios/Client/Experiments/Experiments.swift +++ b/firefox-ios/Client/Experiments/Experiments.swift @@ -157,22 +157,10 @@ enum Experiments { return NimbusDisabled.shared } - let bundles = [ - Bundle.main, - Strings.bundle, - Strings.bundle.fallbackTranslationBundle(language: "en-US") - ].compactMap { $0 } - - return NimbusBuilder(dbPath: dbPath) - .with(url: remoteSettingsURL) - .using(previewCollection: usePreviewCollection()) - .with(errorReporter: errorReporter) - .with(initialExperiments: initialExperiments) - .isFirstRun(isFirstRun) - .with(bundles: bundles) - .with(featureManifest: FxNimbus.shared) - .with(commandLineArgs: CommandLine.arguments) - .build(appInfo: getAppSettings(isFirstRun: isFirstRun)) + return buildNimbus(dbPath: dbPath, + errorReporter: errorReporter, + initialExperiments: initialExperiments, + isFirstRun: isFirstRun) }() private static func getAppSettings(isFirstRun: Bool) -> NimbusAppSettings { @@ -203,6 +191,28 @@ enum Experiments { return isReviewCheckerEnabled } + private static func buildNimbus(dbPath: String, + errorReporter: @escaping NimbusErrorReporter, + initialExperiments: URL?, + isFirstRun: Bool) -> NimbusInterface { + let bundles = [ + Bundle.main, + Strings.bundle, + Strings.bundle.fallbackTranslationBundle(language: "en-US") + ].compactMap { $0 } + + return NimbusBuilder(dbPath: dbPath) + .with(url: remoteSettingsURL) + .using(previewCollection: usePreviewCollection()) + .with(errorReporter: errorReporter) + .with(initialExperiments: initialExperiments) + .isFirstRun(isFirstRun) + .with(bundles: bundles) + .with(featureManifest: FxNimbus.shared) + .with(commandLineArgs: CommandLine.arguments) + .build(appInfo: getAppSettings(isFirstRun: isFirstRun)) + } + /// A convenience method to initialize the `NimbusApi` object at startup. /// /// This includes opening the database, connecting to the Remote Settings server, and downloading From 6084b0bdaecde77636754c971a413386187b024f Mon Sep 17 00:00:00 2001 From: Winnie Teichmann <4530+thatswinnie@users.noreply.github.com> Date: Wed, 14 Aug 2024 08:26:58 +0100 Subject: [PATCH 074/128] Refactor FXIOS-9524 Update share icon with latest from Acorn (#21107) * Add new share icon * Use new share icon everywhere in place of shareApple * Remove shareAppleLarge --- .../Constants/StandardImageIdentifiers.swift | 2 +- .../shareAppleLarge.imageset/shareAppleLarge.pdf | Bin 1643 -> 0 bytes .../Contents.json | 2 +- .../shareLarge.imageset/shareLarge.pdf | Bin 0 -> 1873 bytes .../Actions/ActionProviderBuilder.swift | 2 +- .../Frontend/Browser/MainMenuActionHelper.swift | 4 ++-- .../Legacy/LegacyTabPeekViewController.swift | 2 +- .../Toolbars/Redux/ToolbarMiddleware.swift | 2 +- .../Home/HomepageContextMenuHelper.swift | 2 +- .../Library/LibraryPanelContextMenu.swift | 2 +- .../Frontend/Toolbar+URLBar/ShareButton.swift | 2 +- .../Tests/XCUITests/BookmarksTests.swift | 2 +- .../Tests/XCUITests/FxScreenGraph.swift | 2 +- .../Tests/XCUITests/JumpBackInTests.swift | 2 +- .../Tests/XCUITests/PhotonActionSheetTests.swift | 2 +- 15 files changed, 14 insertions(+), 14 deletions(-) delete mode 100644 firefox-ios/Client/Assets/Images.xcassets/shareAppleLarge.imageset/shareAppleLarge.pdf rename firefox-ios/Client/Assets/Images.xcassets/{shareAppleLarge.imageset => shareLarge.imageset}/Contents.json (82%) create mode 100644 firefox-ios/Client/Assets/Images.xcassets/shareLarge.imageset/shareLarge.pdf diff --git a/BrowserKit/Sources/Common/Constants/StandardImageIdentifiers.swift b/BrowserKit/Sources/Common/Constants/StandardImageIdentifiers.swift index 558e24127856..f7bd51422a91 100644 --- a/BrowserKit/Sources/Common/Constants/StandardImageIdentifiers.swift +++ b/BrowserKit/Sources/Common/Constants/StandardImageIdentifiers.swift @@ -95,7 +95,7 @@ public struct StandardImageIdentifiers { public static let readingListAdd = "readingListAddLarge" public static let search = "searchLarge" public static let settings = "settingsLarge" - public static let shareApple = "shareAppleLarge" + public static let share = "shareLarge" public static let shield = "shieldLarge" public static let shieldSlash = "shieldSlashLarge" public static let shipping = "shippingLarge" diff --git a/firefox-ios/Client/Assets/Images.xcassets/shareAppleLarge.imageset/shareAppleLarge.pdf b/firefox-ios/Client/Assets/Images.xcassets/shareAppleLarge.imageset/shareAppleLarge.pdf deleted file mode 100644 index 7bf0bf5aa5a20feb6923ac3ea847e3c90ad2bcb9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1643 zcmb7_O;6k~5Qgvm6>~v?!#Wu|j%^7cm8DcwTa_-op&rt#fvt9vHVGB&uVX50c=WJ40hD5si_F4`5;k^;n65;O3K;qz!emtO%$vg40>LRN3Se}#gkw~_-RW#lKxTCa z;&r+ZHXkMx#-v^lB~cEm74@EPf2wgTBEXVGiUaleLbQXjKtucaB#fRS7P4K=-`8B2 zxCD`^sZIP`7(e=HLik}YOb$#_5e7#VFb$OCT~*ax3pYP#z|fO?|M%NLa#h^95qxpm zU2$GN!p;1tgrG&xHm@d28`stkP3cV3SRbR4(!!JWYIZhJB$ iCE3(<2VQWW;N*Ju-%<4aZ=qfjN5Qgvm6~0tz59@gB_)DrP(Je&?5M|4);t;ZFyJ$CoO^OP?o^i4nyR-+$ zDf`6p_0D+q=<4Ef0m3l`T=MSgH^%wtDL*@7O}mainaX+bzG?4aVw-! zUP**OXcrSk*V;pn@gOlw*6ZL)WKLK$o_mQ!TO|YFIWs2hY#u|45P|`fC-XwZTXxTG zS<62Cx74VV1*PRbD6Qu9IN`K+PNL9&5(a0YSO-R3vcjS$5K_yrz{##oO5+zp!(nltx0>wQ^1_QEZ#R;gG5fJW+5ofhkI2ln(kNN{OROf>d9MLL#Je z2#u4aU5Eoi5dCSKq7fPq{HQ8Is^%#SfD;FtAVwZ1OCqvH863+Tk=hC7a%Z#@;L709 zyu_O~23cSZFiu9wCb62OHqgN>LW!3#>P--D&UmXMnu8F^)t+H4c4CL}C;(|dc@U`? zx}6pYv29|R_+*>0`69*bcUW!n9*iq*+K;GLw zaaG+l2k@a;Z>sa|k>8}7L6=6A^K_=S+0&}&yN7+<^gJ%=)xq7eYlo)Ah;d8L@T%G) z}T^!vm5}A6h~h^NbIl5om=~|Ak5{@hLLkpP`Tphkdo#HhUJk_x1wi uIPSY$bHa}|>yt^8V%2p6j|Gnc7uTEL4Q4<7`BnR2EC;Lsc69Xmv literal 0 HcmV?d00001 diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Actions/ActionProviderBuilder.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Actions/ActionProviderBuilder.swift index 0cb890bc3cac..bb1d44224a8e 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Actions/ActionProviderBuilder.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Actions/ActionProviderBuilder.swift @@ -106,7 +106,7 @@ class ActionProviderBuilder { contentContainer: ContentContainer) { actions.append(UIAction( title: .ContextMenuShareLink, - image: UIImage.templateImageNamed(StandardImageIdentifiers.Large.shareApple), + image: UIImage.templateImageNamed(StandardImageIdentifiers.Large.share), identifier: UIAction.Identifier("linkContextMenu.share") ) { _ in guard let tab = tabManager[webView], diff --git a/firefox-ios/Client/Frontend/Browser/MainMenuActionHelper.swift b/firefox-ios/Client/Frontend/Browser/MainMenuActionHelper.swift index 9b641cc3b25f..88f7eaa7b65a 100644 --- a/firefox-ios/Client/Frontend/Browser/MainMenuActionHelper.swift +++ b/firefox-ios/Client/Frontend/Browser/MainMenuActionHelper.swift @@ -568,7 +568,7 @@ class MainMenuActionHelper: PhotonActionSheetProtocol, private func getShareFileAction() -> PhotonRowActions { return SingleActionViewModel(title: .AppMenu.AppMenuSharePageTitleString, - iconString: StandardImageIdentifiers.Large.shareApple) { _ in + iconString: StandardImageIdentifiers.Large.share) { _ in guard let tab = self.selectedTab, let url = tab.url else { return } @@ -579,7 +579,7 @@ class MainMenuActionHelper: PhotonActionSheetProtocol, private func getShareAction() -> PhotonRowActions { return SingleActionViewModel(title: .AppMenu.Share, - iconString: StandardImageIdentifiers.Large.shareApple) { _ in + iconString: StandardImageIdentifiers.Large.share) { _ in guard let tab = self.selectedTab, let url = tab.canonicalURL?.displayURL else { return } TelemetryWrapper.recordEvent(category: .action, method: .tap, object: .sharePageWith) diff --git a/firefox-ios/Client/Frontend/Browser/Tabs/Legacy/LegacyTabPeekViewController.swift b/firefox-ios/Client/Frontend/Browser/Tabs/Legacy/LegacyTabPeekViewController.swift index 132a450ad237..151723c3e616 100644 --- a/firefox-ios/Client/Frontend/Browser/Tabs/Legacy/LegacyTabPeekViewController.swift +++ b/firefox-ios/Client/Frontend/Browser/Tabs/Legacy/LegacyTabPeekViewController.swift @@ -88,7 +88,7 @@ class LegacyTabPeekViewController: UIViewController, WKNavigationDelegate { if self.hasRemoteClients { actions.append(UIAction( title: .AppMenu.TouchActions.SendToDeviceTitle, - image: UIImage.templateImageNamed(StandardImageIdentifiers.Large.shareApple), + image: UIImage.templateImageNamed(StandardImageIdentifiers.Large.share), identifier: nil ) { [weak self] _ in guard let wself = self, diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift index 192e45b7098d..36a4fd568891 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift @@ -80,7 +80,7 @@ final class ToolbarMiddleware: FeatureFlaggable { lazy var shareAction = ToolbarActionState( actionType: .share, - iconName: StandardImageIdentifiers.Large.shareApple, + iconName: StandardImageIdentifiers.Large.share, isEnabled: true, a11yLabel: .TabLocationShareAccessibilityLabel, a11yId: AccessibilityIdentifiers.Toolbar.shareButton) diff --git a/firefox-ios/Client/Frontend/Home/HomepageContextMenuHelper.swift b/firefox-ios/Client/Frontend/Home/HomepageContextMenuHelper.swift index 3b18a9a62bf6..69b8f17d1987 100644 --- a/firefox-ios/Client/Frontend/Home/HomepageContextMenuHelper.swift +++ b/firefox-ios/Client/Frontend/Home/HomepageContextMenuHelper.swift @@ -243,7 +243,7 @@ class HomepageContextMenuHelper: HomepageContextMenuProtocol { /// - Returns: Share action private func getShareAction(site: Site, sourceView: UIView?) -> PhotonRowActions { return SingleActionViewModel(title: .ShareContextMenuTitle, - iconString: StandardImageIdentifiers.Large.shareApple, + iconString: StandardImageIdentifiers.Large.share, allowIconScaling: true, tapHandler: { _ in guard let url = URL(string: site.url, invalidCharacters: false) else { return } diff --git a/firefox-ios/Client/Frontend/Library/LibraryPanelContextMenu.swift b/firefox-ios/Client/Frontend/Library/LibraryPanelContextMenu.swift index 0b740737a471..0466faefa729 100644 --- a/firefox-ios/Client/Frontend/Library/LibraryPanelContextMenu.swift +++ b/firefox-ios/Client/Frontend/Library/LibraryPanelContextMenu.swift @@ -111,7 +111,7 @@ extension LibraryPanelContextMenu { func getShareAction(site: Site, sourceView: UIView, delegate: LibraryPanelCoordinatorDelegate?) -> PhotonRowActions { return SingleActionViewModel( title: .ShareContextMenuTitle, - iconString: StandardImageIdentifiers.Large.shareApple) { _ in + iconString: StandardImageIdentifiers.Large.share) { _ in guard let siteURL = URL(string: site.url, invalidCharacters: false) else { return } delegate?.shareLibraryItem(url: siteURL, sourceView: sourceView) }.items diff --git a/firefox-ios/Client/Frontend/Toolbar+URLBar/ShareButton.swift b/firefox-ios/Client/Frontend/Toolbar+URLBar/ShareButton.swift index 4e4c1f6c7b1b..bb1d590a8666 100644 --- a/firefox-ios/Client/Frontend/Toolbar+URLBar/ShareButton.swift +++ b/firefox-ios/Client/Frontend/Toolbar+URLBar/ShareButton.swift @@ -37,7 +37,7 @@ class ShareButton: UIButton { super.init(frame: frame) clipsToBounds = false - setImage(UIImage.templateImageNamed(StandardImageIdentifiers.Large.shareApple), for: .normal) + setImage(UIImage.templateImageNamed(StandardImageIdentifiers.Large.share), for: .normal) imageView?.contentMode = .scaleAspectFit configuration = .plain() } diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/BookmarksTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/BookmarksTests.swift index fa471874b6b7..4b32dc66290e 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/BookmarksTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/BookmarksTests.swift @@ -369,7 +369,7 @@ class BookmarksTests: BaseTestCase { mozWaitForElementToExist(ContextMenuTable.cells.otherElements[StandardImageIdentifiers.Large.plus]) mozWaitForElementToExist(ContextMenuTable.cells.otherElements[StandardImageIdentifiers.Large.privateMode]) mozWaitForElementToExist(ContextMenuTable.cells.otherElements[StandardImageIdentifiers.Large.bookmarkSlash]) - mozWaitForElementToExist(ContextMenuTable.cells.otherElements[StandardImageIdentifiers.Large.shareApple]) + mozWaitForElementToExist(ContextMenuTable.cells.otherElements[StandardImageIdentifiers.Large.share]) } // https://mozilla.testrail.io/index.php?/cases/view/2307054 diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/FxScreenGraph.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/FxScreenGraph.swift index fff388ce9ff6..02e60ee08d3c 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/FxScreenGraph.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/FxScreenGraph.swift @@ -1140,7 +1140,7 @@ func createScreenGraph(for test: XCTestCase, with app: XCUIApplication) -> MMScr } screenState.tap( - app.tables.otherElements[StandardImageIdentifiers.Large.shareApple], + app.tables.otherElements[StandardImageIdentifiers.Large.share], forAction: Action.ShareBrowserTabMenuOption ) { userState in } diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/JumpBackInTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/JumpBackInTests.swift index 01961b944b20..5a1336a5e5a1 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/JumpBackInTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/JumpBackInTests.swift @@ -167,6 +167,6 @@ class JumpBackInTests: BaseTestCase { mozWaitForElementToExist(ContextMenuTable.cells.otherElements[StandardImageIdentifiers.Large.plus]) mozWaitForElementToExist(ContextMenuTable.cells.otherElements[StandardImageIdentifiers.Large.privateMode]) mozWaitForElementToExist(ContextMenuTable.cells.otherElements[StandardImageIdentifiers.Large.bookmark]) - mozWaitForElementToExist(ContextMenuTable.cells.otherElements[StandardImageIdentifiers.Large.shareApple]) + mozWaitForElementToExist(ContextMenuTable.cells.otherElements[StandardImageIdentifiers.Large.share]) } } diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/PhotonActionSheetTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/PhotonActionSheetTests.swift index d918b4e613ad..b863227bfafe 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/PhotonActionSheetTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/PhotonActionSheetTests.swift @@ -72,7 +72,7 @@ class PhotonActionSheetTests: BaseTestCase { // mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.shareButton], timeout: 10) // app.buttons[AccessibilityIdentifiers.Toolbar.shareButton].tap() navigator.goto(BrowserTabMenu) - app.otherElements[StandardImageIdentifiers.Large.shareApple].tap() + app.otherElements[StandardImageIdentifiers.Large.share].tap() if #unavailable(iOS 16) { mozWaitForElementToExist(app.otherElements["ActivityListView"].navigationBars["UIActivityContentView"]) From eb41f4c8f7bd85e661268188633d9e0d2a68aa89 Mon Sep 17 00:00:00 2001 From: dragosb01 <134391433+dragosb01@users.noreply.github.com> Date: Wed, 14 Aug 2024 11:42:46 +0300 Subject: [PATCH 075/128] Add MTE-3284 - back arrow navigation test (#21504) --- .../ExperimentIntegrationTests.xctestplan | 1 + .../Tests/Smoketest3.xctestplan | 1 + .../Tests/Smoketest4.xctestplan | 1 + .../Tests/XCUITests/NavigationTest.swift | 23 +++++++++++++++++++ 4 files changed, 26 insertions(+) diff --git a/firefox-ios/firefox-ios-tests/Tests/ExperimentIntegrationTests.xctestplan b/firefox-ios/firefox-ios-tests/Tests/ExperimentIntegrationTests.xctestplan index fb9a36660e40..3e77bcc58091 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ExperimentIntegrationTests.xctestplan +++ b/firefox-ios/firefox-ios-tests/Tests/ExperimentIntegrationTests.xctestplan @@ -75,6 +75,7 @@ "LoginTest", "MicrosurveyTests", "MultiWindowTests", + "NavigationTest", "NightModeTests", "OpeningScreenTests", "PerformanceTests", diff --git a/firefox-ios/firefox-ios-tests/Tests/Smoketest3.xctestplan b/firefox-ios/firefox-ios-tests/Tests/Smoketest3.xctestplan index 15304943a624..ddb94d474ca3 100644 --- a/firefox-ios/firefox-ios-tests/Tests/Smoketest3.xctestplan +++ b/firefox-ios/firefox-ios-tests/Tests/Smoketest3.xctestplan @@ -94,6 +94,7 @@ "LoginTest", "MicrosurveyTests", "MultiWindowTests", + "NavigationTest\/testBackArrowNavigation()", "NavigationTest\/testBookmarkLink()", "NavigationTest\/testCopyLink()", "NavigationTest\/testCopyLinkPrivateMode()", diff --git a/firefox-ios/firefox-ios-tests/Tests/Smoketest4.xctestplan b/firefox-ios/firefox-ios-tests/Tests/Smoketest4.xctestplan index 3d7dff4351d1..568e7bc380c0 100644 --- a/firefox-ios/firefox-ios-tests/Tests/Smoketest4.xctestplan +++ b/firefox-ios/firefox-ios-tests/Tests/Smoketest4.xctestplan @@ -84,6 +84,7 @@ "LoginTest\/testSearchLogin()", "MicrosurveyTests", "MultiWindowTests", + "NavigationTest\/testBackArrowNavigation()", "NavigationTest\/testBookmarkLink()", "NavigationTest\/testCopyLink()", "NavigationTest\/testCopyLinkPrivateMode()", diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/NavigationTest.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/NavigationTest.swift index 0f629761da47..8c893bf85f0e 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/NavigationTest.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/NavigationTest.swift @@ -482,6 +482,29 @@ class NavigationTest: BaseTestCase { mozWaitForElementToExist(app.tables["Bookmarks List"].staticTexts[website_2["link"]!]) } + // https://mozilla.testrail.io/index.php?/cases/view/2695828 + func testBackArrowNavigation() { + mozWaitForElementToExist(app.buttons[AccessibilityIdentifiers.Toolbar.settingsMenuButton]) + navigator.nowAt(NewTabScreen) + closeFromAppSwitcherAndRelaunch() + navigator.openURL(path(forTestPage: "test-example.html")) + waitUntilPageLoad() + app.links[website_2["link"]!].tap() + waitUntilPageLoad() + let backButton = app.buttons[AccessibilityIdentifiers.Toolbar.backButton] + mozWaitForElementToExist(backButton) + XCTAssertTrue(backButton.isHittable, "Back button is not hittable") + XCTAssertTrue(backButton.isEnabled, "Back button is disabled") + backButton.tap() + waitUntilPageLoad() + mozWaitForValueContains(app.textFields["url"], value: "test-example.html") + XCTAssertTrue(backButton.isHittable, "Back button is not hittable") + XCTAssertTrue(backButton.isEnabled, "Back button is disabled") + backButton.tap() + waitUntilPageLoad() + mozWaitForElementToExist(app.cells[AccessibilityIdentifiers.FirefoxHomepage.TopSites.itemCell]) + } + private func openContextMenuForArticleLink() { navigator.openURL(path(forTestPage: "test-example.html")) mozWaitForElementToExist(app.webViews.links[website_2["link"]!], timeout: TIMEOUT_LONG) From ecc6357aead460769a0ced22d78b834b92505fad Mon Sep 17 00:00:00 2001 From: Ione Souza Junior Date: Wed, 14 Aug 2024 05:49:27 -0300 Subject: [PATCH 076/128] Refactor FXIOS-7301 - Help to remove 1 closure_body_length violation from UITestAppDelegate.swift (1/3) #21333 * Extract webserver port config to a new function * Use the new function * Change access modifier --- .../Client/Application/UITestAppDelegate.swift | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/firefox-ios/Client/Application/UITestAppDelegate.swift b/firefox-ios/Client/Application/UITestAppDelegate.swift index 9a5d8d2206ac..7f9d71402c57 100644 --- a/firefox-ios/Client/Application/UITestAppDelegate.swift +++ b/firefox-ios/Client/Application/UITestAppDelegate.swift @@ -34,12 +34,7 @@ class UITestAppDelegate: AppDelegate, FeatureFlaggable { launchArguments.forEach { arg in if arg.starts(with: LaunchArguments.ServerPort) { - let portString = arg.replacingOccurrences(of: LaunchArguments.ServerPort, with: "") - if let port = Int(portString) { - AppInfo.webserverPort = port - } else { - fatalError("Failed to set web server port override.") - } + configureWebserverPort(arg) } if arg.starts(with: LaunchArguments.LoadDatabasePrefix) { @@ -200,6 +195,15 @@ class UITestAppDelegate: AppDelegate, FeatureFlaggable { return profile } + private func configureWebserverPort(_ arg: String) { + let portString = arg.replacingOccurrences(of: LaunchArguments.ServerPort, with: "") + if let port = Int(portString) { + AppInfo.webserverPort = port + } else { + fatalError("Failed to set web server port override.") + } + } + override func application( _ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil From 29a3c27db512f28a219770f8c1a52394c7dc440a Mon Sep 17 00:00:00 2001 From: Ione Souza Junior Date: Wed, 14 Aug 2024 05:52:22 -0300 Subject: [PATCH 077/128] Refactor FXIOS-7301 - Remove 1 closure_body_length violation from BrowserViewController.swift (#21334) * Extract microsurvey actions to a new function * Use the new function * Change access modifier --- .../Views/BrowserViewController.swift | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift index fa05bd0eaa97..ec35492c5e2e 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift @@ -642,20 +642,7 @@ class BrowserViewController: UIViewController, executeToolbarActions() - // Microsurveys - if !state.microsurveyState.showPrompt { - guard microsurvey != nil else { return } - removeMicrosurveyPrompt() - } else if state.microsurveyState.showSurvey { - guard let model = state.microsurveyState.model else { - logger.log("Microsurvey model should not be nil", level: .warning, category: .redux) - return - } - navigationHandler?.showMicrosurvey(model: model) - } else if state.microsurveyState.showPrompt { - guard microsurvey == nil else { return } - createMicrosurveyPrompt(with: state.microsurveyState) - } + handleMicrosurvey(state: state) } } @@ -675,6 +662,22 @@ class BrowserViewController: UIViewController, show(toast: toast) } + private func handleMicrosurvey(state: BrowserViewControllerState) { + if !state.microsurveyState.showPrompt { + guard microsurvey != nil else { return } + removeMicrosurveyPrompt() + } else if state.microsurveyState.showSurvey { + guard let model = state.microsurveyState.model else { + logger.log("Microsurvey model should not be nil", level: .warning, category: .redux) + return + } + navigationHandler?.showMicrosurvey(model: model) + } else if state.microsurveyState.showPrompt { + guard microsurvey == nil else { return } + createMicrosurveyPrompt(with: state.microsurveyState) + } + } + // MARK: - Lifecycle override func viewDidLoad() { From 79baa1d5219a79d240b6e3725b4ff21e212c7b01 Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Wed, 14 Aug 2024 18:16:54 +0100 Subject: [PATCH 078/128] Bump - Update Sentry to version 8.26.0 (#20271) --- BrowserKit/Package.resolved | 4 ++-- BrowserKit/Package.swift | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- firefox-ios/Client.xcodeproj/project.pbxproj | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- focus-ios/Blockzilla.xcodeproj/project.pbxproj | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/BrowserKit/Package.resolved b/BrowserKit/Package.resolved index 0d8d7a515d83..da740db42b72 100644 --- a/BrowserKit/Package.resolved +++ b/BrowserKit/Package.resolved @@ -41,8 +41,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/getsentry/sentry-cocoa.git", "state" : { - "revision" : "38f4f70d07117b9f958a76b1bff278c2f29ffe0e", - "version" : "8.21.0" + "revision" : "7fc7ca43967e2980d8691a8e017c118a84133aac", + "version" : "8.26.0" } }, { diff --git a/BrowserKit/Package.swift b/BrowserKit/Package.swift index 107755d44bd9..9dff77c7f025 100644 --- a/BrowserKit/Package.swift +++ b/BrowserKit/Package.swift @@ -52,7 +52,7 @@ let package = Package( exact: "2.0.0"), .package( url: "https://github.com/getsentry/sentry-cocoa.git", - exact: "8.21.0"), + exact: "8.26.0"), .package(url: "https://github.com/nbhasin2/GCDWebServer.git", branch: "master") ], diff --git a/SampleBrowser/SampleBrowser.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/SampleBrowser/SampleBrowser.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 0d8d7a515d83..da740db42b72 100644 --- a/SampleBrowser/SampleBrowser.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/SampleBrowser/SampleBrowser.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -41,8 +41,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/getsentry/sentry-cocoa.git", "state" : { - "revision" : "38f4f70d07117b9f958a76b1bff278c2f29ffe0e", - "version" : "8.21.0" + "revision" : "7fc7ca43967e2980d8691a8e017c118a84133aac", + "version" : "8.26.0" } }, { diff --git a/SampleComponentLibraryApp/SampleComponentLibraryApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/SampleComponentLibraryApp/SampleComponentLibraryApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 0d8d7a515d83..da740db42b72 100644 --- a/SampleComponentLibraryApp/SampleComponentLibraryApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/SampleComponentLibraryApp/SampleComponentLibraryApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -41,8 +41,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/getsentry/sentry-cocoa.git", "state" : { - "revision" : "38f4f70d07117b9f958a76b1bff278c2f29ffe0e", - "version" : "8.21.0" + "revision" : "7fc7ca43967e2980d8691a8e017c118a84133aac", + "version" : "8.26.0" } }, { diff --git a/firefox-ios/Client.xcodeproj/project.pbxproj b/firefox-ios/Client.xcodeproj/project.pbxproj index 1cfa2775f550..a5f810f800cb 100644 --- a/firefox-ios/Client.xcodeproj/project.pbxproj +++ b/firefox-ios/Client.xcodeproj/project.pbxproj @@ -23189,7 +23189,7 @@ repositoryURL = "https://github.com/getsentry/sentry-cocoa.git"; requirement = { kind = exactVersion; - version = 8.21.0; + version = 8.26.0; }; }; 8AB30EC62B6C038600BD9A9B /* XCRemoteSwiftPackageReference "lottie-ios" */ = { diff --git a/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 61409fc51c43..b247df8ad3d7 100644 --- a/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -104,8 +104,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/getsentry/sentry-cocoa.git", "state" : { - "revision" : "38f4f70d07117b9f958a76b1bff278c2f29ffe0e", - "version" : "8.21.0" + "revision" : "7fc7ca43967e2980d8691a8e017c118a84133aac", + "version" : "8.26.0" } }, { diff --git a/focus-ios/Blockzilla.xcodeproj/project.pbxproj b/focus-ios/Blockzilla.xcodeproj/project.pbxproj index a92134818366..069f33ac7a9b 100644 --- a/focus-ios/Blockzilla.xcodeproj/project.pbxproj +++ b/focus-ios/Blockzilla.xcodeproj/project.pbxproj @@ -7191,7 +7191,7 @@ repositoryURL = "https://github.com/getsentry/sentry-cocoa"; requirement = { kind = exactVersion; - version = 8.21.0; + version = 8.26.0; }; }; /* End XCRemoteSwiftPackageReference section */ diff --git a/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index bb14bbd50f51..35cb01dee474 100644 --- a/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -60,8 +60,8 @@ "repositoryURL": "https://github.com/getsentry/sentry-cocoa", "state": { "branch": null, - "revision": "38f4f70d07117b9f958a76b1bff278c2f29ffe0e", - "version": "8.21.0" + "revision": "7fc7ca43967e2980d8691a8e017c118a84133aac", + "version": "8.26.0" } }, { From 517b54b7f605ae12f6e1dc61bc798fb73c5df12c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Aug 2024 08:06:05 +0100 Subject: [PATCH 079/128] Bump webob in /firefox-ios/firefox-ios-tests/Tests/SyncIntegrationTests (#21532) Bumps [webob](https://github.com/Pylons/webob) from 1.8.7 to 1.8.8. - [Changelog](https://github.com/Pylons/webob/blob/main/CHANGES.txt) - [Commits](https://github.com/Pylons/webob/compare/1.8.7...1.8.8) --- updated-dependencies: - dependency-name: webob dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../Tests/SyncIntegrationTests/Pipfile.lock | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/firefox-ios/firefox-ios-tests/Tests/SyncIntegrationTests/Pipfile.lock b/firefox-ios/firefox-ios-tests/Tests/SyncIntegrationTests/Pipfile.lock index 294579509063..5f81aa569db9 100644 --- a/firefox-ios/firefox-ios-tests/Tests/SyncIntegrationTests/Pipfile.lock +++ b/firefox-ios/firefox-ios-tests/Tests/SyncIntegrationTests/Pipfile.lock @@ -602,11 +602,12 @@ }, "webob": { "hashes": [ - "sha256:73aae30359291c14fa3b956f8b5ca31960e420c28c1bec002547fb04928cf89b", - "sha256:b64ef5141be559cfade448f044fa45c2260351edcb6a8ef6b7e00c7dcef0c323" + "sha256:2abc1555e118fc251e705fc6dc66c7f5353bb9fbfab6d20e22f1c02b4b71bcee", + "sha256:b60ba63f05c0cf61e086a10c3781a41fcfe30027753a8ae6d819c77592ce83ea" ], + "index": "pypi", "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.8.7" + "version": "==1.8.8" }, "wsproto": { "hashes": [ From c07069f92d130a5e5cd6584d7e4f71cf5fa451f1 Mon Sep 17 00:00:00 2001 From: "roux g. buciu" <11182210+adudenamedruby@users.noreply.github.com> Date: Thu, 15 Aug 2024 04:28:57 -0400 Subject: [PATCH 080/128] Refactor - Comment out unused code (#21524) * First comments * comment out tests * Comment out on Focus * Fix swiftlint issues * comment out mocks * Swiftlints --- firefox-ios/Client/AdjustHelper.swift | 244 +++++++++--------- .../Client/AdjustTelemetryHelper.swift | 118 ++++----- .../Client/Application/AppLaunchUtil.swift | 6 +- .../SendAnonymousUsageDataSetting.swift | 2 +- .../Telemetry/Wrapper/AdjustWrapper.swift | 76 +++--- .../Helpers/AdjustTelemetryHelperTests.swift | 166 ++++++------ .../Mocks/MockAdjustTelemetryData.swift | 42 +-- .../ClientTests/Mocks/MockAdjustWrapper.swift | 82 +++--- focus-ios/Shared/AppConfig.swift | 12 +- 9 files changed, 378 insertions(+), 370 deletions(-) diff --git a/firefox-ios/Client/AdjustHelper.swift b/firefox-ios/Client/AdjustHelper.swift index 438e0eb67ec5..3498cc18dd60 100644 --- a/firefox-ios/Client/AdjustHelper.swift +++ b/firefox-ios/Client/AdjustHelper.swift @@ -1,124 +1,126 @@ -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/ - -import Common -import Foundation -import Adjust -import Shared - -final class AdjustHelper: NSObject, FeatureFlaggable { - private static let adjustAppTokenKey = "AdjustAppToken" - private let profile: Profile - private let telemetryHelper: AdjustTelemetryProtocol - - init(profile: Profile, - telemetryHelper: AdjustTelemetryProtocol = AdjustTelemetryHelper()) { - self.profile = profile - self.telemetryHelper = telemetryHelper - let sendUsageData = profile.prefs.boolForKey(AppConstants.prefSendUsageData) ?? true - - // This is required for adjust to work properly with ASA and we avoid directly disabling - // third-party sharing as there is a specific method provided to us by adjust for that. - // Note: These settings are persisted on the adjust backend as well - if sendUsageData { - if let adjustThirdPartySharing = ADJThirdPartySharing(isEnabledNumberBool: true) { - Adjust.trackThirdPartySharing(adjustThirdPartySharing) - } - } else { - Adjust.disableThirdPartySharing() - } - } - - func setupAdjust() { - guard let config = getConfig() else { return } - - // Always initialize Adjust if we have a config - otherwise we cannot enable/disable it later. Their SDK must be - // initialized through appDidFinishLaunching otherwise it will be in a bad state. - Adjust.appDidLaunch(config) - - AdjustHelper.setEnabled(shouldEnable) - } - - /// Used to enable or disable Adjust SDK and it's features. - /// If user has disabled Send Anonymous Usage Data then we ask Adjust to erase the user's data as well. - static func setEnabled(_ enabled: Bool) { - Adjust.setEnabled(enabled) - - if !enabled { - Adjust.disableThirdPartySharing() - Adjust.gdprForgetMe() - } - } - +// swiftlint:disable comment_spacing file_header +//// This Source Code Form is subject to the terms of the Mozilla Public +//// License, v. 2.0. If a copy of the MPL was not distributed with this +//// file, You can obtain one at http://mozilla.org/MPL/2.0/ +// +//import Common +//import Foundation +//import Adjust +//import Shared +// +//final class AdjustHelper: NSObject, FeatureFlaggable { +// private static let adjustAppTokenKey = "AdjustAppToken" +// private let profile: Profile +// private let telemetryHelper: AdjustTelemetryProtocol +// +// init(profile: Profile, +// telemetryHelper: AdjustTelemetryProtocol = AdjustTelemetryHelper()) { +// self.profile = profile +// self.telemetryHelper = telemetryHelper +// let sendUsageData = profile.prefs.boolForKey(AppConstants.prefSendUsageData) ?? true +// +// // This is required for adjust to work properly with ASA and we avoid directly disabling +// // third-party sharing as there is a specific method provided to us by adjust for that. +// // Note: These settings are persisted on the adjust backend as well +// if sendUsageData { +// if let adjustThirdPartySharing = ADJThirdPartySharing(isEnabledNumberBool: true) { +// Adjust.trackThirdPartySharing(adjustThirdPartySharing) +// } +// } else { +// Adjust.disableThirdPartySharing() +// } +// } +// +// func setupAdjust() { +// guard let config = getConfig() else { return } +// +// // Always initialize Adjust if we have a config - otherwise we cannot enable/disable it later. Their SDK must be +// // initialized through appDidFinishLaunching otherwise it will be in a bad state. +// Adjust.appDidLaunch(config) +// +// AdjustHelper.setEnabled(shouldEnable) +// } +// +// /// Used to enable or disable Adjust SDK and it's features. +// /// If user has disabled Send Anonymous Usage Data then we ask Adjust to erase the user's data as well. +// static func setEnabled(_ enabled: Bool) { +// Adjust.setEnabled(enabled) +// +// if !enabled { +// Adjust.disableThirdPartySharing() +// Adjust.gdprForgetMe() +// } +// } +// // MARK: - Private - - private func getConfig() -> ADJConfig? { - let bundle = AppInfo.applicationBundle - guard let appToken = bundle.object(forInfoDictionaryKey: AdjustHelper.adjustAppTokenKey) as? String, - !appToken.isEmpty else { - return nil - } - - let isProd = featureFlags.isCoreFeatureEnabled(.adjustEnvironmentProd) - let environment = isProd ? ADJEnvironmentProduction : ADJEnvironmentSandbox - let config = ADJConfig(appToken: appToken, environment: environment) - config?.logLevel = isProd ? ADJLogLevelSuppress : ADJLogLevelDebug - - // Record attribution changes - // https://help.adjust.com/en/article/ios-sdk-adjconfig-class#set-up-delegate - config?.delegate = (self as AdjustHelper) - - return config - } - - /// Return true if Adjust should be enabled. If the user has disabled the Send Anonymous Usage Data - /// then we only do one ping to get the attribution and turn it off (i.e. we only enable it if we - /// have not seen the attribution data yet). - private var shouldEnable: Bool { - return shouldTrackRetention || !hasAttribution - } - - /// Return true if retention (session) tracking should be enabled. - /// This follows the Send Anonymous Usage Data setting. - private var shouldTrackRetention: Bool { - return profile.prefs.boolForKey(AppConstants.prefSendUsageData) ?? true - } - +// +// private func getConfig() -> ADJConfig? { +// let bundle = AppInfo.applicationBundle +// guard let appToken = bundle.object(forInfoDictionaryKey: AdjustHelper.adjustAppTokenKey) as? String, +// !appToken.isEmpty else { +// return nil +// } +// +// let isProd = featureFlags.isCoreFeatureEnabled(.adjustEnvironmentProd) +// let environment = isProd ? ADJEnvironmentProduction : ADJEnvironmentSandbox +// let config = ADJConfig(appToken: appToken, environment: environment) +// config?.logLevel = isProd ? ADJLogLevelSuppress : ADJLogLevelDebug +// +// // Record attribution changes +// // https://help.adjust.com/en/article/ios-sdk-adjconfig-class#set-up-delegate +// config?.delegate = (self as AdjustHelper) +// +// return config +// } +// +// /// Return true if Adjust should be enabled. If the user has disabled the Send Anonymous Usage Data +// /// then we only do one ping to get the attribution and turn it off (i.e. we only enable it if we +// /// have not seen the attribution data yet). +// private var shouldEnable: Bool { +// return shouldTrackRetention || !hasAttribution +// } +// +// /// Return true if retention (session) tracking should be enabled. +// /// This follows the Send Anonymous Usage Data setting. +// private var shouldTrackRetention: Bool { +// return profile.prefs.boolForKey(AppConstants.prefSendUsageData) ?? true +// } +// // MARK: - UserDefaults - - private enum UserDefaultsKey: String { - case hasAttribution = "com.moz.adjust.hasAttribution.key" - } - - private var hasAttribution: Bool { - get { UserDefaults.standard.object(forKey: UserDefaultsKey.hasAttribution.rawValue) as? Bool ?? false } - set { UserDefaults.standard.set(newValue, forKey: UserDefaultsKey.hasAttribution.rawValue) } - } -} - +// +// private enum UserDefaultsKey: String { +// case hasAttribution = "com.moz.adjust.hasAttribution.key" +// } +// +// private var hasAttribution: Bool { +// get { UserDefaults.standard.object(forKey: UserDefaultsKey.hasAttribution.rawValue) as? Bool ?? false } +// set { UserDefaults.standard.set(newValue, forKey: UserDefaultsKey.hasAttribution.rawValue) } +// } +//} +// // MARK: - AdjustDelegate -extension AdjustHelper: AdjustDelegate { - /// This is called when Adjust has figured out the attribution. It will call us with a summary - /// of all the things it knows. Like the campaign ID. We simply save a boolean that attribution - /// has changed so we know the single attribution ping to Adjust was done. - /// - /// We also disable Adjust based on the Send Anonymous Usage Data setting. - func adjustAttributionChanged(_ attribution: ADJAttribution?) { - hasAttribution = true - if !shouldEnable { - AdjustHelper.setEnabled(false) - } - - telemetryHelper.setAttributionData(attribution) - } - - func adjustDeeplinkResponse(_ deeplink: URL?) -> Bool { - guard let url = deeplink else { return true } - - // Send telemetry if url is not nil - let attribution = Adjust.attribution() - telemetryHelper.sendDeeplinkTelemetry(url: url, attribution: attribution) - return true - } -} +//extension AdjustHelper: AdjustDelegate { +// /// This is called when Adjust has figured out the attribution. It will call us with a summary +// /// of all the things it knows. Like the campaign ID. We simply save a boolean that attribution +// /// has changed so we know the single attribution ping to Adjust was done. +// /// +// /// We also disable Adjust based on the Send Anonymous Usage Data setting. +// func adjustAttributionChanged(_ attribution: ADJAttribution?) { +// hasAttribution = true +// if !shouldEnable { +// AdjustHelper.setEnabled(false) +// } +// +// telemetryHelper.setAttributionData(attribution) +// } +// +// func adjustDeeplinkResponse(_ deeplink: URL?) -> Bool { +// guard let url = deeplink else { return true } +// +// // Send telemetry if url is not nil +// let attribution = Adjust.attribution() +// telemetryHelper.sendDeeplinkTelemetry(url: url, attribution: attribution) +// return true +// } +//} +// swiftlint:enable comment_spacing file_header diff --git a/firefox-ios/Client/AdjustTelemetryHelper.swift b/firefox-ios/Client/AdjustTelemetryHelper.swift index 857b9e19f367..0db7a0578f83 100644 --- a/firefox-ios/Client/AdjustTelemetryHelper.swift +++ b/firefox-ios/Client/AdjustTelemetryHelper.swift @@ -1,58 +1,60 @@ -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/ - -import Foundation -import Adjust - -protocol AdjustTelemetryData { - var campaign: String? { get set } - var adgroup: String? { get set } - var creative: String? { get set } - var network: String? { get set } -} - -extension ADJAttribution: AdjustTelemetryData { -} - -protocol AdjustTelemetryProtocol { - func setAttributionData(_ attribution: AdjustTelemetryData?) - func sendDeeplinkTelemetry(url: URL, attribution: AdjustTelemetryData?) -} - -class AdjustTelemetryHelper: AdjustTelemetryProtocol { - var gleanWrapper: GleanWrapper - var telemetry: AdjustWrapper - - init(gleanWrapper: GleanWrapper = DefaultGleanWrapper(), - telemetry: AdjustWrapper = DefaultAdjustWrapper()) { - self.gleanWrapper = gleanWrapper - self.telemetry = telemetry - } - - func sendDeeplinkTelemetry(url: URL, attribution: AdjustTelemetryData?) { - telemetry.recordDeeplink(url: url) - - setAttributionData(attribution) - } - - func setAttributionData(_ attribution: AdjustTelemetryData?) { - if let campaign = attribution?.campaign { - telemetry.record(campaign: campaign) - } - - if let adgroup = attribution?.adgroup { - telemetry.record(adgroup: adgroup) - } - - if let creative = attribution?.creative { - telemetry.record(creative: creative) - } - - if let network = attribution?.network { - telemetry.record(network: network) - } - - gleanWrapper.submitPing() - } -} +// swiftlint:disable comment_spacing file_header +//// This Source Code Form is subject to the terms of the Mozilla Public +//// License, v. 2.0. If a copy of the MPL was not distributed with this +//// file, You can obtain one at http://mozilla.org/MPL/2.0/ +// +//import Foundation +//import Adjust +// +//protocol AdjustTelemetryData { +// var campaign: String? { get set } +// var adgroup: String? { get set } +// var creative: String? { get set } +// var network: String? { get set } +//} +// +//extension ADJAttribution: AdjustTelemetryData { +//} +// +//protocol AdjustTelemetryProtocol { +// func setAttributionData(_ attribution: AdjustTelemetryData?) +// func sendDeeplinkTelemetry(url: URL, attribution: AdjustTelemetryData?) +//} +// +//class AdjustTelemetryHelper: AdjustTelemetryProtocol { +// var gleanWrapper: GleanWrapper +// var telemetry: AdjustWrapper +// +// init(gleanWrapper: GleanWrapper = DefaultGleanWrapper(), +// telemetry: AdjustWrapper = DefaultAdjustWrapper()) { +// self.gleanWrapper = gleanWrapper +// self.telemetry = telemetry +// } +// +// func sendDeeplinkTelemetry(url: URL, attribution: AdjustTelemetryData?) { +// telemetry.recordDeeplink(url: url) +// +// setAttributionData(attribution) +// } +// +// func setAttributionData(_ attribution: AdjustTelemetryData?) { +// if let campaign = attribution?.campaign { +// telemetry.record(campaign: campaign) +// } +// +// if let adgroup = attribution?.adgroup { +// telemetry.record(adgroup: adgroup) +// } +// +// if let creative = attribution?.creative { +// telemetry.record(creative: creative) +// } +// +// if let network = attribution?.network { +// telemetry.record(network: network) +// } +// +// gleanWrapper.submitPing() +// } +//} +// swiftlint:enable comment_spacing file_header diff --git a/firefox-ios/Client/Application/AppLaunchUtil.swift b/firefox-ios/Client/Application/AppLaunchUtil.swift index 50a8d2bf2171..fefd5d5df2a4 100644 --- a/firefox-ios/Client/Application/AppLaunchUtil.swift +++ b/firefox-ios/Client/Application/AppLaunchUtil.swift @@ -11,7 +11,7 @@ import Glean class AppLaunchUtil { private var logger: Logger - private var adjustHelper: AdjustHelper +// private var adjustHelper: AdjustHelper private var profile: Profile private let introScreenManager: IntroScreenManager @@ -19,7 +19,7 @@ class AppLaunchUtil { profile: Profile) { self.logger = logger self.profile = profile - self.adjustHelper = AdjustHelper(profile: profile) +// self.adjustHelper = AdjustHelper(profile: profile) self.introScreenManager = IntroScreenManager(prefs: profile.prefs) } @@ -128,7 +128,7 @@ class AppLaunchUtil { } updateSessionCount() - adjustHelper.setupAdjust() +// adjustHelper.setupAdjust() AppEventQueue.signal(event: .postLaunchDependenciesComplete) } diff --git a/firefox-ios/Client/Frontend/Settings/Main/Support/SendAnonymousUsageDataSetting.swift b/firefox-ios/Client/Frontend/Settings/Main/Support/SendAnonymousUsageDataSetting.swift index 0320de985f5e..d880d4ef39a7 100644 --- a/firefox-ios/Client/Frontend/Settings/Main/Support/SendAnonymousUsageDataSetting.swift +++ b/firefox-ios/Client/Frontend/Settings/Main/Support/SendAnonymousUsageDataSetting.swift @@ -40,7 +40,7 @@ class SendAnonymousUsageDataSetting: BoolSetting { attributedTitleText: NSAttributedString(string: .SendUsageSettingTitle), attributedStatusText: statusText, settingDidChange: { - AdjustHelper.setEnabled($0) +// AdjustHelper.setEnabled($0) DefaultGleanWrapper.shared.setUpload(isEnabled: $0) Experiments.setTelemetrySetting($0) } diff --git a/firefox-ios/Client/Telemetry/Wrapper/AdjustWrapper.swift b/firefox-ios/Client/Telemetry/Wrapper/AdjustWrapper.swift index 5cf84519eba0..d0cd5ee88856 100644 --- a/firefox-ios/Client/Telemetry/Wrapper/AdjustWrapper.swift +++ b/firefox-ios/Client/Telemetry/Wrapper/AdjustWrapper.swift @@ -1,37 +1,39 @@ -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/ - -import Foundation -import Glean - -protocol AdjustWrapper { - func recordDeeplink(url: URL) - func record(campaign: String) - func record(adgroup: String) - func record(creative: String) - func record(network: String) -} - -struct DefaultAdjustWrapper: AdjustWrapper { - func recordDeeplink(url: URL) { - let extra = GleanMetrics.Adjust.DeeplinkReceivedExtra(receivedUrl: url.absoluteString) - GleanMetrics.Adjust.deeplinkReceived.record(extra) - } - - func record(campaign: String) { - GleanMetrics.Adjust.campaign.set(campaign) - } - - func record(adgroup: String) { - GleanMetrics.Adjust.adGroup.set(adgroup) - } - - func record(creative: String) { - GleanMetrics.Adjust.creative.set(creative) - } - - func record(network: String) { - GleanMetrics.Adjust.network.set(network) - } -} +// swiftlint:disable comment_spacing file_header +//// This Source Code Form is subject to the terms of the Mozilla Public +//// License, v. 2.0. If a copy of the MPL was not distributed with this +//// file, You can obtain one at http://mozilla.org/MPL/2.0/ +// +//import Foundation +//import Glean +// +//protocol AdjustWrapper { +// func recordDeeplink(url: URL) +// func record(campaign: String) +// func record(adgroup: String) +// func record(creative: String) +// func record(network: String) +//} +// +//struct DefaultAdjustWrapper: AdjustWrapper { +// func recordDeeplink(url: URL) { +// let extra = GleanMetrics.Adjust.DeeplinkReceivedExtra(receivedUrl: url.absoluteString) +// GleanMetrics.Adjust.deeplinkReceived.record(extra) +// } +// +// func record(campaign: String) { +// GleanMetrics.Adjust.campaign.set(campaign) +// } +// +// func record(adgroup: String) { +// GleanMetrics.Adjust.adGroup.set(adgroup) +// } +// +// func record(creative: String) { +// GleanMetrics.Adjust.creative.set(creative) +// } +// +// func record(network: String) { +// GleanMetrics.Adjust.network.set(network) +// } +//} +// swiftlint:enable comment_spacing file_header diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Helpers/AdjustTelemetryHelperTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Helpers/AdjustTelemetryHelperTests.swift index d98012d3d3e1..22b0063c10a8 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Helpers/AdjustTelemetryHelperTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Helpers/AdjustTelemetryHelperTests.swift @@ -1,83 +1,85 @@ -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/ - -import XCTest - -@testable import Client - -class AdjustTelemetryHelperTests: XCTestCase { - var telemetryWrapper: MockAdjustWrapper! - var gleanWrapper: MockGleanWrapper! - - override func setUp() { - super.setUp() - - telemetryWrapper = MockAdjustWrapper() - gleanWrapper = MockGleanWrapper() - } - - override func tearDown() { - super.tearDown() - - telemetryWrapper = nil - gleanWrapper = nil - } - - func testFailSetAttribution_WithAllNilData() { - let subject = createSubject() - let attribution = MockAdjustTelemetryData(campaign: nil, - adgroup: nil, - creative: nil, - network: nil) - subject.setAttributionData(attribution) - - XCTAssertEqual(telemetryWrapper.recordDeeplinkCalled, 0) - XCTAssertEqual(telemetryWrapper.recordCampaignCalled, 0) - XCTAssertEqual(telemetryWrapper.recordNetworkCalled, 0) - XCTAssertEqual(telemetryWrapper.recordCreativeCalled, 0) - XCTAssertEqual(telemetryWrapper.recordAdGroupCalled, 0) - XCTAssertEqual(gleanWrapper.submitPingCalled, 1) - } - - func testSetAttribution_WithSomeNilData() { - let subject = createSubject() - let attribution = MockAdjustTelemetryData(campaign: nil) - - subject.setAttributionData(attribution) - - XCTAssertEqual(telemetryWrapper.recordCampaignCalled, 0) - XCTAssertEqual(telemetryWrapper.savedNetwork, "test_network") - XCTAssertEqual(telemetryWrapper.recordNetworkCalled, 1) - XCTAssertEqual(telemetryWrapper.savedCreative, "test_creative") - XCTAssertEqual(telemetryWrapper.recordCreativeCalled, 1) - XCTAssertEqual(telemetryWrapper.savedAdGroup, "test_adgroup") - XCTAssertEqual(telemetryWrapper.recordAdGroupCalled, 1) - XCTAssertEqual(gleanWrapper.submitPingCalled, 1) - } - - func testDeeplinkHandleEvent_GleanCalled() { - let subject = createSubject() - let url = URL(string: "https://testurl.com")! - let mockData = MockAdjustTelemetryData() - - subject.sendDeeplinkTelemetry(url: url, attribution: mockData) - - XCTAssertEqual(telemetryWrapper.savedDeeplink, url) - XCTAssertEqual(telemetryWrapper.recordDeeplinkCalled, 1) - XCTAssertEqual(telemetryWrapper.savedCampaign, mockData.campaign!) - XCTAssertEqual(telemetryWrapper.savedNetwork, mockData.network!) - XCTAssertEqual(telemetryWrapper.savedCreative, mockData.creative!) - XCTAssertEqual(telemetryWrapper.savedAdGroup, mockData.adgroup!) - XCTAssertEqual(gleanWrapper.submitPingCalled, 1) - } - +// swiftlint:disable comment_spacing file_header +//// This Source Code Form is subject to the terms of the Mozilla Public +//// License, v. 2.0. If a copy of the MPL was not distributed with this +//// file, You can obtain one at http://mozilla.org/MPL/2.0/ +// +//import XCTest +// +//@testable import Client +// +//class AdjustTelemetryHelperTests: XCTestCase { +// var telemetryWrapper: MockAdjustWrapper! +// var gleanWrapper: MockGleanWrapper! +// +// override func setUp() { +// super.setUp() +// +// telemetryWrapper = MockAdjustWrapper() +// gleanWrapper = MockGleanWrapper() +// } +// +// override func tearDown() { +// super.tearDown() +// +// telemetryWrapper = nil +// gleanWrapper = nil +// } +// +// func testFailSetAttribution_WithAllNilData() { +// let subject = createSubject() +// let attribution = MockAdjustTelemetryData(campaign: nil, +// adgroup: nil, +// creative: nil, +// network: nil) +// subject.setAttributionData(attribution) +// +// XCTAssertEqual(telemetryWrapper.recordDeeplinkCalled, 0) +// XCTAssertEqual(telemetryWrapper.recordCampaignCalled, 0) +// XCTAssertEqual(telemetryWrapper.recordNetworkCalled, 0) +// XCTAssertEqual(telemetryWrapper.recordCreativeCalled, 0) +// XCTAssertEqual(telemetryWrapper.recordAdGroupCalled, 0) +// XCTAssertEqual(gleanWrapper.submitPingCalled, 1) +// } +// +// func testSetAttribution_WithSomeNilData() { +// let subject = createSubject() +// let attribution = MockAdjustTelemetryData(campaign: nil) +// +// subject.setAttributionData(attribution) +// +// XCTAssertEqual(telemetryWrapper.recordCampaignCalled, 0) +// XCTAssertEqual(telemetryWrapper.savedNetwork, "test_network") +// XCTAssertEqual(telemetryWrapper.recordNetworkCalled, 1) +// XCTAssertEqual(telemetryWrapper.savedCreative, "test_creative") +// XCTAssertEqual(telemetryWrapper.recordCreativeCalled, 1) +// XCTAssertEqual(telemetryWrapper.savedAdGroup, "test_adgroup") +// XCTAssertEqual(telemetryWrapper.recordAdGroupCalled, 1) +// XCTAssertEqual(gleanWrapper.submitPingCalled, 1) +// } +// +// func testDeeplinkHandleEvent_GleanCalled() { +// let subject = createSubject() +// let url = URL(string: "https://testurl.com")! +// let mockData = MockAdjustTelemetryData() +// +// subject.sendDeeplinkTelemetry(url: url, attribution: mockData) +// +// XCTAssertEqual(telemetryWrapper.savedDeeplink, url) +// XCTAssertEqual(telemetryWrapper.recordDeeplinkCalled, 1) +// XCTAssertEqual(telemetryWrapper.savedCampaign, mockData.campaign!) +// XCTAssertEqual(telemetryWrapper.savedNetwork, mockData.network!) +// XCTAssertEqual(telemetryWrapper.savedCreative, mockData.creative!) +// XCTAssertEqual(telemetryWrapper.savedAdGroup, mockData.adgroup!) +// XCTAssertEqual(gleanWrapper.submitPingCalled, 1) +// } +// // MARK: - Helper - - func createSubject() -> AdjustTelemetryHelper { - let subject = AdjustTelemetryHelper(gleanWrapper: gleanWrapper, - telemetry: telemetryWrapper) - trackForMemoryLeaks(subject) - return subject - } -} +// +// func createSubject() -> AdjustTelemetryHelper { +// let subject = AdjustTelemetryHelper(gleanWrapper: gleanWrapper, +// telemetry: telemetryWrapper) +// trackForMemoryLeaks(subject) +// return subject +// } +//} +// swiftlint:enable comment_spacing file_header diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockAdjustTelemetryData.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockAdjustTelemetryData.swift index aba6c4d379a5..0d2a1203b33a 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockAdjustTelemetryData.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockAdjustTelemetryData.swift @@ -1,24 +1,24 @@ // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/ - -import Foundation - -@testable import Client - -class MockAdjustTelemetryData: AdjustTelemetryData { - var campaign: String? - var adgroup: String? - var creative: String? - var network: String? - - init(campaign: String? = "test_campaing", - adgroup: String? = "test_adgroup", - creative: String? = "test_creative", - network: String? = "test_network") { - self.campaign = campaign - self.adgroup = adgroup - self.creative = creative - self.network = network - } -} +// +// import Foundation +// +// @testable import Client +// +// class MockAdjustTelemetryData: AdjustTelemetryData { +// var campaign: String? +// var adgroup: String? +// var creative: String? +// var network: String? +// +// init(campaign: String? = "test_campaing", +// adgroup: String? = "test_adgroup", +// creative: String? = "test_creative", +// network: String? = "test_network") { +// self.campaign = campaign +// self.adgroup = adgroup +// self.creative = creative +// self.network = network +// } +// } diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockAdjustWrapper.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockAdjustWrapper.swift index d96f596d5fef..97161b8c6a5e 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockAdjustWrapper.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockAdjustWrapper.swift @@ -1,44 +1,44 @@ // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/ - -@testable import Client - -class MockAdjustWrapper: AdjustWrapper { - var recordDeeplinkCalled = 0 - var recordCampaignCalled = 0 - var recordAdGroupCalled = 0 - var recordCreativeCalled = 0 - var recordNetworkCalled = 0 - - var savedDeeplink: URL? - var savedCampaign: String? - var savedAdGroup: String? - var savedCreative: String? - var savedNetwork: String? - - func recordDeeplink(url: URL) { - recordDeeplinkCalled += 1 - savedDeeplink = url - } - - func record(campaign: String) { - recordCampaignCalled += 1 - savedCampaign = campaign - } - - func record(adgroup: String) { - recordAdGroupCalled += 1 - savedAdGroup = adgroup - } - - func record(creative: String) { - recordCreativeCalled += 1 - savedCreative = creative - } - - func record(network: String) { - recordNetworkCalled += 1 - savedNetwork = network - } -} +// +// @testable import Client +// +// class MockAdjustWrapper: AdjustWrapper { +// var recordDeeplinkCalled = 0 +// var recordCampaignCalled = 0 +// var recordAdGroupCalled = 0 +// var recordCreativeCalled = 0 +// var recordNetworkCalled = 0 +// +// var savedDeeplink: URL? +// var savedCampaign: String? +// var savedAdGroup: String? +// var savedCreative: String? +// var savedNetwork: String? +// +// func recordDeeplink(url: URL) { +// recordDeeplinkCalled += 1 +// savedDeeplink = url +// } +// +// func record(campaign: String) { +// recordCampaignCalled += 1 +// savedCampaign = campaign +// } +// +// func record(adgroup: String) { +// recordAdGroupCalled += 1 +// savedAdGroup = adgroup +// } +// +// func record(creative: String) { +// recordCreativeCalled += 1 +// savedCreative = creative +// } +// +// func record(network: String) { +// recordNetworkCalled += 1 +// savedNetwork = network +// } +// } diff --git a/focus-ios/Shared/AppConfig.swift b/focus-ios/Shared/AppConfig.swift index 8f21fa94dbb0..de2dc61fc92a 100644 --- a/focus-ios/Shared/AppConfig.swift +++ b/focus-ios/Shared/AppConfig.swift @@ -6,8 +6,8 @@ import Foundation import UIKit protocol AppConfig { - var adjustFile: String { get } - var firefoxAppStoreURL: URL { get } +// var adjustFile: String { get } +// var firefoxAppStoreURL: URL { get } var productName: String { get } var supportPath: String { get } var appId: String { get } @@ -15,8 +15,8 @@ protocol AppConfig { } struct FocusAppConfig: AppConfig { - let adjustFile = "Adjust-Focus" - let firefoxAppStoreURL = URL(string: "https://app.adjust.com/gs1ao4")! +// let adjustFile = "Adjust-Focus" +// let firefoxAppStoreURL = URL(string: "https://app.adjust.com/gs1ao4")! let productName = "Focus" let supportPath = "kb/focus" let appId = "1055677337" @@ -24,8 +24,8 @@ struct FocusAppConfig: AppConfig { } struct KlarAppConfig: AppConfig { - let adjustFile = "Adjust-Klar" - let firefoxAppStoreURL = URL(string: "https://app.adjust.com/c04cts")! +// let adjustFile = "Adjust-Klar" +// let firefoxAppStoreURL = URL(string: "https://app.adjust.com/c04cts")! let productName = "Klar" let supportPath = "products/klar" let appId = "1073435754" From 14b8d3c28b0bfbd20b82a7937253a9d09fd62a1a Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Thu, 15 Aug 2024 11:48:54 +0100 Subject: [PATCH 081/128] Bump - Update Glean to v60.5.0 (#21528) --- firefox-ios/Client.xcodeproj/project.pbxproj | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- focus-ios/Blockzilla.xcodeproj/project.pbxproj | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/firefox-ios/Client.xcodeproj/project.pbxproj b/firefox-ios/Client.xcodeproj/project.pbxproj index a5f810f800cb..4cc1f677b777 100644 --- a/firefox-ios/Client.xcodeproj/project.pbxproj +++ b/firefox-ios/Client.xcodeproj/project.pbxproj @@ -23157,7 +23157,7 @@ repositoryURL = "https://github.com/mozilla/glean-swift"; requirement = { kind = exactVersion; - version = 60.4.0; + version = 60.5.0; }; }; 4368F83B279669690013419B /* XCRemoteSwiftPackageReference "SnapKit" */ = { diff --git a/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index b247df8ad3d7..2fe1e98a129e 100644 --- a/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -41,8 +41,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/mozilla/glean-swift", "state" : { - "revision" : "4bea990fdaaeea98b7855ce682bfefa6a5acc04b", - "version" : "60.4.0" + "revision" : "2185e2eea2d5ce272ff5c0e851eed42d52104ce4", + "version" : "60.5.0" } }, { diff --git a/focus-ios/Blockzilla.xcodeproj/project.pbxproj b/focus-ios/Blockzilla.xcodeproj/project.pbxproj index 069f33ac7a9b..e1025733b351 100644 --- a/focus-ios/Blockzilla.xcodeproj/project.pbxproj +++ b/focus-ios/Blockzilla.xcodeproj/project.pbxproj @@ -7175,7 +7175,7 @@ repositoryURL = "https://github.com/mozilla/glean-swift"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 60.4.0; + minimumVersion = 60.5.0; }; }; F8324C2D264C807C007E4BFA /* XCRemoteSwiftPackageReference "SnapKit" */ = { diff --git a/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 35cb01dee474..e6df9a11794b 100644 --- a/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -33,8 +33,8 @@ "repositoryURL": "https://github.com/mozilla/glean-swift", "state": { "branch": null, - "revision": "4bea990fdaaeea98b7855ce682bfefa6a5acc04b", - "version": "60.4.0" + "revision": "2185e2eea2d5ce272ff5c0e851eed42d52104ce4", + "version": "60.5.0" } }, { From 8e542792fc415b3cee708f5c5a7a5c1a71cba139 Mon Sep 17 00:00:00 2001 From: lmarceau Date: Thu, 15 Aug 2024 12:28:34 -0400 Subject: [PATCH 082/128] Refactor - Fix unused return value in `RustFirefoxSuggest` (#21534) --- firefox-ios/Storage/Rust/RustFirefoxSuggest.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firefox-ios/Storage/Rust/RustFirefoxSuggest.swift b/firefox-ios/Storage/Rust/RustFirefoxSuggest.swift index 1821653fd11f..931998177e50 100644 --- a/firefox-ios/Storage/Rust/RustFirefoxSuggest.swift +++ b/firefox-ios/Storage/Rust/RustFirefoxSuggest.swift @@ -59,7 +59,7 @@ public class RustFirefoxSuggest: RustFirefoxSuggestProtocol { try await withCheckedThrowingContinuation { continuation in writerQueue.async(qos: .utility) { do { - try self.store.ingest(constraints: SuggestIngestionConstraints()) + _ = try self.store.ingest(constraints: SuggestIngestionConstraints()) continuation.resume() } catch { continuation.resume(throwing: error) From d1b28cd78cfaac9117eef5944a38cda008c5f009 Mon Sep 17 00:00:00 2001 From: PARAIPAN SORIN <51127880+PARAIPAN9@users.noreply.github.com> Date: Fri, 16 Aug 2024 12:24:22 +0300 Subject: [PATCH 083/128] Fix page actions (#21526) --- .../Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift index 36a4fd568891..069c3f0b88c4 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift @@ -542,11 +542,13 @@ final class ToolbarMiddleware: FeatureFlaggable { ) -> [ToolbarActionState] { var actions = [ToolbarActionState]() + let isUrlChangeAction = action.actionType as? ToolbarMiddlewareActionType == .urlDidChange let isReaderModeAction = action.actionType as? ToolbarMiddlewareActionType == .readerModeStateChanged let readerModeState = isReaderModeAction ? action.readerModeState : toolbarState.readerModeState + let url = (isUrlChangeAction || isReaderModeAction) ? action.url : toolbarState.addressToolbar.url readerModeAction.shouldDisplayAsHighlighted = readerModeState == .active - guard action.url != nil, !isEditing else { + guard url != nil, !isEditing else { // On homepage we only show the QR code button return [qrCodeScanAction] } From a4cb6cf71346f470e25f81870627b122ef0994f2 Mon Sep 17 00:00:00 2001 From: mattreaganmozilla <145381717+mattreaganmozilla@users.noreply.github.com> Date: Fri, 16 Aug 2024 15:40:16 +0100 Subject: [PATCH 084/128] [9787] Fix cookies being lost and signing users out between app launches (#21539) --- firefox-ios/Client/TabManagement/TabManagerImplementation.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/firefox-ios/Client/TabManagement/TabManagerImplementation.swift b/firefox-ios/Client/TabManagement/TabManagerImplementation.swift index 180de1aa4d84..506884993486 100644 --- a/firefox-ios/Client/TabManagement/TabManagerImplementation.swift +++ b/firefox-ios/Client/TabManagement/TabManagerImplementation.swift @@ -415,8 +415,6 @@ class TabManagerImplementation: LegacyTabManager, Notifiable, WindowSimpleTabsPr delegates.forEach { $0.get()?.tabManager(self, didRemoveTab: tab, isRestoring: false) } } tabs = normalTabs - - privateConfiguration = LegacyTabManager.makeWebViewConfig(isPrivate: true, prefs: profile.prefs) } private func willSelectTab(_ url: URL?) { From 18b6c0d8f8c6c671393775589deff9d68c440110 Mon Sep 17 00:00:00 2001 From: lmarceau Date: Fri, 16 Aug 2024 12:56:06 -0400 Subject: [PATCH 085/128] Refactor - ImageProvider SiteImageView extension is now also MainActor (#21537) --- .../ImageProcessing/HeroImageFetcher/ImageProvider.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/BrowserKit/Sources/SiteImageView/ImageProcessing/HeroImageFetcher/ImageProvider.swift b/BrowserKit/Sources/SiteImageView/ImageProcessing/HeroImageFetcher/ImageProvider.swift index be856e194ffd..a22d1c67d25d 100644 --- a/BrowserKit/Sources/SiteImageView/ImageProcessing/HeroImageFetcher/ImageProvider.swift +++ b/BrowserKit/Sources/SiteImageView/ImageProcessing/HeroImageFetcher/ImageProvider.swift @@ -13,6 +13,7 @@ protocol ImageProvider { } extension NSItemProvider: ImageProvider { + @MainActor func loadObject(ofClass aClass: NSItemProviderReading.Type) async throws -> UIImage { return try await withCheckedThrowingContinuation { continuation in loadObject(ofClass: aClass) { image, error in From 3bf5b1687cb9be3685277fee6be7014b2c02a8c3 Mon Sep 17 00:00:00 2001 From: Litianu Razvan Date: Mon, 19 Aug 2024 12:53:58 +0300 Subject: [PATCH 086/128] FXIOS-9204 Sec Bugzilla 1863838 (#21540) --- focus-ios/Blockzilla/BrowserViewController.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/focus-ios/Blockzilla/BrowserViewController.swift b/focus-ios/Blockzilla/BrowserViewController.swift index a0a1a43a02d7..f40a0bd9947f 100644 --- a/focus-ios/Blockzilla/BrowserViewController.swift +++ b/focus-ios/Blockzilla/BrowserViewController.swift @@ -23,7 +23,9 @@ class BrowserViewController: UIViewController { private lazy var webViewController: LegacyWebViewController = { var menuAction = WebMenuAction.live menuAction.openLink = { url in - self.submit(url: url, source: .action) + if let url = URIFixup.getURL(entry: url.absoluteString) { + self.submit(url: url, source: .action) + } } return LegacyWebViewController(trackingProtectionManager: trackingProtectionManager, webMenuAction: menuAction) }() From 072b582e8cfb5ea78c912e0be67d361f052a5867 Mon Sep 17 00:00:00 2001 From: Litianu Razvan Date: Mon, 19 Aug 2024 14:43:43 +0300 Subject: [PATCH 087/128] Add FXIOS-9655 [Address autofill phase 2] "Manage addresses" link is missing (#21457) * FXIOS-9655 #21258 [Address autofill phase 2] "Manage addresses" link is missing * Remove uuid from view model --- .../BottomSheet/BottomSheetViewModel.swift | 35 ++++++++----------- .../AddressAutofillCoordinator.swift | 15 +++++--- .../CredentialAutofillCoordinator.swift | 6 ++-- .../Client/Coordinators/Router/Route.swift | 1 + .../Coordinators/SettingsCoordinator.swift | 10 ++++++ .../AddressAutoFillBottomSheetView.swift | 35 ++++++++++++++----- .../Address/AddressListViewModel.swift | 1 + .../Home/HomepageViewController.swift | 4 +-- .../Protocols/OnboardingCardDelegate.swift | 3 +- firefox-ios/Client/Frontend/Strings.swift | 11 ++++-- 10 files changed, 80 insertions(+), 41 deletions(-) diff --git a/BrowserKit/Sources/ComponentLibrary/BottomSheet/BottomSheetViewModel.swift b/BrowserKit/Sources/ComponentLibrary/BottomSheet/BottomSheetViewModel.swift index bd758995d8ee..4d3a0819c823 100644 --- a/BrowserKit/Sources/ComponentLibrary/BottomSheet/BottomSheetViewModel.swift +++ b/BrowserKit/Sources/ComponentLibrary/BottomSheet/BottomSheetViewModel.swift @@ -4,13 +4,14 @@ import Foundation import UIKit +import Common /// The view model used to configure a `BottomSheetViewController` public struct BottomSheetViewModel { - private struct UX { - static let cornerRadius: CGFloat = 8 - static let animationTransitionDuration: CGFloat = 0.3 - static let shadowOpacity: Float = 0.3 + public struct UX { + public static let cornerRadius: CGFloat = 8 + public static let animationTransitionDuration: CGFloat = 0.3 + public static let shadowOpacity: Float = 0.3 } public var cornerRadius: CGFloat @@ -21,23 +22,15 @@ public struct BottomSheetViewModel { public var closeButtonA11yLabel: String public var closeButtonA11yIdentifier: String - public init(closeButtonA11yLabel: String, closeButtonA11yIdentifier: String) { - cornerRadius = BottomSheetViewModel.UX.cornerRadius - animationTransitionDuration = BottomSheetViewModel.UX.animationTransitionDuration - backgroundColor = .clear - shouldDismissForTapOutside = true - shadowOpacity = BottomSheetViewModel.UX.shadowOpacity - self.closeButtonA11yLabel = closeButtonA11yLabel - self.closeButtonA11yIdentifier = closeButtonA11yIdentifier - } - - public init(cornerRadius: CGFloat, - animationTransitionDuration: TimeInterval, - backgroundColor: UIColor, - shouldDismissForTapOutside: Bool, - shadowOpacity: Float, - closeButtonA11yLabel: String, - closeButtonA11yIdentifier: String) { + public init( + cornerRadius: CGFloat = BottomSheetViewModel.UX.cornerRadius, + animationTransitionDuration: TimeInterval = BottomSheetViewModel.UX.animationTransitionDuration, + backgroundColor: UIColor = .clear, + shouldDismissForTapOutside: Bool = true, + shadowOpacity: Float = BottomSheetViewModel.UX.shadowOpacity, + closeButtonA11yLabel: String, + closeButtonA11yIdentifier: String + ) { self.cornerRadius = cornerRadius self.animationTransitionDuration = animationTransitionDuration self.backgroundColor = backgroundColor diff --git a/firefox-ios/Client/Coordinators/AddressAutofillCoordinator.swift b/firefox-ios/Client/Coordinators/AddressAutofillCoordinator.swift index b40f7eb54b75..ed9a9308fa67 100644 --- a/firefox-ios/Client/Coordinators/AddressAutofillCoordinator.swift +++ b/firefox-ios/Client/Coordinators/AddressAutofillCoordinator.swift @@ -11,10 +11,12 @@ import WebKit class AddressAutofillCoordinator: BaseCoordinator { // MARK: - Properties + typealias BottomSheetCardParentCoordinator = BrowserNavigationHandler & ParentCoordinatorDelegate private let profile: Profile private let themeManager: ThemeManager private let tabManager: TabManager - private weak var parentCoordinator: ParentCoordinatorDelegate? + private weak var parentCoordinator: BottomSheetCardParentCoordinator? + private var windowUUID: WindowUUID { return tabManager.windowUUID } // MARK: - Initializers @@ -28,7 +30,7 @@ class AddressAutofillCoordinator: BaseCoordinator { init( profile: Profile, router: Router, - parentCoordinator: ParentCoordinatorDelegate?, + parentCoordinator: BottomSheetCardParentCoordinator?, themeManager: ThemeManager = AppContainer.shared.resolve(), tabManager: TabManager ) { @@ -46,8 +48,8 @@ class AddressAutofillCoordinator: BaseCoordinator { func showAddressAutofill(frame: WKFrameInfo?) { let bottomSheetViewModel = BottomSheetViewModel( closeButtonA11yLabel: .CloseButtonTitle, - closeButtonA11yIdentifier: - AccessibilityIdentifiers.Autofill.addressCloseButton) + closeButtonA11yIdentifier: AccessibilityIdentifiers.Autofill.addressCloseButton + ) let viewModel = AddressListViewModel( windowUUID: tabManager.windowUUID, @@ -75,6 +77,11 @@ class AddressAutofillCoordinator: BaseCoordinator { self.parentCoordinator?.didFinish(from: self) } } + viewModel.manageAddressesInfoAction = { [weak self] in + guard let self else { return } + parentCoordinator?.show(settings: .addresses, onDismiss: {}) + parentCoordinator?.didFinish(from: self) + } let bottomSheetView = AddressAutoFillBottomSheetView(windowUUID: tabManager.windowUUID, addressListViewModel: viewModel) let hostingController = SelfSizingHostingController(rootView: bottomSheetView) diff --git a/firefox-ios/Client/Coordinators/CredentialAutofillCoordinator.swift b/firefox-ios/Client/Coordinators/CredentialAutofillCoordinator.swift index 89a5751e3844..4c9f72413c19 100644 --- a/firefox-ios/Client/Coordinators/CredentialAutofillCoordinator.swift +++ b/firefox-ios/Client/Coordinators/CredentialAutofillCoordinator.swift @@ -107,7 +107,8 @@ class CredentialAutofillCoordinator: BaseCoordinator { var bottomSheetViewModel = BottomSheetViewModel( closeButtonA11yLabel: .CloseButtonTitle, - closeButtonA11yIdentifier: AccessibilityIdentifiers.Autofill.creditCardCloseButton) + closeButtonA11yIdentifier: AccessibilityIdentifiers.Autofill.creditCardCloseButton + ) bottomSheetViewModel.shouldDismissForTapOutside = false let bottomSheetVC = BottomSheetViewController( @@ -183,7 +184,8 @@ class CredentialAutofillCoordinator: BaseCoordinator { var bottomSheetViewModel = BottomSheetViewModel( closeButtonA11yLabel: .CloseButtonTitle, - closeButtonA11yIdentifier: AccessibilityIdentifiers.Autofill.loginCloseButton) + closeButtonA11yIdentifier: AccessibilityIdentifiers.Autofill.loginCloseButton + ) bottomSheetViewModel.shouldDismissForTapOutside = false let bottomSheetVC = BottomSheetViewController( diff --git a/firefox-ios/Client/Coordinators/Router/Route.swift b/firefox-ios/Client/Coordinators/Router/Route.swift index 17ff7c864de8..86e6ea78fc7d 100644 --- a/firefox-ios/Client/Coordinators/Router/Route.swift +++ b/firefox-ios/Client/Coordinators/Router/Route.swift @@ -86,6 +86,7 @@ enum Route: Equatable { /// An enumeration representing different sections of the settings menu. enum SettingsSection: String, CaseIterable, Equatable { + case addresses case contentBlocker case clearPrivateData = "clear-private-data" case creditCard diff --git a/firefox-ios/Client/Coordinators/SettingsCoordinator.swift b/firefox-ios/Client/Coordinators/SettingsCoordinator.swift index 7a14676f1916..b9dc99fe8edd 100644 --- a/firefox-ios/Client/Coordinators/SettingsCoordinator.swift +++ b/firefox-ios/Client/Coordinators/SettingsCoordinator.swift @@ -79,6 +79,16 @@ class SettingsCoordinator: BaseCoordinator, private func getSettingsViewController(settingsSection section: Route.SettingsSection) -> UIViewController? { switch section { + case .addresses: + let viewModel = AddressAutofillSettingsViewModel( + profile: profile, + windowUUID: windowUUID + ) + let viewController = AddressAutofillSettingsViewController( + addressAutofillViewModel: viewModel, + windowUUID: windowUUID + ) + return viewController case .newTab: let viewController = NewTabContentSettingsViewController(prefs: profile.prefs, windowUUID: windowUUID) diff --git a/firefox-ios/Client/Frontend/Autofill/Address/AddressAutoFillBottomSheetView.swift b/firefox-ios/Client/Frontend/Autofill/Address/AddressAutoFillBottomSheetView.swift index d288d856a329..916cbe54e9a5 100644 --- a/firefox-ios/Client/Frontend/Autofill/Address/AddressAutoFillBottomSheetView.swift +++ b/firefox-ios/Client/Frontend/Autofill/Address/AddressAutoFillBottomSheetView.swift @@ -8,25 +8,44 @@ import Common import ComponentLibrary struct AddressAutoFillBottomSheetView: View { - // MARK: - Properties - let windowUUID: WindowUUID @Environment(\.themeManager) var themeManager - /// The observed object for managing the address list. @ObservedObject var addressListViewModel: AddressListViewModel + @State private var backgroundColor: Color = .clear // MARK: - Body var body: some View { VStack { - AutofillHeaderView(windowUUID: windowUUID, title: .Addresses.BottomSheet.UseASavedAddress) - Spacer() - AddressScrollView(windowUUID: windowUUID, viewModel: addressListViewModel) - Spacer() + AutofillHeaderView( + windowUUID: windowUUID, + title: .Addresses.BottomSheet.UseASavedAddress + ) + AddressScrollView( + windowUUID: windowUUID, + viewModel: addressListViewModel + ) + AutofillFooterView( + windowUUID: windowUUID, + title: .Addresses.BottomSheet.ManageAddressesButton, + primaryAction: { addressListViewModel.manageAddressesInfoAction?() } + ) } .padding() - .background(Color(themeManager.getCurrentTheme(for: windowUUID).colors.layer1)) + .background(backgroundColor) + .onAppear { + applyTheme(theme: themeManager.getCurrentTheme(for: windowUUID)) + } + .onReceive(NotificationCenter.default.publisher(for: .ThemeDidChange)) { notification in + guard let uuid = notification.windowUUID, uuid == windowUUID else { return } + applyTheme(theme: themeManager.getCurrentTheme(for: windowUUID)) + } + } + + func applyTheme(theme: Theme) { + let color = theme.colors + backgroundColor = Color(color.layer1) } } diff --git a/firefox-ios/Client/Frontend/Autofill/Address/AddressListViewModel.swift b/firefox-ios/Client/Frontend/Autofill/Address/AddressListViewModel.swift index daed44531b3d..789439ece177 100644 --- a/firefox-ios/Client/Frontend/Autofill/Address/AddressListViewModel.swift +++ b/firefox-ios/Client/Frontend/Autofill/Address/AddressListViewModel.swift @@ -41,6 +41,7 @@ final class AddressListViewModel: ObservableObject, FeatureFlaggable { var saveAction: ((@escaping (UpdatableAddressFields) -> Void) -> Void)? var toggleEditModeAction: ((Bool) -> Void)? var presentToast: ((AddressModifiedStatus) -> Void)? + var manageAddressesInfoAction: (() -> Void)? let addressProvider: AddressProvider let themeManager: ThemeManager diff --git a/firefox-ios/Client/Frontend/Home/HomepageViewController.swift b/firefox-ios/Client/Frontend/Home/HomepageViewController.swift index e8d63540432e..b4645040d0ae 100644 --- a/firefox-ios/Client/Frontend/Home/HomepageViewController.swift +++ b/firefox-ios/Client/Frontend/Home/HomepageViewController.swift @@ -412,8 +412,8 @@ class HomepageViewController: let viewController = WallpaperSelectorViewController(viewModel: viewModel, windowUUID: windowUUID) var bottomSheetViewModel = BottomSheetViewModel( closeButtonA11yLabel: .CloseButtonTitle, - closeButtonA11yIdentifier: - AccessibilityIdentifiers.FirefoxHomepage.OtherButtons.closeButton) + closeButtonA11yIdentifier: AccessibilityIdentifiers.FirefoxHomepage.OtherButtons.closeButton + ) bottomSheetViewModel.shouldDismissForTapOutside = false let bottomSheetVC = BottomSheetViewController( viewModel: bottomSheetViewModel, diff --git a/firefox-ios/Client/Frontend/Onboarding/Protocols/OnboardingCardDelegate.swift b/firefox-ios/Client/Frontend/Onboarding/Protocols/OnboardingCardDelegate.swift index 97c0d19cb1d0..8e8ac1466fe9 100644 --- a/firefox-ios/Client/Frontend/Onboarding/Protocols/OnboardingCardDelegate.swift +++ b/firefox-ios/Client/Frontend/Onboarding/Protocols/OnboardingCardDelegate.swift @@ -110,7 +110,8 @@ extension OnboardingCardDelegate where Self: OnboardingViewControllerProtocol, var bottomSheetViewModel = BottomSheetViewModel( closeButtonA11yLabel: .CloseButtonTitle, closeButtonA11yIdentifier: - AccessibilityIdentifiers.Onboarding.bottomSheetCloseButton) + AccessibilityIdentifiers.Onboarding.bottomSheetCloseButton + ) bottomSheetViewModel.shouldDismissForTapOutside = true let bottomSheetVC = BottomSheetViewController( viewModel: bottomSheetViewModel, diff --git a/firefox-ios/Client/Frontend/Strings.swift b/firefox-ios/Client/Frontend/Strings.swift index 1f9fc846d45d..5066f84c5614 100644 --- a/firefox-ios/Client/Frontend/Strings.swift +++ b/firefox-ios/Client/Frontend/Strings.swift @@ -267,17 +267,17 @@ extension String { value: "Use saved address", comment: "Displayed inside the keyboard hint when a user is entering their address and has at least one saved address. Indicates that there are stored addresses available for use in filling out a form.") public static let SaveAddressesToFirefox = MZLocalizedString( - key: "", // Addresses.Settings.SaveToFirefox.Title.v129 + key: "Addresses.Settings.SaveToFirefox.Title.v130", tableName: "Settings", value: "Save Addresses to %@", comment: "Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app.") public static let SecureSaveInfo = MZLocalizedString( - key: "", // Addresses.Settings.SecureSaveInfo.Description.v129 + key: "Addresses.Settings.SecureSaveInfo.Description.v130", tableName: "Settings", value: "Securely save your information to get quick access to it later.", comment: "Description text for the content unavailable view informing users they can create or add new addresses.") public static let ListItemA11y = MZLocalizedString( - key: "", // Addresses.Settings.ListItemA11y.v129 + key: "Addresses.Settings.ListItemA11y.v130", tableName: "Settings", value: "Address for %@", comment: "Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available.") @@ -572,6 +572,11 @@ extension String { tableName: "BottomSheet", value: "Use a saved address?", comment: "When a user is in the process of entering an address, a screen pops up prompting the user if they want to use a saved address. This string is used as the title label of the screen.") + public static let ManageAddressesButton = MZLocalizedString( + key: "Addresses.ManageAddressesButton.v130", + tableName: "Settings", + value: "Manage addresses", + comment: "This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses.") } } } From 10be45203409bf0cbddfb856e1e224d6558a15fe Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 19 Aug 2024 11:16:30 -0400 Subject: [PATCH 088/128] Localize [v131] String import 2024-08-19 (#21550) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- firefox-ios/Client.xcodeproj/project.pbxproj | 2 ++ firefox-ios/Client/id.lproj/InfoPlist.strings | 3 ++ .../EnhancedTrackingProtection.strings | 3 ++ .../EnhancedTrackingProtection.strings | 3 ++ .../da.lproj/Microsurvey.strings | 3 ++ .../Supporting Files/da.lproj/Toolbar.strings | 3 ++ .../eu.lproj/EditAddress.strings | 3 ++ .../EnhancedTrackingProtection.strings | 3 ++ .../eu.lproj/Microsurvey.strings | 3 ++ .../Supporting Files/eu.lproj/Toolbar.strings | 6 ++++ .../EnhancedTrackingProtection.strings | 3 ++ .../EnhancedTrackingProtection.strings | 3 ++ .../EnhancedTrackingProtection.strings | 3 ++ .../EnhancedTrackingProtection.strings | 3 ++ .../EnhancedTrackingProtection.strings | 3 ++ .../EnhancedTrackingProtection.strings | 3 ++ .../EnhancedTrackingProtection.strings | 3 ++ .../Shared/id.lproj/Localizable.strings | 36 +++++++++++++++++++ .../Shared/id.lproj/LoginManager.strings | 15 ++++++++ 19 files changed, 104 insertions(+) create mode 100644 firefox-ios/Shared/Supporting Files/eu.lproj/Toolbar.strings diff --git a/firefox-ios/Client.xcodeproj/project.pbxproj b/firefox-ios/Client.xcodeproj/project.pbxproj index 4cc1f677b777..0c232af4ec9e 100644 --- a/firefox-ios/Client.xcodeproj/project.pbxproj +++ b/firefox-ios/Client.xcodeproj/project.pbxproj @@ -4666,6 +4666,7 @@ 43A03B3329E427890035374E /* kk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kk; path = "kk.lproj/Edit Card.strings"; sourceTree = ""; }; 43A03D882A0BCAE30002CBFF /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/FirefoxSync.strings"; sourceTree = ""; }; 43A03D892A0BCAE30002CBFF /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/Upgrade.strings"; sourceTree = ""; }; + 43A04D712C73605C0052F8EB /* eu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eu; path = eu.lproj/Toolbar.strings; sourceTree = ""; }; 43A076362BCD41BC00149887 /* be */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = be; path = be.lproj/BottomSheet.strings; sourceTree = ""; }; 43A076372BCD41BC00149887 /* be */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = be; path = be.lproj/KeyboardAccessory.strings; sourceTree = ""; }; 43A173162A24C0B5009C10B1 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/DisplayCard.strings; sourceTree = ""; }; @@ -19127,6 +19128,7 @@ 43E0BE422C60EC4C004FED65 /* hr */, 433D64C72C60EE1100CEC389 /* nb */, 43E7071E2C6A26FC00A29AE4 /* hu */, + 43A04D712C73605C0052F8EB /* eu */, ); name = Toolbar.strings; sourceTree = ""; diff --git a/firefox-ios/Client/id.lproj/InfoPlist.strings b/firefox-ios/Client/id.lproj/InfoPlist.strings index c9a9afb24365..082cb822d881 100644 --- a/firefox-ios/Client/id.lproj/InfoPlist.strings +++ b/firefox-ios/Client/id.lproj/InfoPlist.strings @@ -7,6 +7,9 @@ /* Privacy - Camera Usage Description */ "NSCameraUsageDescription" = "Firefox menggunakan kamera Anda untuk memindai kode QR dan mengambil foto dan video."; +/* Privacy - Face ID Usage Description */ +"NSFaceIDUsageDescription" = "Firefox memerlukan Face ID untuk mengakses kata sandi dan metode pembayaran Anda yang tersimpan."; + /* Privacy - Location When In Use Usage Description */ "NSLocationWhenInUseUsageDescription" = "Situs web yang Anda kunjungi dapat meminta lokasi Anda."; diff --git a/firefox-ios/Shared/Supporting Files/bs.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/bs.lproj/EnhancedTrackingProtection.strings index d18a0b0b9e20..46572e591e84 100644 --- a/firefox-ios/Shared/Supporting Files/bs.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/bs.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Veza nije sigurna"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Nisu pronađeni tragači"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Kolačići za praćenje između web stranica: %@"; diff --git a/firefox-ios/Shared/Supporting Files/da.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/da.lproj/EnhancedTrackingProtection.strings index 0dcc6696114b..d2ad7e917480 100644 --- a/firefox-ios/Shared/Supporting Files/da.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/da.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Forbindelsen er ikke sikker"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Ingen sporings-mekanismer fundet"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Sporings-cookies på tværs af websteder: %@"; diff --git a/firefox-ios/Shared/Supporting Files/da.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/da.lproj/Microsurvey.strings index cb39cbf2214c..f16497da59c9 100644 --- a/firefox-ios/Shared/Supporting Files/da.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/da.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Ikke valgt"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Undersøgelse"; + diff --git a/firefox-ios/Shared/Supporting Files/da.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/da.lproj/Toolbar.strings index 896bdfe93054..2541f1d3f1b7 100644 --- a/firefox-ios/Shared/Supporting Files/da.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/da.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Nyt faneblad"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Luk dette faneblad"; + diff --git a/firefox-ios/Shared/Supporting Files/eu.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/eu.lproj/EditAddress.strings index 8ff1be80188b..67d1009c9fde 100644 --- a/firefox-ios/Shared/Supporting Files/eu.lproj/EditAddress.strings +++ b/firefox-ios/Shared/Supporting Files/eu.lproj/EditAddress.strings @@ -130,6 +130,9 @@ /* Toast message indicating an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveError.v129" = "Ez da helbidea gorde"; +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Ezin da helbidea kendu"; + /* Suggestion to try again after an error occurred while trying to save an address. */ "Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Saiatu berriro"; diff --git a/firefox-ios/Shared/Supporting Files/eu.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/eu.lproj/EnhancedTrackingProtection.strings index c4ff339d6544..20f4d4b5b7a5 100644 --- a/firefox-ios/Shared/Supporting Files/eu.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/eu.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Konexio ez-segurua"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Ez da jarraipen-elementurik aurkitu"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Guneen arteko cookie jarraipen-egileak: %@"; diff --git a/firefox-ios/Shared/Supporting Files/eu.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/eu.lproj/Microsurvey.strings index be49974ab42f..1f83c3cd1388 100644 --- a/firefox-ios/Shared/Supporting Files/eu.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/eu.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Desautatuta"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Inkesta"; + diff --git a/firefox-ios/Shared/Supporting Files/eu.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/eu.lproj/Toolbar.strings new file mode 100644 index 000000000000..b1faf54105ee --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/eu.lproj/Toolbar.strings @@ -0,0 +1,6 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Fitxa berria"; + +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Itxi fitxa"; + diff --git a/firefox-ios/Shared/Supporting Files/fr.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/fr.lproj/EnhancedTrackingProtection.strings index 635ee4707b32..7a1dbc311147 100644 --- a/firefox-ios/Shared/Supporting Files/fr.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/fr.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Connexion non sécurisée"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Aucun traqueur trouvé"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Cookies de pistage intersites : %@"; diff --git a/firefox-ios/Shared/Supporting Files/hu.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/hu.lproj/EnhancedTrackingProtection.strings index 0bb2db1dc638..d4f3c1d48eca 100644 --- a/firefox-ios/Shared/Supporting Files/hu.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/hu.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "A kapcsolat nem biztonságos"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Nem találhatóak nyomkövetők"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Webhelyek közötti nyomkövető sütik: %@"; diff --git a/firefox-ios/Shared/Supporting Files/hy-AM.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/hy-AM.lproj/EnhancedTrackingProtection.strings index fc7409c00e57..e631ae3eafbc 100644 --- a/firefox-ios/Shared/Supporting Files/hy-AM.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/hy-AM.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Կապակցումն անվտանգ չէ"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Հետագծողներ չեն գտնվել"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Միջակայքային հետևող նշոցիկներ` %@"; diff --git a/firefox-ios/Shared/Supporting Files/ja.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/ja.lproj/EnhancedTrackingProtection.strings index 7f718b4e4418..b465bd779463 100644 --- a/firefox-ios/Shared/Supporting Files/ja.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/ja.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "安全でない接続"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "トラッカーが見つかりませんでした"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "クロスサイトトラッキング Cookie: %@"; diff --git a/firefox-ios/Shared/Supporting Files/nb.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/nb.lproj/EnhancedTrackingProtection.strings index 7ab6d5fc288c..c1ba2097de4d 100644 --- a/firefox-ios/Shared/Supporting Files/nb.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/nb.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Tilkoblingen er ikke sikker"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Fant ingen sporere"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Sporingsinfokapsler på tvers av nettsteder: %@"; diff --git a/firefox-ios/Shared/Supporting Files/pa-IN.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/pa-IN.lproj/EnhancedTrackingProtection.strings index 356ab77d7ca5..b70d4cb411fd 100644 --- a/firefox-ios/Shared/Supporting Files/pa-IN.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/pa-IN.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "ਕਨੈਕਸ਼ਨ ਸੁਰੱਖਿਅਤ ਨਹੀਂ ਹੈ"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "ਕੋਈ ਟਰੈਕਰ ਨਹੀਂ ਲੱਭੇ"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "ਅੰਤਰ-ਸਾਈਟ ਟਰੈਕਿੰਗ ਕੂਕੀਜ਼: %@"; diff --git a/firefox-ios/Shared/Supporting Files/zh-TW.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/zh-TW.lproj/EnhancedTrackingProtection.strings index 33f39f1e2b2a..677c4e9062d0 100644 --- a/firefox-ios/Shared/Supporting Files/zh-TW.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/zh-TW.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "連線不安全"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "找不到追蹤器"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "跨網站追蹤 Cookie:%@"; diff --git a/firefox-ios/Shared/id.lproj/Localizable.strings b/firefox-ios/Shared/id.lproj/Localizable.strings index cf1245536e23..e8c475060a38 100644 --- a/firefox-ios/Shared/id.lproj/Localizable.strings +++ b/firefox-ios/Shared/id.lproj/Localizable.strings @@ -166,12 +166,18 @@ /* The label text in the Button Toast for switching to a fresh New Private Tab. */ "ContextMenu.ButtonToast.NewPrivateTabOpened.LabelText" = "Tab Pribadi Baru dibuka"; +/* The label text in the Button Toast for switching to a fresh New Private Tab. */ +"ContextMenu.ButtonToast.NewPrivateTabOpened.LabelText.v113" = "Tab Pribadi Baru Dibuka"; + /* The button text in the Button Toast for switching to a fresh New Tab. */ "ContextMenu.ButtonToast.NewTabOpened.ButtonText" = "Ganti"; /* The label text in the Button Toast for switching to a fresh New Tab. */ "ContextMenu.ButtonToast.NewTabOpened.LabelText" = "Tab Baru dibuka"; +/* The label text in the Button Toast for switching to a fresh New Tab. */ +"ContextMenu.ButtonToast.NewTabOpened.LabelText.v114" = "Tab Baru Dibuka"; + /* Context menu item for copying an image to the clipboard */ "ContextMenu.CopyImageButtonTitle" = "Salin Gambar"; @@ -343,6 +349,9 @@ /* When a user taps and holds on an item from the Recently Visited section, this label will appear indicating the option to remove that item. */ "FirefoxHome.RecentHistory.Remove" = "Hapus"; +/* Label showing how many pages there is in a search group. %d represents a number */ +"FirefoxHomepage.Common.PagesCount.v112" = "Halaman: %d"; + /* The title for the Settings context menu action for sponsored tiles in the Firefox home page shortcuts section. Clicking this brings the users to the Shortcuts Settings. */ "FirefoxHomepage.ContextualMenu.Settings.v101" = "Pengaturan"; @@ -748,6 +757,9 @@ /* Label for the button, displayed in the menu, takes you to History screen when pressed. */ "Menu.History.Label" = "Riwayat"; +/* Label for the new private tab button in the menu page. Pressing this button opens a new private tab. */ +"Menu.NewPrivateTab.Label" = "Tab Pribadi Baru"; + /* Label for the new tab button in the menu page. Pressing this button opens a new tab. */ "Menu.NewTab.v99" = "Tab Baru"; @@ -847,6 +859,9 @@ /* The title for the option to view the What's new page. */ "Menu.WhatsNew.Title" = "Kabar Terbaru"; +/* Label for the zoom page button in the menu, used to show the Zoom Page bar. The placeholder shows the current zoom level in percent. */ +"Menu.ZoomPage.Title.v113" = "Perbesar (%@)"; + /* Accessibility label for Mobile Device image in remote tabs list */ "mobile device" = "perangkat seluler"; @@ -1132,6 +1147,9 @@ /* The placeholder for URL Field when saving a custom search engine */ "Settings.AddCustomEngine.URLPlaceholder" = "URL (Ganti Kueri dengan %s)"; +/* Title of setting to block opening external apps when pressing links. */ +"Settings.BlockOpeningExternalApps.Title" = "Blokir Pembukaan Aplikasi Eksternal"; + /* Button in Data Management that clears all items. */ "Settings.ClearAllWebsiteData.Clear.Button" = "Hapus Semua Data Situs Web"; @@ -1360,6 +1378,9 @@ /* Option in settings to show a blank page when you open a new tab */ "Settings.NewTab.Option.BlankPage" = "Laman Kosong"; +/* Option in settings to show your homepage when you open a new tab */ +"Settings.NewTab.Option.Custom" = "Ubahsuai"; + /* Option in settings to show Firefox Home when you open a new tab */ "Settings.NewTab.Option.FirefoxHome" = "Firefox Home"; @@ -1384,6 +1405,9 @@ /* Description displayed under the ”Offer to Open Copied Link” option. See https://bug1223660.bmoattachments.org/attachment.cgi?id=8898349 */ "Settings.OfferClipboardBar.Status" = "Ketika Membuka Firefox"; +/* Description displayed under the ”Offer to Open Copied Link” option. See https://bug1223660.bmoattachments.org/attachment.cgi?id=8898349. Placeholder is for the app name. */ +"Settings.OfferClipboardBar.Status.v128" = "Saat membuka %@"; + /* Description displayed under the ”Offer to Open Copied Link” option. See https://bug1223660.bmoattachments.org/attachment.cgi?id=8898349 */ "Settings.OfferClipboardBar.StatusV2" = "Ketika Membuka Firefox"; @@ -1492,6 +1516,9 @@ /* Dismiss button for the tracker protection alert. */ "Settings.TrackingProtection.Alert.Button" = "Oke, paham!"; +/* Decription for the tracker protection alert. */ +"Settings.TrackingProtection.Alert.Description" = "Jika situs tidak berfungsi seperti yang diharapkan, ketuk kunci di bilah alamat dan matikan Perlindungan Pelacakan yang Ditingkatkan untuk laman itu."; + /* Title for the tracker protection alert. */ "Settings.TrackingProtection.Alert.Title" = "Perhatian!"; @@ -1504,6 +1531,12 @@ /* Additional information about your Enhanced Tracking Protection */ "Settings.TrackingProtection.ProtectionCellFooter" = "Mengurangi iklan yang ditargetkan dan membantu menghentikan pengiklan melacak penjelajahan Anda."; +/* Footer information for tracker protection level. */ +"Settings.TrackingProtection.ProtectionLevel.Footer" = "Jika situs tidak berfungsi seperti yang diharapkan, ketuk kunci di bilah alamat dan matikan Perlindungan Pelacakan yang Ditingkatkan untuk laman itu."; + +/* Footer information for tracker protection level. */ +"Settings.TrackingProtection.ProtectionLevel.Footer.Lock" = "Jika situs tidak berfungsi seperti yang diharapkan, ketuk kunci di bilah alamat dan matikan Perlindungan Pelacakan yang Ditingkatkan untuk laman itu."; + /* Description for standard level tracker protection */ "Settings.TrackingProtection.ProtectionLevelStandard.Description" = "Mengizinkan beberapa pelacak agar situs web berfungsi dengan baik."; @@ -1519,6 +1552,9 @@ /* Tracking protection settings option for using the basic blocklist. */ "Settings.TrackingProtectionOption.BasicBlockList" = "Standar (baku)"; +/* Tracking protection settings status showing the current option selected. */ +"Settings.TrackingProtectionOption.BasicBlockList.Status" = "Standar"; + /* Tracking protection settings option for using the strict blocklist. */ "Settings.TrackingProtectionOption.BlockListStrict" = "Ketat"; diff --git a/firefox-ios/Shared/id.lproj/LoginManager.strings b/firefox-ios/Shared/id.lproj/LoginManager.strings index 53dd45217662..1b7957a9aca6 100644 --- a/firefox-ios/Shared/id.lproj/LoginManager.strings +++ b/firefox-ios/Shared/id.lproj/LoginManager.strings @@ -16,6 +16,21 @@ /* Label for the button used to delete the current login. */ "Delete" = "Hapus"; +/* Prompt option for cancelling out of deletion */ +"DeleteLoginAlert.DeleteButton.Cancel.v122" = "Batal"; + +/* Label for the button used to delete the current login. */ +"DeleteLoginAlert.DeleteButton.Title.v122" = "Hapus"; + +/* Prompt message warning the user that deleting non-synced logins will permanently remove them, when they attempt to do so */ +"DeleteLoginAlert.Message.Local.v122" = "Anda tidak dapat membatalkan tindakan ini."; + +/* Prompt message warning the user that deleted logins will remove logins from all connected devices */ +"DeleteLoginAlert.Message.Synced.v122" = "Ini akan menghapus kata sandi dari semua perangkat Anda yang disinkronkan."; + +/* Title for the prompt that appears when the user deletes a login. */ +"DeleteLoginsAlert.Title.v122" = "Hapus Kata Sandi?"; + /* Label for the button used to deselect all logins. */ "Deselect All" = "Batalkan semua pilihan"; From 186a5eae9887cbaac65f8996682c7b25c2efe411 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 19 Aug 2024 11:17:03 -0400 Subject: [PATCH 089/128] Auto update SPM with latest rust-component release 131.0.20240815050258 (#21535) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- firefox-ios/Client.xcodeproj/project.pbxproj | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- focus-ios/Blockzilla.xcodeproj/project.pbxproj | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/firefox-ios/Client.xcodeproj/project.pbxproj b/firefox-ios/Client.xcodeproj/project.pbxproj index 0c232af4ec9e..2877015a5523 100644 --- a/firefox-ios/Client.xcodeproj/project.pbxproj +++ b/firefox-ios/Client.xcodeproj/project.pbxproj @@ -23151,7 +23151,7 @@ repositoryURL = "https://github.com/mozilla/rust-components-swift.git"; requirement = { kind = exactVersion; - version = 131.0.20240808050223; + version = 131.0.20240815050258; }; }; 435C85EE2788F4D00072B526 /* XCRemoteSwiftPackageReference "glean-swift" */ = { diff --git a/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 2fe1e98a129e..88ce2ba8093b 100644 --- a/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -95,8 +95,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/mozilla/rust-components-swift.git", "state" : { - "revision" : "f04ad3ebdca06c93e14091efa7756473adb7c51a", - "version" : "131.0.20240808050223" + "revision" : "5f9d1dbd9457d56ed16090e1ff9a38b9f0ffab19", + "version" : "131.0.20240815050258" } }, { diff --git a/focus-ios/Blockzilla.xcodeproj/project.pbxproj b/focus-ios/Blockzilla.xcodeproj/project.pbxproj index e1025733b351..ec2735f6d85e 100644 --- a/focus-ios/Blockzilla.xcodeproj/project.pbxproj +++ b/focus-ios/Blockzilla.xcodeproj/project.pbxproj @@ -7159,7 +7159,7 @@ repositoryURL = "https://github.com/mozilla/rust-components-swift"; requirement = { kind = exactVersion; - version = 131.0.20240808050223; + version = 131.0.20240815050258; }; }; 8A0E7F2C2BA0F0E0006BC6B6 /* XCRemoteSwiftPackageReference "Fuzi" */ = { diff --git a/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index e6df9a11794b..2a64910219ad 100644 --- a/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -51,8 +51,8 @@ "repositoryURL": "https://github.com/mozilla/rust-components-swift", "state": { "branch": null, - "revision": "f04ad3ebdca06c93e14091efa7756473adb7c51a", - "version": "131.0.20240808050223" + "revision": "5f9d1dbd9457d56ed16090e1ff9a38b9f0ffab19", + "version": "131.0.20240815050258" } }, { From 373f3e619fea0f3866ae598f32cbf69b9064fb99 Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Mon, 19 Aug 2024 17:38:50 +0100 Subject: [PATCH 090/128] Bump - Update Sentry to version 8.34.0 (#21554) --- BrowserKit/Package.resolved | 4 ++-- BrowserKit/Package.swift | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- firefox-ios/Client.xcodeproj/project.pbxproj | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- focus-ios/Blockzilla.xcodeproj/project.pbxproj | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/BrowserKit/Package.resolved b/BrowserKit/Package.resolved index da740db42b72..c97fbc9996a9 100644 --- a/BrowserKit/Package.resolved +++ b/BrowserKit/Package.resolved @@ -41,8 +41,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/getsentry/sentry-cocoa.git", "state" : { - "revision" : "7fc7ca43967e2980d8691a8e017c118a84133aac", - "version" : "8.26.0" + "revision" : "d2ced2d961b34573ebd2ea0567a2f1408e90f0ae", + "version" : "8.34.0" } }, { diff --git a/BrowserKit/Package.swift b/BrowserKit/Package.swift index 9dff77c7f025..e3e5ecf3ff75 100644 --- a/BrowserKit/Package.swift +++ b/BrowserKit/Package.swift @@ -52,7 +52,7 @@ let package = Package( exact: "2.0.0"), .package( url: "https://github.com/getsentry/sentry-cocoa.git", - exact: "8.26.0"), + exact: "8.34.0"), .package(url: "https://github.com/nbhasin2/GCDWebServer.git", branch: "master") ], diff --git a/SampleBrowser/SampleBrowser.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/SampleBrowser/SampleBrowser.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index da740db42b72..c97fbc9996a9 100644 --- a/SampleBrowser/SampleBrowser.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/SampleBrowser/SampleBrowser.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -41,8 +41,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/getsentry/sentry-cocoa.git", "state" : { - "revision" : "7fc7ca43967e2980d8691a8e017c118a84133aac", - "version" : "8.26.0" + "revision" : "d2ced2d961b34573ebd2ea0567a2f1408e90f0ae", + "version" : "8.34.0" } }, { diff --git a/SampleComponentLibraryApp/SampleComponentLibraryApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/SampleComponentLibraryApp/SampleComponentLibraryApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index da740db42b72..c97fbc9996a9 100644 --- a/SampleComponentLibraryApp/SampleComponentLibraryApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/SampleComponentLibraryApp/SampleComponentLibraryApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -41,8 +41,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/getsentry/sentry-cocoa.git", "state" : { - "revision" : "7fc7ca43967e2980d8691a8e017c118a84133aac", - "version" : "8.26.0" + "revision" : "d2ced2d961b34573ebd2ea0567a2f1408e90f0ae", + "version" : "8.34.0" } }, { diff --git a/firefox-ios/Client.xcodeproj/project.pbxproj b/firefox-ios/Client.xcodeproj/project.pbxproj index 2877015a5523..174ca7c40dfd 100644 --- a/firefox-ios/Client.xcodeproj/project.pbxproj +++ b/firefox-ios/Client.xcodeproj/project.pbxproj @@ -23191,7 +23191,7 @@ repositoryURL = "https://github.com/getsentry/sentry-cocoa.git"; requirement = { kind = exactVersion; - version = 8.26.0; + version = 8.34.0; }; }; 8AB30EC62B6C038600BD9A9B /* XCRemoteSwiftPackageReference "lottie-ios" */ = { diff --git a/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 88ce2ba8093b..3aa85553d9e6 100644 --- a/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -104,8 +104,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/getsentry/sentry-cocoa.git", "state" : { - "revision" : "7fc7ca43967e2980d8691a8e017c118a84133aac", - "version" : "8.26.0" + "revision" : "d2ced2d961b34573ebd2ea0567a2f1408e90f0ae", + "version" : "8.34.0" } }, { diff --git a/focus-ios/Blockzilla.xcodeproj/project.pbxproj b/focus-ios/Blockzilla.xcodeproj/project.pbxproj index ec2735f6d85e..cf72a52bbeb3 100644 --- a/focus-ios/Blockzilla.xcodeproj/project.pbxproj +++ b/focus-ios/Blockzilla.xcodeproj/project.pbxproj @@ -7191,7 +7191,7 @@ repositoryURL = "https://github.com/getsentry/sentry-cocoa"; requirement = { kind = exactVersion; - version = 8.26.0; + version = 8.34.0; }; }; /* End XCRemoteSwiftPackageReference section */ diff --git a/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 2a64910219ad..78036b5d895f 100644 --- a/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -60,8 +60,8 @@ "repositoryURL": "https://github.com/getsentry/sentry-cocoa", "state": { "branch": null, - "revision": "7fc7ca43967e2980d8691a8e017c118a84133aac", - "version": "8.26.0" + "revision": "d2ced2d961b34573ebd2ea0567a2f1408e90f0ae", + "version": "8.34.0" } }, { From 32a554e8104ddc496e670b66ef36db05fbba7205 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 20 Aug 2024 11:45:20 +0200 Subject: [PATCH 091/128] Refactor - auto update credential provider script (#21313) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .../Client/Assets/CC_Script/AutofillTelemetry.sys.mjs | 4 ++-- .../Client/Assets/CC_Script/FormAutofillHandler.sys.mjs | 8 ++++---- .../Client/Assets/CC_Script/FormAutofillSection.sys.mjs | 2 +- .../Client/Assets/CC_Script/HeuristicsRegExp.sys.mjs | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/firefox-ios/Client/Assets/CC_Script/AutofillTelemetry.sys.mjs b/firefox-ios/Client/Assets/CC_Script/AutofillTelemetry.sys.mjs index a637c3766886..f76afd96581d 100644 --- a/firefox-ios/Client/Assets/CC_Script/AutofillTelemetry.sys.mjs +++ b/firefox-ios/Client/Assets/CC_Script/AutofillTelemetry.sys.mjs @@ -122,7 +122,7 @@ class AutofillTelemetryBase { const extra = this.#initFormEventExtra("unavailable"); for (const fieldDetail of fieldDetails) { - let { filledState, value } = data[fieldDetail.elementId]; + let { filledState, value } = data.get(fieldDetail.elementId); switch (filledState) { case FIELD_STATES.AUTO_FILLED: filledState = "filled"; @@ -152,7 +152,7 @@ class AutofillTelemetryBase { const extra = this.#initFormEventExtra("unavailable"); for (const fieldDetail of fieldDetails) { - let { filledState, value } = data[fieldDetail.elementId]; + let { filledState, value } = data.get(fieldDetail.elementId); switch (filledState) { case FIELD_STATES.AUTO_FILLED: filledState = "autofilled"; diff --git a/firefox-ios/Client/Assets/CC_Script/FormAutofillHandler.sys.mjs b/firefox-ios/Client/Assets/CC_Script/FormAutofillHandler.sys.mjs index f8d7d6309beb..3c0fdb68a14e 100644 --- a/firefox-ios/Client/Assets/CC_Script/FormAutofillHandler.sys.mjs +++ b/firefox-ios/Client/Assets/CC_Script/FormAutofillHandler.sys.mjs @@ -227,7 +227,7 @@ export class FormAutofillHandler { * @param {object} profile * A profile to be previewed with */ - async previewFields(elementIds, profile) { + previewFields(elementIds, profile) { this.getAdaptedProfiles([profile]); for (const fieldDetail of this.fieldDetails) { @@ -945,15 +945,15 @@ export class FormAutofillHandler { * value: The value of the element */ collectFormFilledData() { - const filledData = {}; + const filledData = new Map(); for (const fieldDetail of this.fieldDetails) { const element = fieldDetail.element; - filledData[fieldDetail.elementId] = { + filledData.set(fieldDetail.elementId, { filledState: element.autofillState, filledValue: this.computeFillingValue(fieldDetail), value: element.value, - }; + }); } return filledData; } diff --git a/firefox-ios/Client/Assets/CC_Script/FormAutofillSection.sys.mjs b/firefox-ios/Client/Assets/CC_Script/FormAutofillSection.sys.mjs index f1626ecec1e6..61bb1a52195f 100644 --- a/firefox-ios/Client/Assets/CC_Script/FormAutofillSection.sys.mjs +++ b/firefox-ios/Client/Assets/CC_Script/FormAutofillSection.sys.mjs @@ -294,7 +294,7 @@ export class FormAutofillSection { }; for (const detail of this.fieldDetails) { - const { filledValue } = formFilledData[detail.elementId]; + const { filledValue } = formFilledData.get(detail.elementId); if ( !filledValue || diff --git a/firefox-ios/Client/Assets/CC_Script/HeuristicsRegExp.sys.mjs b/firefox-ios/Client/Assets/CC_Script/HeuristicsRegExp.sys.mjs index c4141628f8fe..1b7ff0d0b61f 100644 --- a/firefox-ios/Client/Assets/CC_Script/HeuristicsRegExp.sys.mjs +++ b/firefox-ios/Client/Assets/CC_Script/HeuristicsRegExp.sys.mjs @@ -555,7 +555,7 @@ export const HeuristicsRegExp = { // Note: `cc-name` expression has been moved up, above `name`, in // order to handle specialization through ordering. "cc-number": - "(add)?(?:card|cc|acct).?(?:number|#|no|num|field)" + + "(add)?(?:card|cc|acct).?(?:number|#|no|num|field(?!s)|pan)" + // In order to support webkit we convert all negative lookbehinds to a capture group // (? (?notword)|word // TODO: Bug 1829583 From f442c900048f41dc518f6153dbe9f72f0e980c5d Mon Sep 17 00:00:00 2001 From: Cyndi Chin Date: Tue, 20 Aug 2024 08:44:29 -0400 Subject: [PATCH 092/128] Bugfix FXIOS-9811 [Unit Tests] Add mock autofill for CreditCardBottom (#21552) --- firefox-ios/Client.xcodeproj/project.pbxproj | 26 +++- .../CredentialAutofillCoordinator.swift | 2 +- .../CreditCardBottomSheetViewModel.swift | 8 +- .../CreditCardProvider.swift | 23 +++ .../Mocks/MockCreditCardProvider.swift | 48 ++++++ .../Autofill/Mocks/MockLoginProvider.swift | 36 +++++ .../CreditCardBottomSheetViewModelTests.swift | 146 ++++++------------ .../Mocks/MockLoginViewModelDelegate.swift | 31 ---- 8 files changed, 180 insertions(+), 140 deletions(-) create mode 100644 firefox-ios/Client/Frontend/Autofill/CreditCard/CreditCardBottomSheet/CreditCardProvider.swift create mode 100644 firefox-ios/firefox-ios-tests/Tests/ClientTests/Autofill/Mocks/MockCreditCardProvider.swift create mode 100644 firefox-ios/firefox-ios-tests/Tests/ClientTests/Autofill/Mocks/MockLoginProvider.swift diff --git a/firefox-ios/Client.xcodeproj/project.pbxproj b/firefox-ios/Client.xcodeproj/project.pbxproj index 174ca7c40dfd..a8375c24eed5 100644 --- a/firefox-ios/Client.xcodeproj/project.pbxproj +++ b/firefox-ios/Client.xcodeproj/project.pbxproj @@ -780,7 +780,6 @@ 8A8629E2288096C40096DDB1 /* BookmarksFolderCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A8629E1288096C40096DDB1 /* BookmarksFolderCell.swift */; }; 8A8629E72880B7330096DDB1 /* BookmarksPanelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A8629E52880B69C0096DDB1 /* BookmarksPanelTests.swift */; }; 8A86DAD8277298DE00D7BFFF /* ClosedTabsStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A86DAD7277298DE00D7BFFF /* ClosedTabsStoreTests.swift */; }; - 8A880C442C63CFE200B77F23 /* MockLoginViewModelDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A880C432C63CFE200B77F23 /* MockLoginViewModelDelegate.swift */; }; 8A88815A2B20FFE0009635AE /* GCDWebServers in Frameworks */ = {isa = PBXBuildFile; productRef = 8A8881592B20FFE0009635AE /* GCDWebServers */; }; 8A88815C2B2103AD009635AE /* WebEngine in Frameworks */ = {isa = PBXBuildFile; productRef = 8A88815B2B2103AD009635AE /* WebEngine */; }; 8A88815E2B21071E009635AE /* GCDWebServers in Frameworks */ = {isa = PBXBuildFile; productRef = 8A88815D2B21071E009635AE /* GCDWebServers */; }; @@ -849,6 +848,10 @@ 8AB8574627D97CB00075C173 /* HomepageContextMenuProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AB8574527D97CB00075C173 /* HomepageContextMenuProtocol.swift */; }; 8AB8574827D97CD40075C173 /* HomePanelType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AB8574727D97CD40075C173 /* HomePanelType.swift */; }; 8AB8574A27D97CE90075C173 /* HomePanelDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AB8574927D97CE90075C173 /* HomePanelDelegate.swift */; }; + 8AB893A32C73AF5200DAEED7 /* MockCreditCardProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AB893A22C73AF5200DAEED7 /* MockCreditCardProvider.swift */; }; + 8AB893A62C73AFBA00DAEED7 /* MockLoginProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AB893A52C73AFBA00DAEED7 /* MockLoginProvider.swift */; }; + 8AB893A72C73AFCC00DAEED7 /* MockLoginViewModelDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A880C432C63CFE200B77F23 /* MockLoginViewModelDelegate.swift */; }; + 8AB893A92C73CBBD00DAEED7 /* CreditCardProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AB893A82C73CBBD00DAEED7 /* CreditCardProvider.swift */; }; 8ABA9C8D28931223002C0077 /* MockDispatchQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8ABA9C8C28931223002C0077 /* MockDispatchQueue.swift */; }; 8ABA9C8E28931288002C0077 /* JumpBackInDataAdaptorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8ABA9C8A28931207002C0077 /* JumpBackInDataAdaptorTests.swift */; }; 8ABC5AEE284532C900FEA552 /* PocketDiscoverCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8ABC5AED284532C900FEA552 /* PocketDiscoverCell.swift */; }; @@ -6619,6 +6622,9 @@ 8AB8574527D97CB00075C173 /* HomepageContextMenuProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomepageContextMenuProtocol.swift; sourceTree = ""; }; 8AB8574727D97CD40075C173 /* HomePanelType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomePanelType.swift; sourceTree = ""; }; 8AB8574927D97CE90075C173 /* HomePanelDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomePanelDelegate.swift; sourceTree = ""; }; + 8AB893A22C73AF5200DAEED7 /* MockCreditCardProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockCreditCardProvider.swift; sourceTree = ""; }; + 8AB893A52C73AFBA00DAEED7 /* MockLoginProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockLoginProvider.swift; sourceTree = ""; }; + 8AB893A82C73CBBD00DAEED7 /* CreditCardProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreditCardProvider.swift; sourceTree = ""; }; 8ABA9C8A28931207002C0077 /* JumpBackInDataAdaptorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JumpBackInDataAdaptorTests.swift; sourceTree = ""; }; 8ABA9C8C28931223002C0077 /* MockDispatchQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockDispatchQueue.swift; sourceTree = ""; }; 8ABC5AED284532C900FEA552 /* PocketDiscoverCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PocketDiscoverCell.swift; sourceTree = ""; }; @@ -10544,6 +10550,15 @@ path = LogoHeader; sourceTree = ""; }; + 8AB893A12C73AF4500DAEED7 /* Mocks */ = { + isa = PBXGroup; + children = ( + 8AB893A22C73AF5200DAEED7 /* MockCreditCardProvider.swift */, + 8AB893A52C73AFBA00DAEED7 /* MockLoginProvider.swift */, + ); + path = Mocks; + sourceTree = ""; + }; 8ABCBE622C485CAA00480A21 /* FeatureFlags */ = { isa = PBXGroup; children = ( @@ -11002,6 +11017,7 @@ AB42CC722A1F523F003C9594 /* CreditCardBottomSheetViewController.swift */, AB42CC732A1F5240003C9594 /* CreditCardBottomSheetHeaderView.swift */, ABEF80D42A254185003F52C4 /* CreditCardBottomSheetFooterView.swift */, + 8AB893A82C73CBBD00DAEED7 /* CreditCardProvider.swift */, ); path = CreditCardBottomSheet; sourceTree = ""; @@ -11009,6 +11025,7 @@ B23620492B7EAF2C000B1DE7 /* Autofill */ = { isa = PBXGroup; children = ( + 8AB893A12C73AF4500DAEED7 /* Mocks */, 439B78172A09721600CAAE37 /* FormAutofillHelperTests.swift */, 8CCD74722B90A945008F919B /* LoginListViewModelTests.swift */, 8CEDF07D2BFE04B100D2617B /* AddressListViewModelTests.swift */, @@ -11396,6 +11413,7 @@ 8AF10D9029D776190086351D /* MockLaunchScreenManager.swift */, 965C3C95293431FC006499ED /* MockLaunchSessionProvider.swift */, 8AF99B5329EF2AF100108DEC /* MockLogger.swift */, + 8A880C432C63CFE200B77F23 /* MockLoginViewModelDelegate.swift */, 8A93F86629D373AC004159D9 /* MockNavigationController.swift */, 5AB4237B28A1947A003BC40C /* MockNotificationCenter.swift */, E18259E229B2A51B00E6BE76 /* MockNotificationManager.swift */, @@ -11420,7 +11438,6 @@ BA1C68BB2B7ED153000D9397 /* MockWebKit.swift */, 1D558A562BED7ECB001EF527 /* MockWindowManager.swift */, 0AC659282BF493CE005C614A /* MockFxAWebViewModel.swift */, - 8A880C432C63CFE200B77F23 /* MockLoginViewModelDelegate.swift */, ); path = Mocks; sourceTree = ""; @@ -15128,6 +15145,7 @@ E13C072B2C2184C80087E404 /* AddressBarState.swift in Sources */, 4347B39A298DA5BB0045F677 /* CreditCardInputViewModel.swift in Sources */, 6025B10D267B6C5400F59F6B /* LoginRecordExtension.swift in Sources */, + 8AB893A62C73AFBA00DAEED7 /* MockLoginProvider.swift in Sources */, 2F44FCC51A9E85E900FD20CC /* SettingsTableViewController.swift in Sources */, 211046C92A7ADE9000A7309F /* BlockPopupSetting.swift in Sources */, 8A3233FC286270CF003E1C33 /* FxBookmarkNode.swift in Sources */, @@ -15207,6 +15225,7 @@ AB03032C2AB47AF300DCD8EF /* FakespotOptInCardViewModel.swift in Sources */, 1D2F68AB2ACB262900524B92 /* RemoteTabsPanelAction.swift in Sources */, 8A5D1CB92A30DBDB005AD35C /* ChinaSyncServiceSetting.swift in Sources */, + 8AB893A92C73CBBD00DAEED7 /* CreditCardProvider.swift in Sources */, 1D8487B42AD0C6C100F7527C /* RemoteTabsPanelMiddleware.swift in Sources */, 5AA1D8272BC09ECB00957516 /* TabTrayAnimationQueue.swift in Sources */, C849E46526B9C3DD00260F0B /* SlideoverPresentationController.swift in Sources */, @@ -15334,6 +15353,7 @@ D3C744CD1A687D6C004CE85D /* URIFixup.swift in Sources */, 43D16B8029831DC5009F8279 /* CreditCardInputView.swift in Sources */, 21112968289480630082C08B /* HomepageMessageCardViewModel.swift in Sources */, + 8AB893A32C73AF5200DAEED7 /* MockCreditCardProvider.swift in Sources */, E1CD81BE290C5C7500124B27 /* DevicePickerTableViewHeaderCell.swift in Sources */, B2FEA68B2B460D1D0058E616 /* AddressAutofillSettingsView.swift in Sources */, E12BD0AC28AC37F00029AAF0 /* UIColor+Extension.swift in Sources */, @@ -15696,7 +15716,6 @@ 8A95FF672B1E97A800AC303D /* TelemetryContextualIdentifierTests.swift in Sources */, 965C3C9829343445006499ED /* MockAppSessionManager.swift in Sources */, 8AFCE50929DE136300B1B253 /* MockLaunchFinishedLoadingDelegate.swift in Sources */, - 8A880C442C63CFE200B77F23 /* MockLoginViewModelDelegate.swift in Sources */, 8AE1E1DB27B1C1320024C45E /* SearchBarSettingsViewModelTests.swift in Sources */, CA24B53924ABFE250093848C /* PasswordManagerSelectionHelperTests.swift in Sources */, C8610DA82A0EBD4100B79FF1 /* OnboardingButtonActionTests.swift in Sources */, @@ -15714,6 +15733,7 @@ D525DFB325FBE5E000B18763 /* TabTests.swift in Sources */, C8E78BDD27F4A1E700C48BAA /* HistoryDeletionUtilityTests.swift in Sources */, 0AC659272BF35854005C614A /* FxAWebViewModelTests.swift in Sources */, + 8AB893A72C73AFCC00DAEED7 /* MockLoginViewModelDelegate.swift in Sources */, 8A11C8132731E54800AC7318 /* DictionaryExtensionsTests.swift in Sources */, 5A475E8F29DB89CE009C13FD /* MockTabDataStore.swift in Sources */, 8A7A93EE2810ADF2005E7E1B /* ContileProviderTests.swift in Sources */, diff --git a/firefox-ios/Client/Coordinators/CredentialAutofillCoordinator.swift b/firefox-ios/Client/Coordinators/CredentialAutofillCoordinator.swift index 4c9f72413c19..51ebbeb57a21 100644 --- a/firefox-ios/Client/Coordinators/CredentialAutofillCoordinator.swift +++ b/firefox-ios/Client/Coordinators/CredentialAutofillCoordinator.swift @@ -48,7 +48,7 @@ class CredentialAutofillCoordinator: BaseCoordinator { viewType state: CreditCardBottomSheetState, frame: WKFrameInfo?, alertContainer: UIView) { - let creditCardControllerViewModel = CreditCardBottomSheetViewModel(profile: profile, + let creditCardControllerViewModel = CreditCardBottomSheetViewModel(creditCardProvider: profile.autofill, creditCard: creditCard, decryptedCreditCard: decryptedCard, state: state) diff --git a/firefox-ios/Client/Frontend/Autofill/CreditCard/CreditCardBottomSheet/CreditCardBottomSheetViewModel.swift b/firefox-ios/Client/Frontend/Autofill/CreditCard/CreditCardBottomSheet/CreditCardBottomSheetViewModel.swift index aa5a56c616ed..f36fe7cdc93e 100644 --- a/firefox-ios/Client/Frontend/Autofill/CreditCard/CreditCardBottomSheet/CreditCardBottomSheetViewModel.swift +++ b/firefox-ios/Client/Frontend/Autofill/CreditCard/CreditCardBottomSheet/CreditCardBottomSheetViewModel.swift @@ -62,8 +62,7 @@ enum CreditCardBottomSheetState: String, Equatable, CaseIterable { class CreditCardBottomSheetViewModel { private var logger: Logger - let profile: Profile - let autofill: RustAutofill + let autofill: CreditCardProvider var creditCard: CreditCard? { didSet { didUpdateCreditCard?() @@ -81,13 +80,12 @@ class CreditCardBottomSheetViewModel { var storedCreditCards = [CreditCard]() var state: CreditCardBottomSheetState - init(profile: Profile, + init(creditCardProvider: CreditCardProvider, creditCard: CreditCard?, decryptedCreditCard: UnencryptedCreditCardFields?, logger: Logger = DefaultLogger.shared, state: CreditCardBottomSheetState) { - self.profile = profile - self.autofill = profile.autofill + self.autofill = creditCardProvider self.state = state self.logger = logger creditCards = [CreditCard]() diff --git a/firefox-ios/Client/Frontend/Autofill/CreditCard/CreditCardBottomSheet/CreditCardProvider.swift b/firefox-ios/Client/Frontend/Autofill/CreditCard/CreditCardBottomSheet/CreditCardProvider.swift new file mode 100644 index 000000000000..047e18b84d66 --- /dev/null +++ b/firefox-ios/Client/Frontend/Autofill/CreditCard/CreditCardBottomSheet/CreditCardProvider.swift @@ -0,0 +1,23 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/ + +import Foundation +import Storage +import struct MozillaAppServices.CreditCard + +protocol CreditCardProvider { + func addCreditCard( + creditCard: UnencryptedCreditCardFields, + completion: @escaping (CreditCard?, Error?) -> Void + ) + func decryptCreditCardNumber(encryptedCCNum: String?) -> String? + func listCreditCards(completion: @escaping ([CreditCard]?, Error?) -> Void) + func updateCreditCard( + id: String, + creditCard: UnencryptedCreditCardFields, + completion: @escaping (Bool?, Error?) -> Void + ) +} + +extension RustAutofill: CreditCardProvider {} diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Autofill/Mocks/MockCreditCardProvider.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Autofill/Mocks/MockCreditCardProvider.swift new file mode 100644 index 000000000000..f958d6e03d89 --- /dev/null +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Autofill/Mocks/MockCreditCardProvider.swift @@ -0,0 +1,48 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/ + +import Foundation +import MozillaAppServices +import Storage + +class MockCreditCardProvider: CreditCardProvider { + var addCreditCardCalledCount = 0 + var updateCreditCardCalledCount = 0 + var listCreditCardsCalledCount = 0 + + private var exampleCreditCard = CreditCard( + guid: "1", + ccName: "Allen Burges", + ccNumberEnc: "4111111111111111", + ccNumberLast4: "1111", + ccExpMonth: 3, + ccExpYear: 2043, + ccType: "VISA", + timeCreated: 1234678, + timeLastUsed: nil, + timeLastModified: 123123, + timesUsed: 123123 + ) + + func addCreditCard( + creditCard: UnencryptedCreditCardFields, + completion: @escaping (CreditCard?, Error?) -> Void + ) { + addCreditCardCalledCount += 1 + completion(exampleCreditCard, nil) + } + func decryptCreditCardNumber(encryptedCCNum: String?) -> String? { return "testCCNum" } + func listCreditCards(completion: @escaping ([CreditCard]?, Error?) -> Void) { + listCreditCardsCalledCount += 1 + completion([exampleCreditCard], nil) + } + func updateCreditCard( + id: String, + creditCard: UnencryptedCreditCardFields, + completion: @escaping (Bool?, Error?) -> Void + ) { + updateCreditCardCalledCount += 1 + completion(nil, nil) + } +} diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Autofill/Mocks/MockLoginProvider.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Autofill/Mocks/MockLoginProvider.swift new file mode 100644 index 000000000000..f18c00a99b5f --- /dev/null +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Autofill/Mocks/MockLoginProvider.swift @@ -0,0 +1,36 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/ + +import Foundation +import MozillaAppServices + +class MockLoginProvider: LoginProvider { + var searchLoginsWithQueryCalledCount = 0 + var addLoginCalledCount = 0 + func searchLoginsWithQuery( + _ query: String?, + completionHandler: @escaping ( + Result< + [MozillaAppServices.EncryptedLogin], + any Error + > + ) -> Void + ) { + searchLoginsWithQueryCalledCount += 1 + completionHandler(.success([])) + } + + func addLogin( + login: MozillaAppServices.LoginEntry, + completionHandler: @escaping ( + Result< + MozillaAppServices.EncryptedLogin?, + any Error + > + ) -> Void + ) { + addLoginCalledCount += 1 + completionHandler(.success(nil)) + } +} diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/CreditCard/CreditCardBottomSheetViewModelTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/CreditCard/CreditCardBottomSheetViewModelTests.swift index da6626bfff7c..01cb5c8afbf8 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/CreditCard/CreditCardBottomSheetViewModelTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/CreditCard/CreditCardBottomSheetViewModelTests.swift @@ -13,9 +13,7 @@ import XCTest class CreditCardBottomSheetViewModelTests: XCTestCase { private var profile: MockProfile! private var viewModel: CreditCardBottomSheetViewModel! - private var files: FileAccessor! - private var autofill: RustAutofill! - private var encryptionKey: String! + private var mockAutofill: MockCreditCardProvider! private var samplePlainTextCard = UnencryptedCreditCardFields(ccName: "Allen Burges", ccNumber: "4111111111111111", ccNumberLast4: "1111", @@ -41,105 +39,49 @@ class CreditCardBottomSheetViewModelTests: XCTestCase { timeLastModified: 123123, timesUsed: 123123) - private var invalidSampleCreditCard = CreditCard(guid: "1", - ccName: "Allen Burges", - ccNumberEnc: "", - ccNumberLast4: "", - ccExpMonth: 1, - ccExpYear: 0, - ccType: "", - timeCreated: 0, - timeLastUsed: nil, - timeLastModified: 2, - timesUsed: 0) - override func setUp() { super.setUp() - files = MockFiles() - - if let rootDirectory = try? files.getAndEnsureDirectory() { - let databasePath = URL(fileURLWithPath: rootDirectory, isDirectory: true) - .appendingPathComponent("testAutofill.db").path - try? files.remove("testAutofill.db") - - if let key = try? createAutofillKey() { - encryptionKey = key - } else { - XCTFail("Encryption key wasn't created") - } - - autofill = RustAutofill(databasePath: databasePath) - _ = autofill.reopenIfClosed() - } else { - XCTFail("Could not retrieve root directory") - } - - profile = MockProfile() - _ = profile.autofill.reopenIfClosed() - - viewModel = CreditCardBottomSheetViewModel(profile: profile, - creditCard: nil, - decryptedCreditCard: samplePlainTextCard, - state: .save) + mockAutofill = MockCreditCardProvider() + viewModel = CreditCardBottomSheetViewModel( + creditCardProvider: mockAutofill, + creditCard: nil, + decryptedCreditCard: samplePlainTextCard, + state: .save + ) } override func tearDown() { - super.tearDown() - profile.shutdown() - profile = nil - autofill = nil - files = nil + mockAutofill = nil viewModel = nil + super.tearDown() } // MARK: - Test Cases - func testSavingCard() { - viewModel.creditCard = sampleCreditCard + func test_saveCreditCard_callsAddCreditCard() { let expectation = expectation(description: "wait for credit card fields to be saved") let decryptedCreditCard = viewModel.getPlainCreditCardValues(bottomSheetState: .save) // Make sure the year saved is a 4 digit year and not 2 digit // 2000 because that is our current period XCTAssertTrue(decryptedCreditCard!.ccExpYear > 2000) viewModel.saveCreditCard(with: decryptedCreditCard) { creditCard, error in - guard error == nil, let creditCard = creditCard else { - XCTFail() - return - } - XCTAssertEqual(creditCard.ccName, self.viewModel.creditCard?.ccName) - // Note: the number for credit card is encrypted so that part - // will get added later and for now we will check the name only + XCTAssertEqual(self.mockAutofill.addCreditCardCalledCount, 1) expectation.fulfill() } waitForExpectations(timeout: 1.0) } - func testUpdatingCard() { + func test_saveAndUpdateCreditCard_callsProperAutofillMethods() { viewModel.state = .save - viewModel.decryptedCreditCard = samplePlainTextCard let expectationSave = expectation(description: "wait for credit card fields to be saved") let expectationUpdate = expectation(description: "wait for credit card fields to be updated") viewModel.saveCreditCard(with: samplePlainTextCard) { creditCard, error in - guard error == nil, let creditCard = creditCard else { - XCTFail() - return - } + XCTAssertEqual(self.mockAutofill.addCreditCardCalledCount, 1) expectationSave.fulfill() - XCTAssertEqual(creditCard.ccName, self.viewModel.decryptedCreditCard?.ccName) - // Note: the number for credit card is encrypted so that part - // will get added later and for now we will check the name only - - self.samplePlainTextCard.ccExpYear = 2045 - self.samplePlainTextCard.ccName = "Test" self.viewModel.state = .update - - self.viewModel.updateCreditCard(for: creditCard.guid, + self.viewModel.updateCreditCard(for: creditCard?.guid, with: self.samplePlainTextCard) { didUpdate, error in - XCTAssertNotNil(didUpdate) - if let updated = didUpdate { - XCTAssert(updated) - } - XCTAssertNil(error) + XCTAssertEqual(self.mockAutofill.updateCreditCardCalledCount, 1) expectationUpdate.fulfill() } } @@ -338,54 +280,58 @@ class CreditCardBottomSheetViewModelTests: XCTestCase { XCTAssertEqual(value!.ccNumber, sampleCreditCardVal.ccNumberEnc) } - func test_didTapMainButton() { + func test_didTapMainButton_withSaveState_callsAddCreditCard() { viewModel.state = .save viewModel.decryptedCreditCard = samplePlainTextCard let expectation = expectation(description: "wait for credit card fields to be saved") - viewModel.didTapMainButton { error in - XCTAssertNil(error) + viewModel.didTapMainButton { _ in + XCTAssertEqual(self.mockAutofill.addCreditCardCalledCount, 1) expectation.fulfill() } waitForExpectations(timeout: 1.0) } - func test_invalidCreditCardUpdateDidTapMainButton() { + func test_didTapMainButton_withUpdateState_callsAddCreditCard() { viewModel.state = .update - viewModel.creditCard = invalidSampleCreditCard viewModel.decryptedCreditCard = samplePlainTextCard let expectation = expectation(description: "wait for credit card fields to be updated") - viewModel.didTapMainButton { error in - XCTAssertNotNil(error) + viewModel.didTapMainButton { _ in + XCTAssertEqual(self.mockAutofill.updateCreditCardCalledCount, 1) expectation.fulfill() } waitForExpectations(timeout: 1.0) } - func test_updateCreditCardList() { + func test_updateCreditCardList_callsListCreditCards() { let expectation = expectation(description: "wait for credit card to be added") viewModel.creditCard = nil viewModel.decryptedCreditCard = nil - // Add a sample card to the storage - viewModel.saveCreditCard(with: samplePlainTextCard) { creditCard, error in - guard error == nil, creditCard != nil else { - XCTFail() - return - } - // Make the view model state selected card - self.viewModel.state = .selectSavedCard - // Perform update - self.viewModel.updateCreditCardList({ cards in - // Check if the view model updated the list - let cards = self.viewModel.creditCards - XCTAssertNotNil(cards) - XCTAssert(!cards!.isEmpty) - expectation.fulfill() - }) - } - waitForExpectations(timeout: 3.0) + viewModel.state = .selectSavedCard + + viewModel.updateCreditCardList({ cards in + XCTAssertEqual(self.viewModel.creditCards, cards) + XCTAssertEqual(cards?.count, 1) + XCTAssertEqual(cards?.first?.guid, "1") + XCTAssertEqual(cards?.first?.ccName, "Allen Burges") + XCTAssertEqual(self.mockAutofill.listCreditCardsCalledCount, 1) + expectation.fulfill() + }) + waitForExpectations(timeout: 1.0) + } + + func test_updateCreditCardList_withoutSelectedSavedCardState_doesNotCallListCreditCards() { + let expectation = expectation(description: "wait for credit card to be added") + expectation.isInverted = true + viewModel.creditCard = nil + viewModel.decryptedCreditCard = nil + + viewModel.updateCreditCardList({ cards in + expectation.fulfill() + }) + waitForExpectations(timeout: 1.0) } } diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockLoginViewModelDelegate.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockLoginViewModelDelegate.swift index c4725834ea15..733e38d66c2f 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockLoginViewModelDelegate.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockLoginViewModelDelegate.swift @@ -3,7 +3,6 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/ import Foundation -import MozillaAppServices @testable import Client class MockLoginViewModelDelegate: LoginViewModelDelegate { @@ -17,33 +16,3 @@ class MockLoginViewModelDelegate: LoginViewModelDelegate { breachPathDidUpdateCalledCount += 1 } } - -class MockLoginProvider: LoginProvider { - var searchLoginsWithQueryCalledCount = 0 - var addLoginCalledCount = 0 - func searchLoginsWithQuery( - _ query: String?, - completionHandler: @escaping ( - Result< - [MozillaAppServices.EncryptedLogin], - any Error - > - ) -> Void - ) { - searchLoginsWithQueryCalledCount += 1 - completionHandler(.success([])) - } - - func addLogin( - login: MozillaAppServices.LoginEntry, - completionHandler: @escaping ( - Result< - MozillaAppServices.EncryptedLogin?, - any Error - > - ) -> Void - ) { - addLoginCalledCount += 1 - completionHandler(.success(nil)) - } -} From 97c464112d90383232f6e987d9844dea1f832898 Mon Sep 17 00:00:00 2001 From: dicarobinho <61138287+dicarobinho@users.noreply.github.com> Date: Tue, 20 Aug 2024 16:26:09 +0300 Subject: [PATCH 093/128] =?UTF-8?q?Add=20FXIOS-9196=20=E2=81=83=20Enhanced?= =?UTF-8?q?=20Tracking=20Protection=20design=20when=20the=20connection=20i?= =?UTF-8?q?s=20not=20secure=20(#21561)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- firefox-ios/Client/Frontend/Strings.swift | 2 +- .../TrackingProtectionModel.swift | 48 +++++++++++++------ .../TrackingProtectionViewController.swift | 8 ++-- 3 files changed, 37 insertions(+), 21 deletions(-) diff --git a/firefox-ios/Client/Frontend/Strings.swift b/firefox-ios/Client/Frontend/Strings.swift index 5066f84c5614..10e967df9a2c 100644 --- a/firefox-ios/Client/Frontend/Strings.swift +++ b/firefox-ios/Client/Frontend/Strings.swift @@ -4114,7 +4114,7 @@ extension String { comment: "Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure.") public static let onNotSecureHeader = MZLocalizedString( - key: "Menu.EnhancedTrackingProtection.On.Header.v128", + key: "Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128", tableName: "EnhancedTrackingProtection", value: "Your connection is not secure.", comment: "Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure.") diff --git a/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionModel.swift b/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionModel.swift index cf9b9d45197a..ba6275e63637 100644 --- a/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionModel.swift +++ b/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionModel.swift @@ -53,32 +53,41 @@ class TrackingProtectionModel { return url.baseDomain ?? "" } - private var isSecuredAndProtected: Bool { - return connectionSecure && isProtectionEnabled - } - let secureStatusString = String.Menu.EnhancedTrackingProtection.connectionSecureLabel let unsecureStatusString = String.Menu.EnhancedTrackingProtection.connectionUnsecureLabel var connectionStatusString: String { return connectionSecure ? secureStatusString : unsecureStatusString } - var connectionDetailsTitle: String { - let titleOn = String(format: String.Menu.EnhancedTrackingProtection.onTitle, AppName.shortName.rawValue) - return isSecuredAndProtected ? titleOn : .Menu.EnhancedTrackingProtection.offTitle + var connectionDetailsTitle: String { + if !isProtectionEnabled { + return .Menu.EnhancedTrackingProtection.offTitle + } + if !connectionSecure { + return .Menu.EnhancedTrackingProtection.onNotSecureTitle + } + return String(format: String.Menu.EnhancedTrackingProtection.onTitle, AppName.shortName.rawValue) } - let protectionOnHeaderString = String.Menu.EnhancedTrackingProtection.onHeader - let protectionOffHeaderString = String(format: .Menu.EnhancedTrackingProtection.offHeader, AppName.shortName.rawValue) - var connectionDetailsHeader: String { - return isSecuredAndProtected ? protectionOnHeaderString : protectionOffHeaderString + var connectionDetailsHeader: String { + if !isProtectionEnabled { + return String(format: .Menu.EnhancedTrackingProtection.offHeader, AppName.shortName.rawValue) + } + if !connectionSecure { + return .Menu.EnhancedTrackingProtection.onNotSecureHeader + } + return .Menu.EnhancedTrackingProtection.onHeader } - let protectionOnImage = UIImage(named: ImageIdentifiers.TrackingProtection.protectionOn) - let protectionOffImage = UIImage(named: ImageIdentifiers.TrackingProtection.protectionOff) var isProtectionEnabled = false - var connectionDetailsImage: UIImage? { - return isSecuredAndProtected ? protectionOnImage : protectionOffImage + var connectionDetailsImage: UIImage? { + if !isProtectionEnabled { + return UIImage(named: ImageIdentifiers.TrackingProtection.protectionOff) + } + if !connectionSecure { + return UIImage(named: ImageIdentifiers.TrackingProtection.protectionAlert) + } + return UIImage(named: ImageIdentifiers.TrackingProtection.protectionOn) } var isSiteETPEnabled: Bool { @@ -105,6 +114,15 @@ class TrackingProtectionModel { } // MARK: - Helpers + func getConnectionDetailsBackgroundColor(theme: Theme) -> UIColor { + if !isProtectionEnabled { + return theme.colors.layerAccentPrivateNonOpaque + } + if !connectionSecure { + return theme.colors.layerRatingFSubdued + } + return theme.colors.layer3 + } func getConnectionStatusImage(themeType: ThemeType) -> UIImage { if connectionSecure { diff --git a/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionViewController.swift b/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionViewController.swift index 4ac83d036002..8b1b32b0be0c 100644 --- a/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionViewController.swift +++ b/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionViewController.swift @@ -898,23 +898,21 @@ class TrackingProtectionViewController: UIViewController, Themeable, Notifiable, // MARK: - Update Views private func updateProtectionViewStatus() { if toggleSwitch.isOn { - // TODO: FXIOS-9195 #20363 Enhanced Tracking Protection screen status enabled design toggleStatusLabel.text = .Menu.EnhancedTrackingProtection.switchOnText trackersView.isHidden = false trackersLabelTopConstraint?.constant = TPMenuUX.UX.trackersLabelConstraintConstant trackersLabelBottomConstraint?.constant = -TPMenuUX.UX.trackersLabelConstraintConstant viewModel.isProtectionEnabled = true - foxStatusImage.image = viewModel.protectionOnImage - connectionDetailsContentView.backgroundColor = currentTheme().colors.layerAccentPrivateNonOpaque } else { toggleStatusLabel.text = .Menu.EnhancedTrackingProtection.switchOffText trackersView.isHidden = true trackersLabelTopConstraint?.constant = 0 trackersLabelBottomConstraint?.constant = 0 viewModel.isProtectionEnabled = false - foxStatusImage.image = viewModel.protectionOffImage - connectionDetailsContentView.backgroundColor = currentTheme().colors.layer3 } + + connectionDetailsContentView.backgroundColor = viewModel.getConnectionDetailsBackgroundColor(theme: currentTheme()) + foxStatusImage.image = viewModel.connectionDetailsImage connectionDetailsTitleLabel.text = viewModel.connectionDetailsTitle connectionDetailsStatusLabel.text = viewModel.connectionDetailsHeader } From 550f508029ddba6818253b383261b6e1b588591d Mon Sep 17 00:00:00 2001 From: Tushar Chitnavis <64319078+tusharC95@users.noreply.github.com> Date: Tue, 20 Aug 2024 10:11:33 -0400 Subject: [PATCH 094/128] Add FXIOS-9716 [Native Error Page] Strings for No internet Connection and Generic Error (#21559) * Add FXIOS-9716 [Native Error Page] Strings for No internet Connection --- firefox-ios/Client/Frontend/Strings.swift | 35 +++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/firefox-ios/Client/Frontend/Strings.swift b/firefox-ios/Client/Frontend/Strings.swift index 10e967df9a2c..c2514e874800 100644 --- a/firefox-ios/Client/Frontend/Strings.swift +++ b/firefox-ios/Client/Frontend/Strings.swift @@ -1471,6 +1471,41 @@ extension String { } } +// MARK: - Native Error Page +extension String { + struct NativeErrorPage { + public static let ButtonLabel = MZLocalizedString( + key: "NativeErrorPage.ButtonLabel.v131", + tableName: "NativeErrorPage", + value: "Reload", + comment: "On error page, this is the text on a button that will try to load the page again.") + struct NoInternetConnection { + public static let TitleLabel = MZLocalizedString( + key: "NativeErrorPage.NoInternetConnection.TitleLabel.v131", + tableName: "NativeErrorPage", + value: "Looks like there’s a problem with your internet connection.", + comment: "On error page, this is the title for no internet connection") + public static let Description = MZLocalizedString( + key: "NativeErrorPage.NoInternetConnection.Description.v131", + tableName: "NativeErrorPage", + value: "Try connecting on a different device. Check your modem or router. Disconnect and reconnect to Wi-Fi.", + comment: "On error page, this is the description for no internet connection.") + } + struct GenericError { + public static let TitleLabel = MZLocalizedString( + key: "NativeErrorPage.GenericError.TitleLabel.v131", + tableName: "NativeErrorPage", + value: "Be careful. Something doesn’t look right.", + comment: "On error page, this is the title for generic error.") + public static let Description = MZLocalizedString( + key: "NativeErrorPage.GenericError.Description.v131", + tableName: "NativeErrorPage", + value: "An SSL error has occurred and a secure connection to the server cannot be made.", + comment: "On error page, this is the description for generic error.") + } + } +} + // MARK: - Onboarding screens extension String { public struct Onboarding { From 107055c59b98479efae0a51944a39b314ff70649 Mon Sep 17 00:00:00 2001 From: PARAIPAN SORIN <51127880+PARAIPAN9@users.noreply.github.com> Date: Wed, 21 Aug 2024 14:43:44 +0300 Subject: [PATCH 095/128] Add FXIOS-9709 - Add a11y custom action to reader mode button (#21541) * Add custom a11y action for reader mode * Rename a11y custom action name * Fix spelling --------- Co-authored-by: Winnie Teichmann <4530+thatswinnie@users.noreply.github.com> --- .../Sources/ToolbarKit/ToolbarButton.swift | 11 ++++++ .../Sources/ToolbarKit/ToolbarElement.swift | 10 +++++ .../Actions/GeneralBrowserAction.swift | 1 + ...BrowserViewController+URLBarDelegate.swift | 33 +--------------- .../State/BrowserViewControllerState.swift | 11 ++++++ .../Views/BrowserViewController.swift | 39 +++++++++++++++++++ .../Models/AddressToolbarContainerModel.swift | 7 ++++ .../NavigationToolbarContainerModel.swift | 7 ++++ .../Toolbars/Redux/ToolbarAction.swift | 1 + .../Toolbars/Redux/ToolbarActionState.swift | 2 + .../Toolbars/Redux/ToolbarMiddleware.swift | 24 ++++++++++-- 11 files changed, 111 insertions(+), 35 deletions(-) diff --git a/BrowserKit/Sources/ToolbarKit/ToolbarButton.swift b/BrowserKit/Sources/ToolbarKit/ToolbarButton.swift index 20fb087488a1..a7be39e1fb25 100644 --- a/BrowserKit/Sources/ToolbarKit/ToolbarButton.swift +++ b/BrowserKit/Sources/ToolbarKit/ToolbarButton.swift @@ -42,6 +42,7 @@ class ToolbarButton: UIButton, ThemeApplicable { guard var config = configuration else { return } removeAllGestureRecognizers() configureLongPressGestureRecognizerIfNeeded(for: element) + configureCustomA11yActionIfNeeded(for: element) shouldDisplayAsHighlighted = element.shouldDisplayAsHighlighted let image = imageConfiguredForRTL(for: element) @@ -132,6 +133,16 @@ class ToolbarButton: UIButton, ThemeApplicable { addGestureRecognizer(longPressRecognizer) } + private func configureCustomA11yActionIfNeeded(for element: ToolbarElement) { + guard let a11yCustomActionName = element.a11yCustomActionName, + let a11yCustomAction = element.a11yCustomAction else { return } + let a11yAction = UIAccessibilityCustomAction(name: a11yCustomActionName) { _ in + a11yCustomAction() + return true + } + accessibilityCustomActions = [a11yAction] + } + private func imageConfiguredForRTL(for element: ToolbarElement) -> UIImage? { let image = UIImage(named: element.iconName)?.withRenderingMode(.alwaysTemplate) return element.isFlippedForRTL ? image?.imageFlippedForRightToLeftLayoutDirection() : image diff --git a/BrowserKit/Sources/ToolbarKit/ToolbarElement.swift b/BrowserKit/Sources/ToolbarKit/ToolbarElement.swift index f83e8f71494f..bf1eaf625bcf 100644 --- a/BrowserKit/Sources/ToolbarKit/ToolbarElement.swift +++ b/BrowserKit/Sources/ToolbarKit/ToolbarElement.swift @@ -35,6 +35,12 @@ public struct ToolbarElement: Equatable { /// Accessibility identifier of the toolbar element let a11yId: String + /// Name for the custom accessibility action + let a11yCustomActionName: String? + + /// Action to be performed for custom accessibility action + let a11yCustomAction: (() -> Void)? + /// Closure that is executed when the toolbar element is tapped let onSelected: ((UIButton) -> Void)? @@ -53,6 +59,8 @@ public struct ToolbarElement: Equatable { a11yLabel: String, a11yHint: String?, a11yId: String, + a11yCustomActionName: String? = nil, + a11yCustomAction: (() -> Void)? = nil, onSelected: ((UIButton) -> Void)?, onLongPress: ((UIButton) -> Void)? = nil) { self.iconName = iconName @@ -67,6 +75,8 @@ public struct ToolbarElement: Equatable { self.a11yLabel = a11yLabel self.a11yHint = a11yHint self.a11yId = a11yId + self.a11yCustomActionName = a11yCustomActionName + self.a11yCustomAction = a11yCustomAction } public static func == (lhs: ToolbarElement, rhs: ToolbarElement) -> Bool { diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Actions/GeneralBrowserAction.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Actions/GeneralBrowserAction.swift index 2ef9df2d0af3..42dc14173afd 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Actions/GeneralBrowserAction.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Actions/GeneralBrowserAction.swift @@ -51,6 +51,7 @@ enum GeneralBrowserActionType: ActionType { case showReaderMode case addNewTab case showNewTabLongPressActions + case addToReadingListLongPressAction case clearData } diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+URLBarDelegate.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+URLBarDelegate.swift index b4c66477462b..ca06c568a6b4 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+URLBarDelegate.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+URLBarDelegate.swift @@ -185,38 +185,7 @@ extension BrowserViewController: URLBarDelegate { } func urlBarDidLongPressReaderMode(_ urlBar: URLBarView) -> Bool { - guard let tab = tabManager.selectedTab, - let url = tab.url?.displayURL - else { - UIAccessibility.post( - notification: UIAccessibility.Notification.announcement, - argument: String.ReaderModeAddPageGeneralErrorAccessibilityLabel - ) - return false - } - - let result = profile.readingList.createRecordWithURL( - url.absoluteString, - title: tab.title ?? "", - addedBy: UIDevice.current.name - ) - - switch result.value { - case .success: - UIAccessibility.post( - notification: UIAccessibility.Notification.announcement, - argument: String.ReaderModeAddPageSuccessAcessibilityLabel - ) - SimpleToast().showAlertWithText(.ShareAddToReadingListDone, - bottomContainer: contentContainer, - theme: currentTheme()) - case .failure: - UIAccessibility.post( - notification: UIAccessibility.Notification.announcement, - argument: String.ReaderModeAddPageMaybeExistsErrorAccessibilityLabel - ) - } - return true + toggleReaderModeLongPressAction() } func urlBarDidLongPressReload(_ urlBar: URLBarView, from button: UIButton) { diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/State/BrowserViewControllerState.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/State/BrowserViewControllerState.swift index 8d306ad6c254..e850a2ff00b8 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/State/BrowserViewControllerState.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/State/BrowserViewControllerState.swift @@ -29,6 +29,7 @@ struct BrowserViewControllerState: ScreenState, Equatable { case share case readerMode case newTabLongPressActions + case readerModeLongPressAction case dataClearance } @@ -386,6 +387,16 @@ struct BrowserViewControllerState: ScreenState, Equatable { browserViewType: state.browserViewType, displayView: .newTabLongPressActions, microsurveyState: MicrosurveyPromptState.reducer(state.microsurveyState, action)) + case GeneralBrowserActionType.addToReadingListLongPressAction: + return BrowserViewControllerState( + searchScreenState: state.searchScreenState, + showDataClearanceFlow: state.showDataClearanceFlow, + fakespotState: state.fakespotState, + toast: state.toast, + windowUUID: state.windowUUID, + browserViewType: state.browserViewType, + displayView: .readerModeLongPressAction, + microsurveyState: MicrosurveyPromptState.reducer(state.microsurveyState, action)) case GeneralBrowserActionType.clearData: return BrowserViewControllerState( searchScreenState: state.searchScreenState, diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift index ec35492c5e2e..4704db60961b 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift @@ -1960,6 +1960,8 @@ class BrowserViewController: UIViewController, didTapOnShare(from: button) case .readerMode: toggleReaderMode() + case .readerModeLongPressAction: + _ = toggleReaderModeLongPressAction() case .newTabLongPressActions: presentNewTabLongPressActionSheet(from: view) case .dataClearance: @@ -2096,6 +2098,43 @@ class BrowserViewController: UIViewController, } } + func toggleReaderModeLongPressAction() -> Bool { + guard let tab = tabManager.selectedTab, + let url = tab.url?.displayURL + else { + UIAccessibility.post( + notification: UIAccessibility.Notification.announcement, + argument: String.ReaderModeAddPageGeneralErrorAccessibilityLabel + ) + + return false + } + + let result = profile.readingList.createRecordWithURL( + url.absoluteString, + title: tab.title ?? "", + addedBy: UIDevice.current.name + ) + + switch result.value { + case .success: + UIAccessibility.post( + notification: UIAccessibility.Notification.announcement, + argument: String.ReaderModeAddPageSuccessAcessibilityLabel + ) + SimpleToast().showAlertWithText(.ShareAddToReadingListDone, + bottomContainer: contentContainer, + theme: currentTheme()) + case .failure: + UIAccessibility.post( + notification: UIAccessibility.Notification.announcement, + argument: String.ReaderModeAddPageMaybeExistsErrorAccessibilityLabel + ) + } + + return true + } + private func showPhotonMainMenu(from button: UIButton?) { guard let button else { return } diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift index 9490514e17d6..a4aa0a1d9abb 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift @@ -103,6 +103,13 @@ class AddressToolbarContainerModel: Equatable { a11yLabel: action.a11yLabel, a11yHint: action.a11yHint, a11yId: action.a11yId, + a11yCustomActionName: action.a11yCustomActionName, + a11yCustomAction: action.a11yCustomActionName != nil ? { + let action = ToolbarMiddlewareAction(buttonType: action.actionType, + windowUUID: windowUUID, + actionType: ToolbarMiddlewareActionType.customA11yAction) + store.dispatch(action) + } : nil, onSelected: { button in let action = ToolbarMiddlewareAction(buttonType: action.actionType, buttonTapped: button, diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/NavigationToolbarContainerModel.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/NavigationToolbarContainerModel.swift index 839d45b8d6c8..5422c77e5d18 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/NavigationToolbarContainerModel.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/NavigationToolbarContainerModel.swift @@ -28,6 +28,13 @@ struct NavigationToolbarContainerModel: Equatable { a11yLabel: action.a11yLabel, a11yHint: action.a11yHint, a11yId: action.a11yId, + a11yCustomActionName: action.a11yCustomActionName, + a11yCustomAction: action.a11yCustomActionName != nil ? { + let action = ToolbarMiddlewareAction(buttonType: action.actionType, + windowUUID: windowUUID, + actionType: ToolbarMiddlewareActionType.customA11yAction) + store.dispatch(action) + } : nil, onSelected: { button in let action = ToolbarMiddlewareAction(buttonType: action.actionType, buttonTapped: button, diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarAction.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarAction.swift index 0b72bfce2289..f74182dd5ebc 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarAction.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarAction.swift @@ -123,6 +123,7 @@ class ToolbarMiddlewareAction: Action { enum ToolbarMiddlewareActionType: ActionType { case didTapButton + case customA11yAction case numberOfTabsChanged case urlDidChange case searchEngineDidChange diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarActionState.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarActionState.swift index 9cee22e36c41..b1ce7f012fc8 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarActionState.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarActionState.swift @@ -36,12 +36,14 @@ struct ToolbarActionState: Equatable, FeatureFlaggable { var a11yLabel: String var a11yHint: String? var a11yId: String + var a11yCustomActionName: String? func canPerformLongPressAction(isShowingTopTabs: Bool?) -> Bool { return actionType == .back || actionType == .forward || actionType == .reload || actionType == .newTab || + actionType == .readerMode || (actionType == .tabs && isShowingTopTabs == false) } } diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift index 069c3f0b88c4..1fdccd10bd0e 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift @@ -47,7 +47,9 @@ final class ToolbarMiddleware: FeatureFlaggable { iconName: StandardImageIdentifiers.Large.readerView, isEnabled: true, a11yLabel: .TabLocationReaderModeAccessibilityLabel, - a11yId: AccessibilityIdentifiers.Toolbar.readerModeButton) + a11yHint: .TabLocationReloadAccessibilityHint, + a11yId: AccessibilityIdentifiers.Toolbar.readerModeButton, + a11yCustomActionName: .TabLocationReaderModeAddToReadingListAccessibilityLabel) lazy var qrCodeScanAction = ToolbarActionState( actionType: .qrCode, @@ -130,6 +132,9 @@ final class ToolbarMiddleware: FeatureFlaggable { private func resolveToolbarMiddlewareActions(action: ToolbarMiddlewareAction, state: AppState) { switch action.actionType { + case ToolbarMiddlewareActionType.customA11yAction: + resolveToolbarMiddlewareCustomA11yActions(action: action, state: state) + case ToolbarMiddlewareActionType.didTapButton: resolveToolbarMiddlewareButtonTapActions(action: action, state: state) @@ -184,6 +189,16 @@ final class ToolbarMiddleware: FeatureFlaggable { } } + func resolveToolbarMiddlewareCustomA11yActions(action: ToolbarMiddlewareAction, state: AppState) { + switch action.buttonType { + case .readerMode: + let action = GeneralBrowserAction(windowUUID: action.windowUUID, + actionType: GeneralBrowserActionType.addToReadingListLongPressAction) + store.dispatch(action) + default: break + } + } + private func loadInitialAddressToolbarState(toolbarPosition: AddressToolbarPosition) -> AddressToolbarModel { let borderPosition = getAddressBorderPosition(toolbarPosition: toolbarPosition) @@ -307,8 +322,11 @@ final class ToolbarMiddleware: FeatureFlaggable { store.dispatch(action) case .newTab: let action = GeneralBrowserAction(windowUUID: action.windowUUID, - actionType: GeneralBrowserActionType.showNewTabLongPressActions - ) + actionType: GeneralBrowserActionType.showNewTabLongPressActions) + store.dispatch(action) + case .readerMode: + let action = GeneralBrowserAction(windowUUID: action.windowUUID, + actionType: GeneralBrowserActionType.addToReadingListLongPressAction) store.dispatch(action) default: break From b1cc6ab908cc6ef0f98792a41a502f83c067f483 Mon Sep 17 00:00:00 2001 From: Winnie Teichmann <4530+thatswinnie@users.noreply.github.com> Date: Thu, 22 Aug 2024 08:43:18 +0100 Subject: [PATCH 096/128] Refactor FXIOS-9761 Verify text color of location text field (#21545) * Use correct text color for location text field * Fix dark selected color * Fix warning * Tint clear button when changing theme * Update tint color & text color for editing * Fix Swiftlint warning --- .../Sources/Common/Theming/DarkTheme.swift | 2 +- .../LocationView/LocationTextField.swift | 33 ++++++++++++------- .../LocationView/LocationView.swift | 6 +++- 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/BrowserKit/Sources/Common/Theming/DarkTheme.swift b/BrowserKit/Sources/Common/Theming/DarkTheme.swift index baaeb49a092d..1606c4972de2 100644 --- a/BrowserKit/Sources/Common/Theming/DarkTheme.swift +++ b/BrowserKit/Sources/Common/Theming/DarkTheme.swift @@ -47,7 +47,7 @@ private struct DarkColourPalette: ThemeColourPalette { var layerConfirmation: UIColor = FXColors.Green80 var layerWarning: UIColor = FXColors.Yellow70.withAlphaComponent(0.77) var layerError: UIColor = FXColors.Pink80 - var layerSelectedText: UIColor = FXColors.DarkGrey05.withAlphaComponent(0.34) + var layerSelectedText: UIColor = FXColors.LightGrey05.withAlphaComponent(0.34) var layerSearch: UIColor = FXColors.DarkGrey80 var layerGradientURL = Gradient(colors: [ FXColors.DarkGrey80.withAlphaComponent(0), diff --git a/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationTextField.swift b/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationTextField.swift index ae874290ec20..2fae2d17af09 100644 --- a/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationTextField.swift +++ b/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationTextField.swift @@ -50,6 +50,7 @@ class LocationTextField: UITextField, UITextFieldDelegate, ThemeApplicable { autocorrectionType = .no autocapitalizationType = .none returnKeyType = .go + tintAdjustmentMode = .normal delegate = self // Disable dragging urls on iPhones because it conflicts with editing the text @@ -87,18 +88,8 @@ class LocationTextField: UITextField, UITextFieldDelegate, ThemeApplicable { override func layoutSubviews() { super.layoutSubviews() - guard let image = UIImage(named: StandardImageIdentifiers.Large.crossCircleFill) else { return } if tintedClearImage == nil { - if let clearButtonTintColor { - tintedClearImage = image.withTintColor(clearButtonTintColor) - } - } - - // Since we're unable to change the tint color of the clear image, we need to iterate through the - // subviews, find the clear button, and tint it ourselves. - // https://stackoverflow.com/questions/55046917/clear-button-on-text-field-not-accessible-with-voice-over-swift - if let clearButton = value(forKey: "_clearButton") as? UIButton { - clearButton.setImage(tintedClearImage, for: []) + tintClearButton() } } @@ -161,8 +152,15 @@ class LocationTextField: UITextField, UITextFieldDelegate, ThemeApplicable { // MARK: - ThemeApplicable func applyTheme(theme: Theme) { let colors = theme.colors + tintColor = colors.layerSelectedText clearButtonTintColor = colors.iconPrimary markedTextStyle = [NSAttributedString.Key.backgroundColor: colors.layerSelectedText] + + if isEditing { + textColor = colors.textPrimary + } + + tintClearButton() } // MARK: - Private @@ -235,6 +233,19 @@ class LocationTextField: UITextField, UITextFieldDelegate, ThemeApplicable { selectedTextRange = textRange(from: endOfDocument, to: endOfDocument) } + private func tintClearButton() { + // Since we're unable to change the tint color of the clear image, we need to use KVO to + // find the clear button, and tint it ourselves. + // https://stackoverflow.com/questions/27944781/how-to-change-the-tint-color-of-the-clear-button-on-a-uitextfield + guard let image = UIImage(named: StandardImageIdentifiers.Large.crossCircleFill), + let clearButtonTintColor, + let clearButton = value(forKey: "_clearButton") as? UIButton + else { return } + + tintedClearImage = image.withTintColor(clearButtonTintColor) + clearButton.setImage(tintedClearImage, for: []) + } + // MARK: - UITextFieldDelegate public func textFieldDidBeginEditing(_ textField: UITextField) { autocompleteDelegate?.locationTextFieldDidBeginEditing(self) diff --git a/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationView.swift b/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationView.swift index 6c83ed1e152c..6a54a46c04de 100644 --- a/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationView.swift +++ b/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationView.swift @@ -43,6 +43,7 @@ final class LocationView: UIView, LocationTextFieldDelegate, ThemeApplicable, Ac return CGFloat(width) } + private lazy var urlTextFieldColor: UIColor = .black private lazy var urlTextFieldSubdomainColor: UIColor = .clear private lazy var gradientLayer = CAGradientLayer() private lazy var gradientView: UIView = .build() @@ -276,7 +277,9 @@ final class LocationView: UIView, LocationTextFieldDelegate, ThemeApplicable, Ac let urlString = urlAbsolutePath ?? "" let (subdomain, normalizedHost) = URL.getSubdomainAndHost(from: urlString) - let attributedString = NSMutableAttributedString(string: normalizedHost) + let attributedString = NSMutableAttributedString( + string: normalizedHost, + attributes: [.foregroundColor: urlTextFieldColor]) if let subdomain { let range = NSRange(location: 0, length: subdomain.count) @@ -403,6 +406,7 @@ final class LocationView: UIView, LocationTextFieldDelegate, ThemeApplicable, Ac // MARK: - ThemeApplicable func applyTheme(theme: Theme) { let colors = theme.colors + urlTextFieldColor = colors.textPrimary urlTextFieldSubdomainColor = colors.textSecondary gradientLayer.colors = colors.layerGradientURL.cgColors.reversed() searchEngineImageView.backgroundColor = colors.iconPrimary From a2da2b97abed210131c8c558277120d86a87d831 Mon Sep 17 00:00:00 2001 From: dicarobinho <61138287+dicarobinho@users.noreply.github.com> Date: Thu, 22 Aug 2024 14:50:02 +0300 Subject: [PATCH 097/128] =?UTF-8?q?Add=20FXIOS-9828=20=E2=81=83=20Enhanced?= =?UTF-8?q?=20Tracking=20Protection=20certificates=20details=20screen=20st?= =?UTF-8?q?rings=20(#21584)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- firefox-ios/Client/Frontend/Strings.swift | 66 +++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/firefox-ios/Client/Frontend/Strings.swift b/firefox-ios/Client/Frontend/Strings.swift index c2514e874800..57ec5a0a20b2 100644 --- a/firefox-ios/Client/Frontend/Strings.swift +++ b/firefox-ios/Client/Frontend/Strings.swift @@ -4261,6 +4261,72 @@ extension String { tableName: "EnhancedTrackingProtection", value: "Privacy settings", comment: "The title for the privacy settings button inside the enhanced tracking protection screen.") + + public static let certificatesTitle = MZLocalizedString( + key: "Menu.EnhancedTrackingProtection.Certificates.Title.v131", + tableName: "EnhancedTrackingProtection", + value: "Certificate", + comment: "The title for the certificates screen inside the certificates screen.") + + public static let certificateSubjectName = MZLocalizedString( + key: "Menu.EnhancedTrackingProtection.Certificates.SubjectName.v131", + tableName: "EnhancedTrackingProtection", + value: "Subject Name", + comment: "The title for the certificate subject name section inside the certificate screen.") + + public static let certificateCommonName = MZLocalizedString( + key: "Menu.EnhancedTrackingProtection.Certificates.CommonName.v131", + tableName: "EnhancedTrackingProtection", + value: "Common Name", + comment: "The title for the certificate common name inside the certificate screen.") + + public static let certificateIssuerName = MZLocalizedString( + key: "Menu.EnhancedTrackingProtection.Certificates.IssuerName.v131", + tableName: "EnhancedTrackingProtection", + value: "Issuer Name", + comment: "The title for the certificate issuer name section inside the certificate screen.") + + public static let certificateIssuerCountry = MZLocalizedString( + key: "Menu.EnhancedTrackingProtection.Certificates.IssuerCountry.v131", + tableName: "EnhancedTrackingProtection", + value: "Country", + comment: "The title for the certificate issuer country inside the certificate screen.") + + public static let certificateIssuerOrganization = MZLocalizedString( + key: "Menu.EnhancedTrackingProtection.Certificates.IssuerOrganization.v131", + tableName: "EnhancedTrackingProtection", + value: "Organization", + comment: "The title for the certificate issuer organization inside the certificate screen.") + + public static let certificateValidity = MZLocalizedString( + key: "Menu.EnhancedTrackingProtection.Certificates.Validity.v131", + tableName: "EnhancedTrackingProtection", + value: "Validity", + comment: "The title for the certificate validity section inside the certificate screen.") + + public static let certificateValidityNotBefore = MZLocalizedString( + key: "Menu.EnhancedTrackingProtection.Certificates.ValidityNotBefore.v131", + tableName: "EnhancedTrackingProtection", + value: "Not Before", + comment: "The title for the certificate validity not before date inside the certificate screen.") + + public static let certificateValidityNotAfter = MZLocalizedString( + key: "Menu.EnhancedTrackingProtection.Certificates.ValidityNotAfter.v131", + tableName: "EnhancedTrackingProtection", + value: "Not After", + comment: "The title for the certificate validity not after date inside the certificate screen.") + + public static let certificateSubjectAltNames = MZLocalizedString( + key: "Menu.EnhancedTrackingProtection.Certificates.SubjectAltNames.v131", + tableName: "EnhancedTrackingProtection", + value: "Subject Alt Names", + comment: "The title for the certificate subject alt names section inside the certificate screen.") + + public static let certificateSubjectAltNamesDNSName = MZLocalizedString( + key: "Menu.EnhancedTrackingProtection.Certificates.SubjectAltNamesDNSName.v131", + tableName: "EnhancedTrackingProtection", + value: "DNS Name", + comment: "The title for the certificate subject alt names DNS name inside the certificate screen.") } } } From 285ec70c599b95ae1de8ccb2cf9e44a031861741 Mon Sep 17 00:00:00 2001 From: Winnie Teichmann <4530+thatswinnie@users.noreply.github.com> Date: Fri, 23 Aug 2024 09:32:26 +0100 Subject: [PATCH 098/128] Refactor FXIOS-9823 Use StandardImageIdentifiers in app extensions (#21576) * Add external link icon * Use standard image identifiers in app extensions * Mark image as template * Fix Swiftlint warnings --- .../Constants/StandardImageIdentifiers.swift | 1 + .../externalLinkSmall.imageset/Contents.json | 15 +++++++++++++++ .../externalLinkSmall.pdf | Bin 0 -> 1784 bytes .../CredentialListViewController.swift | 8 ++++++-- .../Extensions/ShareTo/ShareViewController.swift | 14 +++++++------- .../privateModeLarge.imageset/Contents.json | 3 ++- firefox-ios/WidgetKit/ImageButtonWithLabel.swift | 3 ++- .../WidgetKit/OpenTabs/OpenTabsWidget.swift | 11 +++++++---- firefox-ios/WidgetKit/QuickLink.swift | 7 ++++--- 9 files changed, 44 insertions(+), 18 deletions(-) create mode 100644 firefox-ios/Client/Assets/Images.xcassets/externalLinkSmall.imageset/Contents.json create mode 100644 firefox-ios/Client/Assets/Images.xcassets/externalLinkSmall.imageset/externalLinkSmall.pdf diff --git a/BrowserKit/Sources/Common/Constants/StandardImageIdentifiers.swift b/BrowserKit/Sources/Common/Constants/StandardImageIdentifiers.swift index f7bd51422a91..a94b3e8106a8 100644 --- a/BrowserKit/Sources/Common/Constants/StandardImageIdentifiers.swift +++ b/BrowserKit/Sources/Common/Constants/StandardImageIdentifiers.swift @@ -10,6 +10,7 @@ import Foundation public struct StandardImageIdentifiers { // Icon size 16x16 public struct Small { + public static let externalLink = "externalLinkSmall" public static let notificationDot = "notificationDotSmall" public static let notificationDotFill = "notificationDotFillSmall" public static let pinBadgeFill = "pinBadgeFillSmall" diff --git a/firefox-ios/Client/Assets/Images.xcassets/externalLinkSmall.imageset/Contents.json b/firefox-ios/Client/Assets/Images.xcassets/externalLinkSmall.imageset/Contents.json new file mode 100644 index 000000000000..bd08dc6caa87 --- /dev/null +++ b/firefox-ios/Client/Assets/Images.xcassets/externalLinkSmall.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "externalLinkSmall.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/firefox-ios/Client/Assets/Images.xcassets/externalLinkSmall.imageset/externalLinkSmall.pdf b/firefox-ios/Client/Assets/Images.xcassets/externalLinkSmall.imageset/externalLinkSmall.pdf new file mode 100644 index 0000000000000000000000000000000000000000..371e4c8a0886782fc35e3758d28906ba2c1de61a GIT binary patch literal 1784 zcmb7_O>f&U42JLe6}%K^50&+;7$^#?$vO<%urA%L*uituG=pPrwmWqD^`&fCa+(6e zbO@No)Juw#>64q)^*N`O5DpBQ?>`8@#RXhm5?62hUn1r_`{?Rz{{Rx<+Iw|<>xwhW1}nU^q7lDdA5g3%9#>eVcbQo z?ZN<8lV9ABP)Y3cG{I^H1=Zs@Dw4L(Al6X~@i3j>$)h2tuwxE06zWo9iNb~`TqTxt zV}K*~D1cf~BSI8=HGa(UDDkK<=mo!6AJmJLd=hhG3=CDA zb7`SM#$-M+D~xA36-FQgi-sPFW!C#dg6)yRWtc-Ox}?^c1JBU0!H;2743Lnac8q{} zV`tG%(A)|x4JJ2-T38P;gfjSoc|XbIpoe``LsUTxUwDLicztbd4F^f{g;Lz>VF7b3 z77W59Funqqgha_4a26P*bL9gcmoK%=52-MLrg7yb(>TUBS29j9oB?UNWpC=b={val zhSLsL_Vv$C2iZ-rbpd>Gn_Y3$Ji%R>S@D{26URifCZ)COn#Z2@#x_g2bjf^j-{{^G9)POiF&S0$<|HNgFo<4;Outy*J1Xzm+;W%6yK~7HIe!hMN DfkkrC literal 0 HcmV?d00001 diff --git a/firefox-ios/CredentialProvider/CredentialListViewController.swift b/firefox-ios/CredentialProvider/CredentialListViewController.swift index c184391f2cd9..b03c6ddaf558 100644 --- a/firefox-ios/CredentialProvider/CredentialListViewController.swift +++ b/firefox-ios/CredentialProvider/CredentialListViewController.swift @@ -4,6 +4,7 @@ import UIKit import AuthenticationServices +import Common protocol CredentialListViewProtocol: AnyObject { var credentialExtensionContext: ASCredentialProviderExtensionContext? { get } @@ -109,8 +110,11 @@ class CredentialListViewController: UIViewController, CredentialListViewProtocol self.navigationItem.hidesSearchBarWhenScrolling = false self.definesPresentationContext = true - let searchIcon = UIImage(named: "searchLarge")?.withRenderingMode(.alwaysTemplate).tinted(UIColor.systemBlue) - let clearIcon = UIImage(named: "crossCircleFillLarge")?.withRenderingMode(.alwaysTemplate) + let searchIcon = UIImage(named: StandardImageIdentifiers.Large.search)? + .withRenderingMode(.alwaysTemplate) + .tinted(UIColor.systemBlue) + let clearIcon = UIImage(named: StandardImageIdentifiers.Large.crossCircleFill)? + .withRenderingMode(.alwaysTemplate) .tinted(UIColor.systemBlue) searchController.searchBar.setImage(searchIcon, for: UISearchBar.Icon.search, state: .normal) searchController.searchBar.setImage(clearIcon, for: UISearchBar.Icon.clear, state: .normal) diff --git a/firefox-ios/Extensions/ShareTo/ShareViewController.swift b/firefox-ios/Extensions/ShareTo/ShareViewController.swift index 5d9d4636060d..d6a50d18525e 100644 --- a/firefox-ios/Extensions/ShareTo/ShareViewController.swift +++ b/firefox-ios/Extensions/ShareTo/ShareViewController.swift @@ -147,28 +147,28 @@ class ShareViewController: UIViewController { makeActionRow( addTo: stackView, label: .ShareOpenInFirefox, - imageName: "logoFirefoxLarge", + imageName: StandardImageIdentifiers.Large.logoFirefox, action: #selector(actionOpenInFirefoxNow), hasNavigation: false ) makeActionRow( addTo: stackView, label: .ShareLoadInBackground, - imageName: "tabTrayLarge", + imageName: StandardImageIdentifiers.Large.tabTray, action: #selector(actionLoadInBackground), hasNavigation: false ) makeActionRow( addTo: stackView, label: .ShareBookmarkThisPage, - imageName: "bookmarkLarge", + imageName: StandardImageIdentifiers.Large.bookmark, action: #selector(actionBookmarkThisPage), hasNavigation: false ) makeActionRow( addTo: stackView, label: .ShareAddToReadingList, - imageName: "readingListAddLarge", + imageName: StandardImageIdentifiers.Large.readingListAdd, action: #selector(actionAddToReadingList), hasNavigation: false ) @@ -176,7 +176,7 @@ class ShareViewController: UIViewController { makeActionRow( addTo: stackView, label: .ShareSendToDevice, - imageName: "deviceDesktopSendLarge", + imageName: StandardImageIdentifiers.Large.deviceDesktopSend, action: #selector(actionSendToDevice), hasNavigation: true ) @@ -185,7 +185,7 @@ class ShareViewController: UIViewController { makeActionRow( addTo: stackView, label: .ShareSearchInFirefox, - imageName: "searchLarge", + imageName: StandardImageIdentifiers.Large.search, action: #selector(actionSearchInFirefox), hasNavigation: false ) @@ -317,7 +317,7 @@ class ShareViewController: UIViewController { if hasNavigation { let navButton = UIImageView( - image: UIImage(named: "chevronRightLarge")?.withRenderingMode(.alwaysTemplate) + image: UIImage(named: StandardImageIdentifiers.Large.chevronRight)?.withRenderingMode(.alwaysTemplate) ) navButton.contentMode = .scaleAspectFit navButton.tintColor = theme.colors.textPrimary diff --git a/firefox-ios/WidgetKit/Assets.xcassets/privateModeLarge.imageset/Contents.json b/firefox-ios/WidgetKit/Assets.xcassets/privateModeLarge.imageset/Contents.json index 570a48042855..64b21449c03b 100644 --- a/firefox-ios/WidgetKit/Assets.xcassets/privateModeLarge.imageset/Contents.json +++ b/firefox-ios/WidgetKit/Assets.xcassets/privateModeLarge.imageset/Contents.json @@ -10,6 +10,7 @@ "version" : 1 }, "properties" : { - "preserves-vector-representation" : true + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" } } diff --git a/firefox-ios/WidgetKit/ImageButtonWithLabel.swift b/firefox-ios/WidgetKit/ImageButtonWithLabel.swift index 46b447261db6..7fa3b2a1e2c7 100644 --- a/firefox-ios/WidgetKit/ImageButtonWithLabel.swift +++ b/firefox-ios/WidgetKit/ImageButtonWithLabel.swift @@ -4,6 +4,7 @@ #if canImport(WidgetKit) import SwiftUI +import Common // View for Quick Action Widget Buttons (Small & Medium) // +-------------------------------------------------------+ @@ -90,7 +91,7 @@ struct ImageButtonWithLabel: View { } Spacer() if link == .search && isSmall { - Image("searchLarge") + Image(StandardImageIdentifiers.Large.search) .scaledToFit() .frame(height: 24.0) } else { diff --git a/firefox-ios/WidgetKit/OpenTabs/OpenTabsWidget.swift b/firefox-ios/WidgetKit/OpenTabs/OpenTabsWidget.swift index 3171e78439f6..826bb3f865d9 100644 --- a/firefox-ios/WidgetKit/OpenTabs/OpenTabsWidget.swift +++ b/firefox-ios/WidgetKit/OpenTabs/OpenTabsWidget.swift @@ -6,6 +6,7 @@ import SwiftUI import WidgetKit import UIKit import Combine +import Common struct OpenTabsWidget: Widget { private let kind: String = "Quick View" @@ -36,7 +37,7 @@ struct OpenTabsView: View { if entry.favicons[tab.imageKey] != nil { (entry.favicons[tab.imageKey])!.resizable().frame(width: 16, height: 16) } else { - Image("globeLarge") + Image(StandardImageIdentifiers.Large.globe) .foregroundColor(Color.white) .frame(width: 16, height: 16) } @@ -58,7 +59,7 @@ struct OpenTabsView: View { var openFirefoxButton: some View { HStack(alignment: .center, spacing: 15) { - Image("externalLinkSmall").foregroundColor(Color.white) + Image(StandardImageIdentifiers.Small.externalLink).foregroundColor(Color.white) Text("Open Firefox") .foregroundColor(Color.white).lineLimit(1) .font(.system(size: 13, weight: .semibold, design: .default)) @@ -81,7 +82,7 @@ struct OpenTabsView: View { Text(String.NoOpenTabsLabel) HStack { Spacer() - Image("externalLinkSmall") + Image(StandardImageIdentifiers.Small.externalLink) Text(String.OpenFirefoxLabel) .foregroundColor(Color.white).lineLimit(1) .font(.system(size: 13, weight: .semibold, design: .default)) @@ -96,7 +97,9 @@ struct OpenTabsView: View { if entry.tabs.count > numberOfTabsToDisplay { HStack(alignment: .center, spacing: 15) { - Image("externalLinkSmall").foregroundColor(Color.white).frame(width: 16, height: 16) + Image(StandardImageIdentifiers.Small.externalLink) + .foregroundColor(Color.white) + .frame(width: 16, height: 16) Text( String.localizedStringWithFormat( String.MoreTabsLabel, diff --git a/firefox-ios/WidgetKit/QuickLink.swift b/firefox-ios/WidgetKit/QuickLink.swift index ba5ef8a8cc3d..c513707c545f 100644 --- a/firefox-ios/WidgetKit/QuickLink.swift +++ b/firefox-ios/WidgetKit/QuickLink.swift @@ -3,6 +3,7 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/ import SwiftUI +import Common /// Enum file that holds the different cases for the Quick Actions small widget with their /// configurations (string, backgrounds, images) as selected by the user in edit mode. @@ -17,11 +18,11 @@ enum QuickLink: Int { case .search: return "faviconFox" case .privateSearch: - return "privateModeLarge" + return StandardImageIdentifiers.Large.privateMode case .copiedLink: - return "tabTrayLarge" + return StandardImageIdentifiers.Large.tabTray case .closePrivateTabs: - return "deleteLarge" + return StandardImageIdentifiers.Large.delete } } From 39c3a816bfc83f14cf8c350603f587603b7d7bcf Mon Sep 17 00:00:00 2001 From: Cyndi Chin Date: Fri, 23 Aug 2024 09:23:01 -0400 Subject: [PATCH 099/128] Bugfix FXIOS-9825 [Unit Tests] Remove unnecessary glean calls (#21579) --- .../Tests/ClientTests/BrowserViewControllerTests.swift | 1 - .../Tests/ClientTests/ContextMenuHelperTests.swift | 1 - .../Messaging/GleanPlumbMessageManagerTests.swift | 1 - .../ClientTests/Microsurvey/MicrosurveyMiddlewareTests.swift | 3 +-- .../OnboardingTests/OnboardingTelemetryDelegationTests.swift | 3 +-- .../OnboardingTests/OnboardingTelemetryUtilityTests.swift | 5 ----- .../Tests/ClientTests/PasswordManagerViewModelTests.swift | 1 - .../Tests/ClientTests/PrivateBrowsingTelemetryTests.swift | 1 - .../Tests/ClientTests/SponsoredTileTelemetryTests.swift | 1 - .../TabManagement/Legacy/TabsTelemetryTests.swift | 1 - .../Tests/ClientTests/Telemetry/HomepageTelemetryTests.swift | 1 - .../Tests/ClientTests/TelemetryWrapperTests.swift | 1 - 12 files changed, 2 insertions(+), 18 deletions(-) diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/BrowserViewControllerTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/BrowserViewControllerTests.swift index b07bdc091e73..f8b0d36a26f8 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/BrowserViewControllerTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/BrowserViewControllerTests.swift @@ -20,7 +20,6 @@ class BrowserViewControllerTests: XCTestCase { DependencyHelperMock().bootstrapDependencies() TelemetryContextualIdentifier.setupContextId() Glean.shared.resetGlean(clearStores: true) - Glean.shared.enableTestingMode() profile = MockProfile() tabManager = MockTabManager() diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/ContextMenuHelperTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/ContextMenuHelperTests.swift index a9cd79587382..0d266cd7ab14 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/ContextMenuHelperTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/ContextMenuHelperTests.swift @@ -20,7 +20,6 @@ class ContextMenuHelperTests: XCTestCase { DependencyHelperMock().bootstrapDependencies() Glean.shared.resetGlean(clearStores: true) - Glean.shared.enableTestingMode() } override func tearDown() { diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Messaging/GleanPlumbMessageManagerTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Messaging/GleanPlumbMessageManagerTests.swift index 211953397aaa..b3192d352fc0 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Messaging/GleanPlumbMessageManagerTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Messaging/GleanPlumbMessageManagerTests.swift @@ -18,7 +18,6 @@ class GleanPlumbMessageManagerTests: XCTestCase { super.setUp() Glean.shared.resetGlean(clearStores: true) - Glean.shared.enableTestingMode() messagingStore = MockGleanPlumbMessageStore(messageId: messageId) applicationHelper = MockApplicationHelper() subject = GleanPlumbMessageManager( diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Microsurvey/MicrosurveyMiddlewareTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Microsurvey/MicrosurveyMiddlewareTests.swift index afb093491bfa..f0bc7a285ad7 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Microsurvey/MicrosurveyMiddlewareTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Microsurvey/MicrosurveyMiddlewareTests.swift @@ -12,13 +12,12 @@ final class MicrosurveyMiddlewareTests: XCTestCase { override func setUp() { super.setUp() Glean.shared.resetGlean(clearStores: true) - Glean.shared.enableTestingMode() DependencyHelperMock().bootstrapDependencies() } override func tearDown() { - super.tearDown() DependencyHelperMock().reset() + super.tearDown() } func testDismissSurveyAction() throws { diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/OnboardingTests/OnboardingTelemetryDelegationTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/OnboardingTests/OnboardingTelemetryDelegationTests.swift index cd8789f5d5d0..29c272263810 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/OnboardingTests/OnboardingTelemetryDelegationTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/OnboardingTests/OnboardingTelemetryDelegationTests.swift @@ -20,9 +20,8 @@ class OnboardingTelemetryDelegationTests: XCTestCase { } override func tearDown() { - super.tearDown() - Glean.shared.resetGlean(clearStores: true) nimbusUtility = nil + super.tearDown() } func testOnboardingCard_viewSendsCardView() { diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/OnboardingTests/OnboardingTelemetryUtilityTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/OnboardingTests/OnboardingTelemetryUtilityTests.swift index 5f728d4cb61e..ddce3bcc9865 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/OnboardingTests/OnboardingTelemetryUtilityTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/OnboardingTests/OnboardingTelemetryUtilityTests.swift @@ -15,11 +15,6 @@ class OnboardingTelemetryUtilityTests: XCTestCase { Glean.shared.resetGlean(clearStores: true) } - override func tearDown() { - super.tearDown() - Glean.shared.resetGlean(clearStores: true) - } - // MARK: - Card View telemetry func testSendOnboardingCardView_WelcomeCard_Success() { let subject = createTelemetryUtility(for: .freshInstall) diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/PasswordManagerViewModelTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/PasswordManagerViewModelTests.swift index d7904214a1db..48d03de300c3 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/PasswordManagerViewModelTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/PasswordManagerViewModelTests.swift @@ -36,7 +36,6 @@ class PasswordManagerViewModelTests: XCTestCase { } override func tearDown() { - Glean.shared.resetGlean(clearStores: true) viewModel = nil mockLoginProvider = nil mockDelegate = nil diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/PrivateBrowsingTelemetryTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/PrivateBrowsingTelemetryTests.swift index f513252fc3e3..22abd67c3669 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/PrivateBrowsingTelemetryTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/PrivateBrowsingTelemetryTests.swift @@ -11,7 +11,6 @@ final class PrivateBrowsingTelemetryTests: XCTestCase { override func setUp() { super.setUp() Glean.shared.resetGlean(clearStores: true) - Glean.shared.enableTestingMode() } func testDataClearanceConfirmed() throws { diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/SponsoredTileTelemetryTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/SponsoredTileTelemetryTests.swift index f1158268bd93..13dda51927db 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/SponsoredTileTelemetryTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/SponsoredTileTelemetryTests.swift @@ -107,7 +107,6 @@ class SponsoredTileTelemetryTests: XCTestCase { func clearTest() { Glean.shared.resetGlean(clearStores: true) - Glean.shared.enableTestingMode() TelemetryContextualIdentifier.clearUserDefaults() } } diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/TabManagement/Legacy/TabsTelemetryTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/TabManagement/Legacy/TabsTelemetryTests.swift index 410216fd7a86..ccf1df84e1e2 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/TabManagement/Legacy/TabsTelemetryTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/TabManagement/Legacy/TabsTelemetryTests.swift @@ -19,7 +19,6 @@ class TabsTelemetryTests: XCTestCase { inactiveTabsManager = MockInactiveTabsManager() LegacyFeatureFlagsManager.shared.initializeDeveloperFeatures(with: profile) Glean.shared.resetGlean(clearStores: true) - Glean.shared.enableTestingMode() DependencyHelperMock().bootstrapDependencies() } diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Telemetry/HomepageTelemetryTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Telemetry/HomepageTelemetryTests.swift index 78d2dd91e476..805c45a05068 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Telemetry/HomepageTelemetryTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Telemetry/HomepageTelemetryTests.swift @@ -11,7 +11,6 @@ final class HomepageTelemetryTests: XCTestCase { override func setUp() { super.setUp() Glean.shared.resetGlean(clearStores: true) - Glean.shared.enableTestingMode() } func testPrivateModeShortcutToggleTappedInNormalMode() throws { diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/TelemetryWrapperTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/TelemetryWrapperTests.swift index d60ebb7fa1e6..c1b62fc4a098 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/TelemetryWrapperTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/TelemetryWrapperTests.swift @@ -19,7 +19,6 @@ class TelemetryWrapperTests: XCTestCase { } override func tearDown() { - Glean.shared.resetGlean(clearStores: true) Experiments.events.clearEvents() DependencyHelperMock().reset() super.tearDown() From 0b924b968f6a0cbe4c292edaf39d1d73aa3d39cc Mon Sep 17 00:00:00 2001 From: Daniel Dervishi <58835213+DanielDervishi@users.noreply.github.com> Date: Fri, 23 Aug 2024 09:36:45 -0400 Subject: [PATCH 100/128] Add FXIOS-9783 - Add strings for Bookmarks MVP+1 (#21508) * Finished string changes * Added version numbers to string keys * Updated version number to release the strings are included in * Fixed swiftlint violations --------- Co-authored-by: Daniel Dervishi --- firefox-ios/Client/Frontend/Strings.swift | 45 +++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/firefox-ios/Client/Frontend/Strings.swift b/firefox-ios/Client/Frontend/Strings.swift index 57ec5a0a20b2..2378560cace0 100644 --- a/firefox-ios/Client/Frontend/Strings.swift +++ b/firefox-ios/Client/Frontend/Strings.swift @@ -132,6 +132,46 @@ extension String { tableName: nil, value: "Desktop Bookmarks", comment: "A label indicating all bookmarks grouped under the category 'Desktop Bookmarks'.") + public static let EditBookmark = MZLocalizedString( + key: "Bookmarks.Menu.EditBookmark.v131", + tableName: "Bookmarks", + value: "Edit Bookmark", + comment: "When a bookmark is longpressed in the bookmarks menu, an `Edit Bookmark` button is present.") + public static let EditFolder = MZLocalizedString( + key: "Bookmarks.Menu.EditFolder.v131", + tableName: "Bookmarks", + value: "Edit Folder", + comment: "When a folder is longpressed in the bookmarks menu, an `Edit Folder` button is present.") + public static let DeleteFolder = MZLocalizedString( + key: "Bookmarks.Menu.DeleteFolder.v131", + tableName: "Bookmarks", + value: "Delete Folder", + comment: "When a folder is longpressed in the bookmarks menu, a `Delete Folder` button is present.") + public static let AllBookmarks = MZLocalizedString( + key: "Bookmarks.Menu.AllBookmarks.v131", + tableName: "Bookmarks", + value: "All", + comment: "When navigating through the bookmarks menu and bookmark folders, a back button with an `All` (bookmarks) label is present to take the user to the top level bookmarks menu.") + public static let EditBookmarkSaveIn = MZLocalizedString( + key: "Bookmarks.Menu.EditBookmarkSaveIn.v131", + tableName: "Bookmarks", + value: "Save in", + comment: "When editing a bookmark, you can select the folder that the bookmark will be saved in. The label for this section of the view is `Save in`.") + public static let EditBookmarkTitle = MZLocalizedString( + key: "Bookmarks.Menu.EditBookmarkTitle.v131", + tableName: "Bookmarks", + value: "Edit Bookmark", + comment: "Label on the top of the `Edit Bookmarks` screen.") + public static let DeletedBookmark = MZLocalizedString( + key: "Bookmarks.Menu.DeletedBookmark.v131", + tableName: "Bookmarks", + value: "Deleted \"%@\"", + comment: "Label of toast displayed after a bookmark is deleted in the Bookmarks menu. %@ is the name of the bookmark.") + public static let BookmarksTopLevelTitle = MZLocalizedString( + key: "Bookmarks.Menu.BookmarksTopLevelTitle.v131", + tableName: "Bookmarks", + value: "Bookmarks", + comment: "Name of the top level bookmarks folder present in the folder selection menu of the`Edit Bookmark` screen") } } } @@ -2606,6 +2646,11 @@ extension String { tableName: nil, value: "Remove", comment: "The title for the Remove context menu action for sites in Home Panels") + public static let EditContextMenuTitle = MZLocalizedString( + key: "HomePanel.ContextMenu.Edit.v131", + tableName: "Bookmarks", + value: "Edit", + comment: "The title for the Edit context menu action for sites in Home Panels") public static let PinTopsiteActionTitle2 = MZLocalizedString( key: "ActivityStream.ContextMenu.PinTopsite2", tableName: nil, From 10e1fb3461e83122c0b3d297aaebb7e1fcbecdfb Mon Sep 17 00:00:00 2001 From: Matt Lichtenstein Date: Fri, 23 Aug 2024 11:25:30 -0400 Subject: [PATCH 101/128] Add FXIOS-9741: Data clearance button for address toolbar (#21580) --- .../Toolbars/Redux/ToolbarMiddleware.swift | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift index 1fdccd10bd0e..5fd26a46ac62 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift @@ -548,6 +548,9 @@ final class ToolbarMiddleware: FeatureFlaggable { let isForwardButtonEnabled = canGoForward actions.append(backAction(enabled: isBackButtonEnabled)) actions.append(forwardAction(enabled: isForwardButtonEnabled)) + if shouldShowDataClearanceAction(isPrivate: toolbarState.isPrivateMode) { + actions.append(dataClearanceAction) + } } return actions @@ -682,10 +685,7 @@ final class ToolbarMiddleware: FeatureFlaggable { } private func getMiddleButtonAction(url: URL?, isPrivateMode: Bool) -> ToolbarActionState { - let isFeltPrivacyUIEnabled = featureFlags.isFeatureEnabled(.feltPrivacySimplifiedUI, checking: .buildOnly) - let isFeltPrivacyDeletionEnabled = featureFlags.isFeatureEnabled(.feltPrivacyFeltDeletion, checking: .buildOnly) - let shouldShowDataClearanceAction = isPrivateMode && isFeltPrivacyUIEnabled && - isFeltPrivacyDeletionEnabled + let shouldShowDataClearanceAction = shouldShowDataClearanceAction(isPrivate: isPrivateMode) guard !shouldShowDataClearanceAction else { return dataClearanceAction } @@ -751,4 +751,11 @@ final class ToolbarMiddleware: FeatureFlaggable { private func shouldDisplayNavigationToolbarBorder(toolbarPosition: AddressToolbarPosition) -> Bool { return manager.shouldDisplayNavigationBorder(toolbarPosition: toolbarPosition) } + + private func shouldShowDataClearanceAction(isPrivate: Bool) -> Bool { + let isFeltPrivacyUIEnabled = featureFlags.isFeatureEnabled(.feltPrivacySimplifiedUI, checking: .buildOnly) + let isFeltPrivacyDeletionEnabled = featureFlags.isFeatureEnabled(.feltPrivacyFeltDeletion, checking: .buildOnly) + + return isPrivate && isFeltPrivacyUIEnabled && isFeltPrivacyDeletionEnabled + } } From cb1436b185438e8c63f77eb6e325ec9ef527c0c6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 23 Aug 2024 13:04:52 -0400 Subject: [PATCH 102/128] Auto update SPM with latest rust-component release 131.0.20240821050323 (#21575) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- firefox-ios/Client.xcodeproj/project.pbxproj | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- focus-ios/Blockzilla.xcodeproj/project.pbxproj | 2 +- .../project.xcworkspace/xcshareddata/swiftpm/Package.resolved | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/firefox-ios/Client.xcodeproj/project.pbxproj b/firefox-ios/Client.xcodeproj/project.pbxproj index a8375c24eed5..596368e873a7 100644 --- a/firefox-ios/Client.xcodeproj/project.pbxproj +++ b/firefox-ios/Client.xcodeproj/project.pbxproj @@ -23171,7 +23171,7 @@ repositoryURL = "https://github.com/mozilla/rust-components-swift.git"; requirement = { kind = exactVersion; - version = 131.0.20240815050258; + version = 131.0.20240821050323; }; }; 435C85EE2788F4D00072B526 /* XCRemoteSwiftPackageReference "glean-swift" */ = { diff --git a/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 3aa85553d9e6..a825940aa98b 100644 --- a/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -95,8 +95,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/mozilla/rust-components-swift.git", "state" : { - "revision" : "5f9d1dbd9457d56ed16090e1ff9a38b9f0ffab19", - "version" : "131.0.20240815050258" + "revision" : "368989055f07f4e2c135ebed7f4d649b22c1dae2", + "version" : "131.0.20240821050323" } }, { diff --git a/focus-ios/Blockzilla.xcodeproj/project.pbxproj b/focus-ios/Blockzilla.xcodeproj/project.pbxproj index cf72a52bbeb3..658339ac4e06 100644 --- a/focus-ios/Blockzilla.xcodeproj/project.pbxproj +++ b/focus-ios/Blockzilla.xcodeproj/project.pbxproj @@ -7159,7 +7159,7 @@ repositoryURL = "https://github.com/mozilla/rust-components-swift"; requirement = { kind = exactVersion; - version = 131.0.20240815050258; + version = 131.0.20240821050323; }; }; 8A0E7F2C2BA0F0E0006BC6B6 /* XCRemoteSwiftPackageReference "Fuzi" */ = { diff --git a/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 78036b5d895f..7881ffafaea2 100644 --- a/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/focus-ios/Blockzilla.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -51,8 +51,8 @@ "repositoryURL": "https://github.com/mozilla/rust-components-swift", "state": { "branch": null, - "revision": "5f9d1dbd9457d56ed16090e1ff9a38b9f0ffab19", - "version": "131.0.20240815050258" + "revision": "368989055f07f4e2c135ebed7f4d649b22c1dae2", + "version": "131.0.20240821050323" } }, { From da611429b1494cef4bc2d29846b10d4fe2b43cc0 Mon Sep 17 00:00:00 2001 From: Daniel Dervishi <58835213+DanielDervishi@users.noreply.github.com> Date: Fri, 23 Aug 2024 13:38:40 -0400 Subject: [PATCH 103/128] Add FXIOS-9832 - Password Generator Feature Flag (#21590) * Feature Flag Added * Addressed comments --------- Co-authored-by: Daniel Dervishi --- .../FeatureFlags/NimbusFlaggableFeature.swift | 2 ++ .../Client/Nimbus/NimbusFeatureFlagLayer.swift | 7 +++++++ .../passwordGeneratorFeature.yaml | 17 +++++++++++++++++ firefox-ios/nimbus.fml.yaml | 1 + 4 files changed, 27 insertions(+) create mode 100644 firefox-ios/nimbus-features/passwordGeneratorFeature.yaml diff --git a/firefox-ios/Client/FeatureFlags/NimbusFlaggableFeature.swift b/firefox-ios/Client/FeatureFlags/NimbusFlaggableFeature.swift index b5af01560936..8903187e7af8 100644 --- a/firefox-ios/Client/FeatureFlags/NimbusFlaggableFeature.swift +++ b/firefox-ios/Client/FeatureFlags/NimbusFlaggableFeature.swift @@ -29,6 +29,7 @@ enum NimbusFeatureFlagID: String, CaseIterable { case microsurvey case nativeErrorPage case nightMode + case passwordGenerator case preferSwitchToOpenTabOverDuplicate case reduxSearchSettings case closeRemoteTabs @@ -91,6 +92,7 @@ struct NimbusFlaggableFeature: HasNimbusSearchBar { .menuRefactor, .nativeErrorPage, .nightMode, + .passwordGenerator, .preferSwitchToOpenTabOverDuplicate, .reduxSearchSettings, .reportSiteIssue, diff --git a/firefox-ios/Client/Nimbus/NimbusFeatureFlagLayer.swift b/firefox-ios/Client/Nimbus/NimbusFeatureFlagLayer.swift index 7e2675a4254f..192588067a45 100644 --- a/firefox-ios/Client/Nimbus/NimbusFeatureFlagLayer.swift +++ b/firefox-ios/Client/Nimbus/NimbusFeatureFlagLayer.swift @@ -64,6 +64,9 @@ final class NimbusFeatureFlagLayer { case .nightMode: return checkNightModeFeature(from: nimbus) + case .passwordGenerator: + return checkPasswordGeneratorFeature(from: nimbus) + case .preferSwitchToOpenTabOverDuplicate: return checkPreferSwitchToOpenTabOverDuplicate(from: nimbus) @@ -247,6 +250,10 @@ final class NimbusFeatureFlagLayer { return config.productAds } + private func checkPasswordGeneratorFeature(from nimbus: FxNimbus) -> Bool { + return nimbus.features.passwordGeneratorFeature.value().enabled + } + private func checkProductBackInStockFakespotFeature(from nimbus: FxNimbus) -> Bool { let config = nimbus.features.shopping2023.value() diff --git a/firefox-ios/nimbus-features/passwordGeneratorFeature.yaml b/firefox-ios/nimbus-features/passwordGeneratorFeature.yaml new file mode 100644 index 000000000000..6efae6f53385 --- /dev/null +++ b/firefox-ios/nimbus-features/passwordGeneratorFeature.yaml @@ -0,0 +1,17 @@ +# The configuration for the passwordGeneratorFeature feature +features: + password-generator-feature: + description: Password Generator Feature + variables: + enabled: + description: If true, the password generator feature is enabled + type: Boolean + default: false + defaults: + - channel: beta + value: + enabled: false + - channel: developer + value: + enabled: false + diff --git a/firefox-ios/nimbus.fml.yaml b/firefox-ios/nimbus.fml.yaml index 8765fe727dee..8e0fca0f9507 100644 --- a/firefox-ios/nimbus.fml.yaml +++ b/firefox-ios/nimbus.fml.yaml @@ -29,6 +29,7 @@ include: - nimbus-features/nativeErrorPageFeature.yaml - nimbus-features/nightModeFeature.yaml - nimbus-features/onboardingFrameworkFeature.yaml + - nimbus-features/passwordGeneratorFeature.yaml - nimbus-features/reduxSearchSettingsFeature.yaml - nimbus-features/remoteTabManagement.yaml - nimbus-features/searchFeature.yaml From 8341f58519bcfd95f467f289e9f2ccc8ca56fda6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 25 Aug 2024 14:56:28 +0200 Subject: [PATCH 104/128] Refactor - auto update credential provider script (#21612) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- firefox-ios/Client/Assets/CC_Script/FormStateManager.sys.mjs | 1 - 1 file changed, 1 deletion(-) diff --git a/firefox-ios/Client/Assets/CC_Script/FormStateManager.sys.mjs b/firefox-ios/Client/Assets/CC_Script/FormStateManager.sys.mjs index 1e4662b2defe..6b5595b16024 100644 --- a/firefox-ios/Client/Assets/CC_Script/FormStateManager.sys.mjs +++ b/firefox-ios/Client/Assets/CC_Script/FormStateManager.sys.mjs @@ -26,7 +26,6 @@ export class FormStateManager { * @returns {Array | null} * Return target form's handler from content cache * (or return null if the information is not found in the cache). - * */ getFormHandler(element) { if (!element) { From a5b945d44f539b179ec96207d49d5973ebd59fa7 Mon Sep 17 00:00:00 2001 From: dicarobinho <61138287+dicarobinho@users.noreply.github.com> Date: Mon, 26 Aug 2024 09:17:57 +0300 Subject: [PATCH 105/128] =?UTF-8?q?Add=20FXIOS-9202=20=E2=81=83=20Enhanced?= =?UTF-8?q?=20Tracking=20Protection=20clear=20website=20data=20(#21456)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * FXIOS-9202 #20370 ⁃ Enhanced Tracking Protection clear website data Removed NSLog() * FXIOS-9202 #20370 ⁃ Enhanced Tracking Protection clear website data Removed Clear Data methods in order to use the existing ones. Tested clearCookiesAndSiteData() method. Fixed SwiftLint issue Added test files to the Xcode pbxproj file * Update firefox-ios/firefox-ios-tests/Tests/ClientTests/TrackingProtectionTests/TrackingProtectionModelTests.swift Co-authored-by: Cyndi Chin --------- Co-authored-by: Cyndi Chin --- firefox-ios/Client.xcodeproj/project.pbxproj | 8 ++++++ ...nhancedTrackingProtectionCoordinator.swift | 3 ++- .../TrackingProtectionModel.swift | 12 ++++++--- .../ClientTests/Mocks/MockDataCleaner.swift | 25 +++++++++++++++++++ .../TrackingProtectionModelTests.swift | 25 +++++++++++++++++++ 5 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockDataCleaner.swift create mode 100644 firefox-ios/firefox-ios-tests/Tests/ClientTests/TrackingProtectionTests/TrackingProtectionModelTests.swift diff --git a/firefox-ios/Client.xcodeproj/project.pbxproj b/firefox-ios/Client.xcodeproj/project.pbxproj index 596368e873a7..b8291b1458fa 100644 --- a/firefox-ios/Client.xcodeproj/project.pbxproj +++ b/firefox-ios/Client.xcodeproj/project.pbxproj @@ -19,6 +19,8 @@ 0AC659272BF35854005C614A /* FxAWebViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AC659262BF35854005C614A /* FxAWebViewModelTests.swift */; }; 0AC659292BF493CE005C614A /* MockFxAWebViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AC659282BF493CE005C614A /* MockFxAWebViewModel.swift */; }; 0AD3EEAC2C2485A7001044E5 /* ThemedCenteredTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AD3EEAB2C2485A7001044E5 /* ThemedCenteredTableViewCell.swift */; }; + 0AFF7F642C7784D600265214 /* MockDataCleaner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AFF7F632C7784D600265214 /* MockDataCleaner.swift */; }; + 0AFF7F662C7784F100265214 /* TrackingProtectionModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AFF7F652C7784F000265214 /* TrackingProtectionModelTests.swift */; }; 0B305E1B1E3A98A900BE0767 /* BookmarksTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B305E1A1E3A98A900BE0767 /* BookmarksTests.swift */; }; 0B3D670E1E09B90B00C1EFC7 /* AuthenticationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B3D670D1E09B90B00C1EFC7 /* AuthenticationTest.swift */; }; 0B54BD191B698B7C004C822C /* SuggestedSites.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B54BD181B698B7C004C822C /* SuggestedSites.swift */; }; @@ -2161,6 +2163,8 @@ 0AC659282BF493CE005C614A /* MockFxAWebViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockFxAWebViewModel.swift; sourceTree = ""; }; 0AD3EEAB2C2485A7001044E5 /* ThemedCenteredTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemedCenteredTableViewCell.swift; sourceTree = ""; }; 0AE9462E8A8E05CE07D4973D /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/InfoPlist.strings; sourceTree = ""; }; + 0AFF7F632C7784D600265214 /* MockDataCleaner.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockDataCleaner.swift; sourceTree = ""; }; + 0AFF7F652C7784F000265214 /* TrackingProtectionModelTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrackingProtectionModelTests.swift; sourceTree = ""; }; 0B305E1A1E3A98A900BE0767 /* BookmarksTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BookmarksTests.swift; sourceTree = ""; }; 0B3D670D1E09B90B00C1EFC7 /* AuthenticationTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthenticationTest.swift; sourceTree = ""; }; 0B414433840C8AA60829B6FB /* ms */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ms; path = ms.lproj/Intro.strings; sourceTree = ""; }; @@ -11005,6 +11009,7 @@ AB9CBC0A2C53B9A400102610 /* TrackingProtectionTests */ = { isa = PBXGroup; children = ( + 0AFF7F652C7784F000265214 /* TrackingProtectionModelTests.swift */, AB9CBC062C53B76400102610 /* TrackingProtectionStateTests.swift */, ); path = TrackingProtectionTests; @@ -11399,6 +11404,7 @@ 434CD57729F6FC4500A0D04B /* MockAppAuthenticator.swift */, 8AABBD022A001CBC0089941E /* MockApplicationHelper.swift */, 965C3C9729343445006499ED /* MockAppSessionManager.swift */, + 0AFF7F632C7784D600265214 /* MockDataCleaner.swift */, 8A5D1C9F2A30C9D7005AD35C /* MockAppSettingsDelegate.swift */, 8A5038132A5DFCE000A1B02A /* MockBrowserProfile.swift */, C8C3FEA029F973C40038E3BA /* MockBrowserViewController.swift */, @@ -15552,6 +15558,7 @@ 8A8482F02BE1602500F9007B /* MicrosurveyPromptStateTests.swift in Sources */, 8ADED7EC27691351009C19E6 /* CalendarExtensionsTests.swift in Sources */, 3B39EDBA1E16E18900EF029F /* CustomSearchEnginesTest.swift in Sources */, + 0AFF7F662C7784F100265214 /* TrackingProtectionModelTests.swift in Sources */, C80C11EE28B3C8B80062922A /* WallpaperMetadataTrackerTests.swift in Sources */, 8C8D8C7A2AA067AD00490D32 /* FakespotCoordinatorTests.swift in Sources */, C8E531CA29E5F7D300E03FEF /* URLScannerTests.swift in Sources */, @@ -15779,6 +15786,7 @@ 21FA8FAE2AE856460013B815 /* TabsCoordinatorTests.swift in Sources */, E1D8BC7A21FF7A0000B100BD /* TPStatsBlocklistsTests.swift in Sources */, 5AF6254328A57A4600A90253 /* HistoryHighlightsDataAdaptorTests.swift in Sources */, + 0AFF7F642C7784D600265214 /* MockDataCleaner.swift in Sources */, 8AE80BAD2891957C00BC12EA /* TopSitesDimensionTests.swift in Sources */, D82ED2641FEB3C420059570B /* DefaultSearchPrefsTests.swift in Sources */, 1D74FF502B2797EA00FF01D0 /* WindowManagerTests.swift in Sources */, diff --git a/firefox-ios/Client/Coordinators/EnhancedTrackingProtectionCoordinator.swift b/firefox-ios/Client/Coordinators/EnhancedTrackingProtectionCoordinator.swift index 4f4598f39896..6955eafdd876 100644 --- a/firefox-ios/Client/Coordinators/EnhancedTrackingProtectionCoordinator.swift +++ b/firefox-ios/Client/Coordinators/EnhancedTrackingProtectionCoordinator.swift @@ -45,7 +45,8 @@ class EnhancedTrackingProtectionCoordinator: BaseCoordinator, connectionSecure: connectionSecure, globalETPIsEnabled: FirefoxTabContentBlocker.isTrackingProtectionEnabled(prefs: profile.prefs), contentBlockerStatus: contentBlockerStatus, - contentBlockerStats: contentBlockerStats + contentBlockerStats: contentBlockerStats, + selectedTab: tabManager.selectedTab ) enhancedTrackingProtectionMenuVC = TrackingProtectionViewController(viewModel: etpViewModel, diff --git a/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionModel.swift b/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionModel.swift index ba6275e63637..72e6331db89e 100644 --- a/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionModel.swift +++ b/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionModel.swift @@ -20,6 +20,7 @@ class TrackingProtectionModel { let displayTitle: String let connectionSecure: Bool let globalETPIsEnabled: Bool + private var selectedTab: Tab? let clearCookiesButtonTitle: String = .Menu.EnhancedTrackingProtection.clearDataButtonTitle let clearCookiesButtonA11yId: String = AccessibilityIdentifiers.EnhancedTrackingProtection.MainScreen.clearCookiesButton @@ -104,13 +105,15 @@ class TrackingProtectionModel { connectionSecure: Bool, globalETPIsEnabled: Bool, contentBlockerStatus: BlockerStatus, - contentBlockerStats: TPPageStats?) { + contentBlockerStats: TPPageStats?, + selectedTab: Tab?) { self.url = url self.displayTitle = displayTitle self.connectionSecure = connectionSecure self.globalETPIsEnabled = globalETPIsEnabled self.contentBlockerStatus = contentBlockerStatus self.contentBlockerStats = contentBlockerStats + self.selectedTab = selectedTab } // MARK: - Helpers @@ -152,12 +155,15 @@ class TrackingProtectionModel { let confirmAction = UIAlertAction(title: clearCookiesAlertButton, style: .destructive) { [weak self] _ in - self?.clearCookiesAndSiteData() + self?.clearCookiesAndSiteData(cookiesClearable: CookiesClearable(), siteDataClearable: SiteDataClearable()) + self?.selectedTab?.webView?.reload() } alert.addAction(confirmAction) controller.present(alert, animated: true, completion: nil) } - func clearCookiesAndSiteData() { + func clearCookiesAndSiteData(cookiesClearable: Clearable, siteDataClearable: Clearable) { + _ = cookiesClearable.clear() + _ = siteDataClearable.clear() } } diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockDataCleaner.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockDataCleaner.swift new file mode 100644 index 000000000000..1258ecb24463 --- /dev/null +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockDataCleaner.swift @@ -0,0 +1,25 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/ + +import Foundation +import Shared +@testable import Client + +class MockCookiesClearable: CookiesClearable { + var isSucceed: Success? + + override func clear() -> Success { + isSucceed = succeed() + return succeed() + } +} + +class MockSiteDataClearable: SiteDataClearable { + var isSucceed: Success? + + override func clear() -> Success { + isSucceed = succeed() + return succeed() + } +} diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/TrackingProtectionTests/TrackingProtectionModelTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/TrackingProtectionTests/TrackingProtectionModelTests.swift new file mode 100644 index 000000000000..d800b7adbb14 --- /dev/null +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/TrackingProtectionTests/TrackingProtectionModelTests.swift @@ -0,0 +1,25 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/ + +import XCTest +@testable import Client + +final class TrackingProtectionModelTests: XCTestCase { + func testClearCookiesAndSiteData() { + let cookiesClearable = MockCookiesClearable() + let siteDataClearable = MockSiteDataClearable() + + let trackingProtectionModel = TrackingProtectionModel(url: URL(string: "https://www.google.com")!, + displayTitle: "TitleTest", + connectionSecure: false, + globalETPIsEnabled: false, + contentBlockerStatus: .disabled, + contentBlockerStats: nil, + selectedTab: nil) + trackingProtectionModel.clearCookiesAndSiteData(cookiesClearable: cookiesClearable, + siteDataClearable: siteDataClearable) + XCTAssertNotNil(cookiesClearable.isSucceed) + XCTAssertNotNil(siteDataClearable.isSucceed) + } +} From 8f5728248e9aa46019415d366f55f47320ef2b59 Mon Sep 17 00:00:00 2001 From: dicarobinho <61138287+dicarobinho@users.noreply.github.com> Date: Mon, 26 Aug 2024 09:20:13 +0300 Subject: [PATCH 106/128] =?UTF-8?q?Bugfix=20FXIOS-9758=20=E2=81=83=20Botto?= =?UTF-8?q?m=20modal=20view(s)=20are=20not=20visible=20(#21553)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * FXIOS-9758 #21429 ⁃ Bottom modal view(s) are not visible Improvement for calculating Tracking Protection modal height Removed. extensions for UILabel and UIButton --- ...nhancedTrackingProtectionCoordinator.swift | 1 + .../TrackingProtectionViewController.swift | 42 ++++++++++++------- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/firefox-ios/Client/Coordinators/EnhancedTrackingProtectionCoordinator.swift b/firefox-ios/Client/Coordinators/EnhancedTrackingProtectionCoordinator.swift index 6955eafdd876..c79f32ddcb45 100644 --- a/firefox-ios/Client/Coordinators/EnhancedTrackingProtectionCoordinator.swift +++ b/firefox-ios/Client/Coordinators/EnhancedTrackingProtectionCoordinator.swift @@ -75,6 +75,7 @@ class EnhancedTrackingProtectionCoordinator: BaseCoordinator, sheetPresentationController.prefersScrollingExpandsWhenScrolledToEdge = true sheetPresentationController.preferredCornerRadius = TPMenuUX.UX.modalMenuCornerRadius } + enhancedTrackingProtectionMenuVC.asPopover = true router.present(enhancedTrackingProtectionMenuVC, animated: true, completion: nil) } else { enhancedTrackingProtectionMenuVC.asPopover = true diff --git a/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionViewController.swift b/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionViewController.swift index 8b1b32b0be0c..630a8cf1ba01 100644 --- a/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionViewController.swift +++ b/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionViewController.swift @@ -18,7 +18,7 @@ struct TPMenuUX { struct UX { static let baseCellHeight: CGFloat = 44 - static let popoverTopDistance: CGFloat = 20 + static let popoverTopDistance: CGFloat = 16 static let horizontalMargin: CGFloat = 16 static let viewCornerRadius: CGFloat = 8 static let headerLabelDistance: CGFloat = 2.0 @@ -34,7 +34,9 @@ struct TPMenuUX { static let faviconCornerRadius: CGFloat = 5 static let scrollContentHorizontalPadding: CGFloat = 16 - static let trackersLabelConstraintConstant = 11.0 + static let trackersLabelConstraintConstant = 16.0 + static let connectionStatusLabelConstraintConstant = 16.0 + static let toggleLabelsContainerConstraintConstant = 16.0 static let clearDataButtonCornerRadius: CGFloat = 12 static let clearDataButtonBorderWidth: CGFloat = 1 @@ -337,8 +339,8 @@ class TrackingProtectionViewController: UIViewController, Themeable, Notifiable, private func setupView() { constraints.removeAll() - setupContentView() setupHeaderView() + setupContentView() setupConnectionHeaderView() setupBlockedTrackersView() setupConnectionStatusView() @@ -356,7 +358,7 @@ class TrackingProtectionViewController: UIViewController, Themeable, Notifiable, view.addSubview(scrollView) let scrollViewConstraints = [ - scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + scrollView.topAnchor.constraint(equalTo: headerContainer.bottomAnchor), scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor), scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor), scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor) @@ -382,17 +384,17 @@ class TrackingProtectionViewController: UIViewController, Themeable, Notifiable, headerLabelsContainer.addArrangedSubview(siteDomainLabel) headerContainer.addSubviews(favicon, headerLabelsContainer, closeButton) - baseView.addSubview(headerContainer) + view.addSubview(headerContainer) faviconHeightConstraint = favicon.heightAnchor.constraint(equalToConstant: TPMenuUX.UX.faviconImageSize) faviconWidthConstraint = favicon.widthAnchor.constraint(equalToConstant: TPMenuUX.UX.faviconImageSize) let topDistance = asPopover ? TPMenuUX.UX.popoverTopDistance : 0 let headerConstraints = [ - headerContainer.leadingAnchor.constraint(equalTo: baseView.leadingAnchor), - headerContainer.trailingAnchor.constraint(equalTo: baseView.trailingAnchor), + headerContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor), + headerContainer.trailingAnchor.constraint(equalTo: view.trailingAnchor), headerContainer.topAnchor.constraint( - equalTo: baseView.topAnchor, + equalTo: view.safeAreaLayoutGuide.topAnchor, constant: topDistance ), @@ -454,8 +456,8 @@ class TrackingProtectionViewController: UIViewController, Themeable, Notifiable, equalTo: view.trailingAnchor, constant: -TPMenuUX.UX.horizontalMargin ), - connectionDetailsHeaderView.topAnchor.constraint(equalTo: headerContainer.bottomAnchor, - constant: 0), + connectionDetailsHeaderView.topAnchor.constraint(equalTo: baseView.topAnchor, + constant: TPMenuUX.UX.connectionDetailsHeaderMargins), // Content connectionDetailsContentView.leadingAnchor.constraint( equalTo: connectionDetailsHeaderView.leadingAnchor, @@ -609,8 +611,10 @@ class TrackingProtectionViewController: UIViewController, Themeable, Notifiable, equalTo: connectionStatusImage.trailingAnchor, constant: TPMenuUX.UX.horizontalMargin ), - connectionStatusLabel.topAnchor.constraint(equalTo: connectionView.topAnchor, constant: 11), - connectionStatusLabel.bottomAnchor.constraint(equalTo: connectionView.bottomAnchor, constant: -11), + connectionStatusLabel.topAnchor.constraint(equalTo: connectionView.topAnchor, + constant: TPMenuUX.UX.connectionStatusLabelConstraintConstant), + connectionStatusLabel.bottomAnchor.constraint(equalTo: connectionView.bottomAnchor, + constant: -TPMenuUX.UX.connectionStatusLabelConstraintConstant), connectionStatusLabel.trailingAnchor.constraint( equalTo: connectionDetailArrow.leadingAnchor, constant: TPMenuUX.UX.horizontalMargin @@ -665,11 +669,11 @@ class TrackingProtectionViewController: UIViewController, Themeable, Notifiable, ), toggleLabelsContainer.topAnchor.constraint( equalTo: toggleView.topAnchor, - constant: 11 + constant: TPMenuUX.UX.toggleLabelsContainerConstraintConstant ), toggleLabelsContainer.bottomAnchor.constraint( equalTo: toggleView.bottomAnchor, - constant: -11 + constant: -TPMenuUX.UX.toggleLabelsContainerConstraintConstant ), toggleSwitch.centerYAnchor.constraint(equalTo: toggleView.centerYAnchor), @@ -816,6 +820,16 @@ class TrackingProtectionViewController: UIViewController, Themeable, Notifiable, lockImageHeightConstraint?.constant = min(UIFontMetrics.default.scaledValue(for: iconSize), 2 * iconSize) connectionArrowHeightConstraint?.constant = min(UIFontMetrics.default.scaledValue(for: iconSize), 2 * iconSize) + if #available(iOS 16.0, *), UIDevice.current.userInterfaceIdiom == .phone { + headerContainer.layoutIfNeeded() + scrollView.layoutIfNeeded() + let contentHeight = headerContainer.frame.height + scrollView.contentSize.height + let customDetent = UISheetPresentationController.Detent.custom { context in + return contentHeight + } + self.sheetPresentationController?.detents = [customDetent] + } + view.setNeedsLayout() view.layoutIfNeeded() } From 0c056628cd1af72d60ae36ce8c8c346706f7e83a Mon Sep 17 00:00:00 2001 From: Winnie Teichmann <4530+thatswinnie@users.noreply.github.com> Date: Mon, 26 Aug 2024 09:11:15 +0100 Subject: [PATCH 107/128] Refactor FXIOS-9737 Add badge to tabs icon when in private mode (#21594) --- .../Browser/Toolbars/Redux/ToolbarMiddleware.swift | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift index 5fd26a46ac62..8c1218e0085c 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift @@ -512,7 +512,7 @@ final class ToolbarMiddleware: FeatureFlaggable { let menuBadgeImageName = isShowMenuWarningAction ? action.badgeImageName : toolbarState.badgeImageName let maskImageName = isShowMenuWarningAction ? action.maskImageName : toolbarState.maskImageName - actions.append(contentsOf: [tabsAction(numberOfTabs: numberOfTabs), + actions.append(contentsOf: [tabsAction(numberOfTabs: numberOfTabs, isPrivateMode: toolbarState.isPrivateMode), menuAction(badgeImageName: menuBadgeImageName, maskImageName: maskImageName)]) return actions @@ -672,7 +672,9 @@ final class ToolbarMiddleware: FeatureFlaggable { backAction(enabled: canGoBack), forwardAction(enabled: canGoForward), middleAction, - tabsAction(numberOfTabs: numberOfTabs, isShowingTopTabs: isShowingTopTabs), + tabsAction(numberOfTabs: numberOfTabs, + isPrivateMode: toolbarState.isPrivateMode, + isShowingTopTabs: isShowingTopTabs), menuAction(badgeImageName: menuBadgeImageName, maskImageName: maskImageName) ] @@ -720,10 +722,14 @@ final class ToolbarMiddleware: FeatureFlaggable { a11yId: AccessibilityIdentifiers.Toolbar.forwardButton) } - private func tabsAction(numberOfTabs: Int = 1, isShowingTopTabs: Bool = false) -> ToolbarActionState { + private func tabsAction(numberOfTabs: Int = 1, + isPrivateMode: Bool = false, + isShowingTopTabs: Bool = false) -> ToolbarActionState { return ToolbarActionState( actionType: .tabs, iconName: StandardImageIdentifiers.Large.tab, + badgeImageName: isPrivateMode ? StandardImageIdentifiers.Medium.privateModeCircleFillPurple : nil, + maskImageName: isPrivateMode ? ImageIdentifiers.badgeMask : nil, numberOfTabs: numberOfTabs, isShowingTopTabs: isShowingTopTabs, isEnabled: true, From e77b59711239544003c6540e0a9de10f6302dc8e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 26 Aug 2024 08:03:50 -0400 Subject: [PATCH 108/128] Localize [v131] String import 2024-08-26 (#21615) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- firefox-ios/Client.xcodeproj/project.pbxproj | 100 ++++++++ .../EnhancedTrackingProtection.strings | 6 +- .../bs.lproj/NativeErrorPage.strings | 15 ++ .../bs.lproj/Settings.strings | 12 + .../EnhancedTrackingProtection.strings | 3 +- .../co.lproj/CredentialProvider.strings | 2 +- .../EnhancedTrackingProtection.strings | 9 +- .../co.lproj/Microsurvey.strings | 3 + .../co.lproj/NativeErrorPage.strings | 15 ++ .../co.lproj/Settings.strings | 12 + .../Supporting Files/co.lproj/Toolbar.strings | 3 + .../EnhancedTrackingProtection.strings | 6 +- .../cs.lproj/NativeErrorPage.strings | 15 ++ .../cs.lproj/Settings.strings | 12 + .../EnhancedTrackingProtection.strings | 6 +- .../cy.lproj/NativeErrorPage.strings | 15 ++ .../cy.lproj/Settings.strings | 12 + .../EnhancedTrackingProtection.strings | 6 +- .../da.lproj/NativeErrorPage.strings | 15 ++ .../da.lproj/Settings.strings | 12 + .../EnhancedTrackingProtection.strings | 6 +- .../de.lproj/NativeErrorPage.strings | 15 ++ .../de.lproj/Settings.strings | 12 + .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 6 +- .../el.lproj/NativeErrorPage.strings | 15 ++ .../el.lproj/Settings.strings | 12 + .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 6 +- .../en-GB.lproj/NativeErrorPage.strings | 15 ++ .../en-GB.lproj/Settings.strings | 12 + .../EnhancedTrackingProtection.strings | 6 +- .../en-US.lproj/NativeErrorPage.strings | 15 ++ .../en-US.lproj/Settings.strings | 12 + .../eo.lproj/EditAddress.strings | 141 ++++++++++++ .../EnhancedTrackingProtection.strings | 21 +- .../eo.lproj/Microsurvey.strings | 3 + .../eo.lproj/NativeErrorPage.strings | 15 ++ .../eo.lproj/PasswordAutofill.strings | 3 + .../eo.lproj/ScanQRCode.strings | 9 + .../eo.lproj/Settings.strings | 12 + .../Supporting Files/eo.lproj/Toolbar.strings | 6 + .../EnhancedTrackingProtection.strings | 6 +- .../es-AR.lproj/NativeErrorPage.strings | 15 ++ .../es-AR.lproj/Settings.strings | 12 + .../EnhancedTrackingProtection.strings | 6 +- .../es-CL.lproj/NativeErrorPage.strings | 9 + .../es-CL.lproj/Settings.strings | 12 + .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 6 +- .../fi.lproj/NativeErrorPage.strings | 15 ++ .../fi.lproj/Settings.strings | 12 + .../EnhancedTrackingProtection.strings | 6 +- .../fr.lproj/NativeErrorPage.strings | 15 ++ .../fr.lproj/Settings.strings | 12 + .../EnhancedTrackingProtection.strings | 6 +- .../he.lproj/NativeErrorPage.strings | 15 ++ .../he.lproj/Settings.strings | 12 + .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 6 +- .../hsb.lproj/NativeErrorPage.strings | 15 ++ .../hsb.lproj/Settings.strings | 12 + .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 6 +- .../ia.lproj/NativeErrorPage.strings | 15 ++ .../ia.lproj/Settings.strings | 12 + .../EnhancedTrackingProtection.strings | 6 +- .../is.lproj/NativeErrorPage.strings | 15 ++ .../is.lproj/Settings.strings | 12 + .../EnhancedTrackingProtection.strings | 6 +- .../it.lproj/NativeErrorPage.strings | 15 ++ .../it.lproj/Settings.strings | 12 + .../EnhancedTrackingProtection.strings | 6 +- .../ja.lproj/NativeErrorPage.strings | 6 + .../EnhancedTrackingProtection.strings | 9 +- .../kab.lproj/Microsurvey.strings | 3 + .../kab.lproj/NativeErrorPage.strings | 9 + .../kab.lproj/Settings.strings | 9 + .../kab.lproj/Toolbar.strings | 3 + .../EnhancedTrackingProtection.strings | 6 +- .../kk.lproj/NativeErrorPage.strings | 15 ++ .../kk.lproj/Settings.strings | 12 + .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 6 +- .../EnhancedTrackingProtection.strings | 6 +- .../nn.lproj/NativeErrorPage.strings | 15 ++ .../nn.lproj/Settings.strings | 12 + .../EnhancedTrackingProtection.strings | 6 +- .../pa-IN.lproj/NativeErrorPage.strings | 15 ++ .../pa-IN.lproj/Settings.strings | 12 + .../EnhancedTrackingProtection.strings | 9 +- .../pl.lproj/Microsurvey.strings | 3 + .../pl.lproj/NativeErrorPage.strings | 15 ++ .../pl.lproj/Settings.strings | 12 + .../Supporting Files/pl.lproj/Toolbar.strings | 3 + .../EnhancedTrackingProtection.strings | 6 +- .../pt-BR.lproj/NativeErrorPage.strings | 15 ++ .../pt-BR.lproj/Settings.strings | 12 + .../EnhancedTrackingProtection.strings | 6 +- .../pt-PT.lproj/NativeErrorPage.strings | 15 ++ .../pt-PT.lproj/Settings.strings | 12 + .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 6 +- .../ru.lproj/NativeErrorPage.strings | 15 ++ .../ru.lproj/Settings.strings | 12 + .../EnhancedTrackingProtection.strings | 6 +- .../sk.lproj/NativeErrorPage.strings | 15 ++ .../sk.lproj/Settings.strings | 12 + .../EnhancedTrackingProtection.strings | 9 +- .../sl.lproj/Microsurvey.strings | 3 + .../sl.lproj/NativeErrorPage.strings | 15 ++ .../sl.lproj/Onboarding.strings | 6 + .../sl.lproj/Settings.strings | 18 ++ .../sl.lproj/Shopping.strings | 216 ++++++++++++++++++ .../Supporting Files/sl.lproj/Toolbar.strings | 3 + .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 6 +- .../sv.lproj/NativeErrorPage.strings | 15 ++ .../sv.lproj/Settings.strings | 12 + .../EnhancedTrackingProtection.strings | 3 +- .../EnhancedTrackingProtection.strings | 6 +- .../tr.lproj/NativeErrorPage.strings | 9 + .../tr.lproj/Settings.strings | 12 + .../EnhancedTrackingProtection.strings | 6 +- .../ug.lproj/NativeErrorPage.strings | 15 ++ .../ug.lproj/Settings.strings | 12 + .../uk.lproj/ActivityStream.strings | 3 + .../uk.lproj/AddressToolbar.strings | 3 + .../uk.lproj/CustomizeFirefoxHome.strings | 3 + .../uk.lproj/EditAddress.strings | 96 ++++++++ .../EnhancedTrackingProtection.strings | 30 +++ .../uk.lproj/Microsurvey.strings | 15 ++ .../uk.lproj/PasswordAutofill.strings | 3 + .../uk.lproj/ScanQRCode.strings | 6 + .../Supporting Files/uk.lproj/Toolbar.strings | 6 + .../EnhancedTrackingProtection.strings | 6 +- .../vi.lproj/NativeErrorPage.strings | 15 ++ .../vi.lproj/Settings.strings | 12 + .../EnhancedTrackingProtection.strings | 6 +- .../zh-CN.lproj/NativeErrorPage.strings | 15 ++ .../zh-CN.lproj/Settings.strings | 12 + .../EnhancedTrackingProtection.strings | 6 +- .../zh-TW.lproj/NativeErrorPage.strings | 15 ++ .../zh-TW.lproj/Settings.strings | 12 + .../Shared/co.lproj/Localizable.strings | 2 +- .../Shared/co.lproj/LoginManager.strings | 4 +- .../Shared/eo.lproj/Localizable.strings | 2 +- .../Shared/uk.lproj/Localizable.strings | 9 + firefox-ios/Shared/uk.lproj/Menu.strings | 6 + 153 files changed, 1818 insertions(+), 107 deletions(-) create mode 100644 firefox-ios/Shared/Supporting Files/bs.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/co.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/cs.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/cy.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/da.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/de.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/el.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/en-GB.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/en-US.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/eo.lproj/EditAddress.strings create mode 100644 firefox-ios/Shared/Supporting Files/eo.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/eo.lproj/ScanQRCode.strings create mode 100644 firefox-ios/Shared/Supporting Files/eo.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/es-AR.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/es-CL.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/fi.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/fr.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/he.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/hsb.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/ia.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/is.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/it.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/ja.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/kab.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/kk.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/nn.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/pa-IN.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/pl.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/pt-BR.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/pt-PT.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/ru.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/sk.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/sl.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/sv.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/tr.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/ug.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/uk.lproj/ActivityStream.strings create mode 100644 firefox-ios/Shared/Supporting Files/uk.lproj/AddressToolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/uk.lproj/EditAddress.strings create mode 100644 firefox-ios/Shared/Supporting Files/uk.lproj/EnhancedTrackingProtection.strings create mode 100644 firefox-ios/Shared/Supporting Files/uk.lproj/ScanQRCode.strings create mode 100644 firefox-ios/Shared/Supporting Files/uk.lproj/Toolbar.strings create mode 100644 firefox-ios/Shared/Supporting Files/vi.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/zh-CN.lproj/NativeErrorPage.strings create mode 100644 firefox-ios/Shared/Supporting Files/zh-TW.lproj/NativeErrorPage.strings diff --git a/firefox-ios/Client.xcodeproj/project.pbxproj b/firefox-ios/Client.xcodeproj/project.pbxproj index b8291b1458fa..aaf24cb0f202 100644 --- a/firefox-ios/Client.xcodeproj/project.pbxproj +++ b/firefox-ios/Client.xcodeproj/project.pbxproj @@ -364,6 +364,7 @@ 437A857827E43FE100E42764 /* FxAWebViewTelemetry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 437A857727E43FE100E42764 /* FxAWebViewTelemetry.swift */; }; 437A9B682681256800FB41C1 /* LegacyInactiveTabCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 437A9B672681256800FB41C1 /* LegacyInactiveTabCell.swift */; }; 437A9B6A2681257F00FB41C1 /* LegacyInactiveTabViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 437A9B692681257F00FB41C1 /* LegacyInactiveTabViewModel.swift */; }; + 437AE3102C7C9A0C0053F7F3 /* NativeErrorPage.strings in Resources */ = {isa = PBXBuildFile; fileRef = 437AE30E2C7C9A0C0053F7F3 /* NativeErrorPage.strings */; }; 438FE8642988ABA600155B10 /* CreditCardTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 438FE8632988ABA600155B10 /* CreditCardTableViewController.swift */; }; 43903A892C20502A00ACF76E /* ActivityStream.strings in Resources */ = {isa = PBXBuildFile; fileRef = 43903A872C20502A00ACF76E /* ActivityStream.strings */; }; 43903A8C2C20502A00ACF76E /* AddressToolbar.strings in Resources */ = {isa = PBXBuildFile; fileRef = 43903A8A2C20502A00ACF76E /* AddressToolbar.strings */; }; @@ -2960,6 +2961,7 @@ 43045C9C29E428A800B5BD9B /* si */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = si; path = si.lproj/ResearchSurface.strings; sourceTree = ""; }; 43045C9D29E428A800B5BD9B /* si */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = si; path = si.lproj/Settings.strings; sourceTree = ""; }; 43045C9E29E428A800B5BD9B /* si */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = si; path = si.lproj/SnackBar.strings; sourceTree = ""; }; + 4304BD432C7C9DCB0063AF05 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/NativeErrorPage.strings; sourceTree = ""; }; 4304EDF32C60EABA00F3C9DE /* cy */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cy; path = cy.lproj/Toolbar.strings; sourceTree = ""; }; 43050A002ACAE09E002684A4 /* pa-IN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pa-IN"; path = "pa-IN.lproj/Share.strings"; sourceTree = ""; }; 430514F52AD4195A00188114 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/Share.strings; sourceTree = ""; }; @@ -2983,6 +2985,7 @@ 4307A24229F69BC400570352 /* is */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = is; path = is.lproj/Notification.strings; sourceTree = ""; }; 4307A24329F69BC400570352 /* is */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = is; path = is.lproj/ZoomPageBar.strings; sourceTree = ""; }; 4308262A2BF506EC002C58F9 /* bs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bs; path = bs.lproj/Microsurvey.strings; sourceTree = ""; }; + 430832542C7C9E4100F58087 /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/NativeErrorPage.strings; sourceTree = ""; }; 43087EE12BF50875005EAA6C /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/Microsurvey.strings; sourceTree = ""; }; 4308A4E52A52E38C001D652E /* be */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = be; path = be.lproj/SelectCreditCard.strings; sourceTree = ""; }; 430901D52C3C00DB00D5F3AC /* eu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eu; path = eu.lproj/ActivityStream.strings; sourceTree = ""; }; @@ -3038,6 +3041,7 @@ 430E7BBF293E0D2B005A10AD /* zh-CN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-CN"; path = "zh-CN.lproj/TabsTray.strings"; sourceTree = ""; }; 430E91272B5549E300F90C14 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/TabToolbar.strings; sourceTree = ""; }; 430E9CD329225D8300DC418A /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/SearchHeaderTitle.strings; sourceTree = ""; }; + 430EC8982C7C9B5100759193 /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/NativeErrorPage.strings; sourceTree = ""; }; 430EE26429BA6968009B5023 /* es-CL */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-CL"; path = "es-CL.lproj/EngagementNotification.strings"; sourceTree = ""; }; 430EE26529BA6968009B5023 /* es-CL */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-CL"; path = "es-CL.lproj/Onboarding.strings"; sourceTree = ""; }; 430EE26629BA6968009B5023 /* es-CL */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-CL"; path = "es-CL.lproj/ResearchSurface.strings"; sourceTree = ""; }; @@ -3226,6 +3230,7 @@ 431D44862AEFC97A00B92311 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Shopping.strings; sourceTree = ""; }; 431D65DB292B94F800BB9A90 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/SearchHeaderTitle.strings; sourceTree = ""; }; 431D82792C57B3F600062D71 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Toolbar.strings; sourceTree = ""; }; + 431D8FEE2C7C9B61001E041F /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/NativeErrorPage.strings; sourceTree = ""; }; 431DACF12A24BF0C00D7CE85 /* en-US */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-US"; path = "en-US.lproj/DisplayCard.strings"; sourceTree = ""; }; 431DE38F2B023BC600BF06E3 /* eo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eo; path = eo.lproj/Shopping.strings; sourceTree = ""; }; 431DF6C52C20532100ADD05A /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/ActivityStream.strings; sourceTree = ""; }; @@ -3271,6 +3276,7 @@ 43211DCD2C3C045A00E4CA4D /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/EditAddress.strings; sourceTree = ""; }; 43211DCE2C3C045A00E4CA4D /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/ScanQRCode.strings; sourceTree = ""; }; 43211E6B2C57B11F003F9FAF /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = he.lproj/Toolbar.strings; sourceTree = ""; }; + 4321F0522C7C9BE00001D0DD /* hsb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hsb; path = hsb.lproj/NativeErrorPage.strings; sourceTree = ""; }; 4321FAB82B8CA9A70046DCA0 /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/KeyboardAccessory.strings; sourceTree = ""; }; 4321FAB92B8CA9A70046DCA0 /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/PasswordAutofill.strings; sourceTree = ""; }; 4322680229225CA3008F8C47 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/SearchHeaderTitle.strings; sourceTree = ""; }; @@ -3486,6 +3492,7 @@ 433429FC29BA6CB1005B05B0 /* zh-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-TW"; path = "zh-TW.lproj/ResearchSurface.strings"; sourceTree = ""; }; 43349476294745560027B85C /* sq */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sq; path = sq.lproj/Alerts.strings; sourceTree = ""; }; 43349477294745560027B85C /* sq */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sq; path = sq.lproj/TabsTray.strings; sourceTree = ""; }; + 4334C4F02C7C9EDE00FBEFCF /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/NativeErrorPage.strings; sourceTree = ""; }; 4334CA5C2BB195DE00B29D5B /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/BottomSheet.strings; sourceTree = ""; }; 4334DC2B29225A0B0064F9CD /* es-AR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-AR"; path = "es-AR.lproj/SearchHeaderTitle.strings"; sourceTree = ""; }; 4335A79E2B554A630087D279 /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = he.lproj/TabToolbar.strings; sourceTree = ""; }; @@ -3597,6 +3604,7 @@ 433FD5CD2A52E55400E7B4CB /* is */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = is; path = is.lproj/SelectCreditCard.strings; sourceTree = ""; }; 433FF82028BCD74B006A70C8 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/JumpBackIn.strings; sourceTree = ""; }; 433FF82128BCD74B006A70C8 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/ToolbarLocation.strings; sourceTree = ""; }; + 43400BC22C7C9C7100D8ECE9 /* kab */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kab; path = kab.lproj/NativeErrorPage.strings; sourceTree = ""; }; 434073A929E4271900458D21 /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = "hu.lproj/Edit Card.strings"; sourceTree = ""; }; 434094D1293E0B6000CAD2F5 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Alerts.strings; sourceTree = ""; }; 434094D2293E0B6000CAD2F5 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/TabsTray.strings; sourceTree = ""; }; @@ -3643,6 +3651,7 @@ 4344D02F292259CE00B12BF8 /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/SearchHeaderTitle.strings"; sourceTree = ""; }; 4345055729E4289200F137B6 /* sat-Olck */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "sat-Olck"; path = "sat-Olck.lproj/Settings.strings"; sourceTree = ""; }; 4345441C26D2E52600D5EEAA /* SearchTermGroupsUtility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchTermGroupsUtility.swift; sourceTree = ""; }; + 4345E88F2C7C9A5B00FC0D7D /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/NativeErrorPage.strings; sourceTree = ""; }; 43464A7329E4264400C3CA87 /* es-CL */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-CL"; path = "es-CL.lproj/Edit Card.strings"; sourceTree = ""; }; 4346FF07295BA6A200F4D220 /* CreditCardSettingsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CreditCardSettingsViewController.swift; sourceTree = ""; }; 4347022C2AC1A19200BEB809 /* dsb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = dsb; path = dsb.lproj/Share.strings; sourceTree = ""; }; @@ -3717,8 +3726,10 @@ 434F05982A0BCD36008B1057 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/FirefoxSync.strings; sourceTree = ""; }; 434F05992A0BCD36008B1057 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Upgrade.strings; sourceTree = ""; }; 434F78E429225CD10037862C /* si */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = si; path = si.lproj/SearchHeaderTitle.strings; sourceTree = ""; }; + 434FE6142C7C9C7F00C44560 /* kk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kk; path = kk.lproj/NativeErrorPage.strings; sourceTree = ""; }; 434FFA2E2AEFC8EE008CAD12 /* sl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sl; path = sl.lproj/Shopping.strings; sourceTree = ""; }; 434FFF292ACAE1C000680A93 /* zh-CN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-CN"; path = "zh-CN.lproj/Share.strings"; sourceTree = ""; }; + 43500A6B2C7C9EFB008E385F /* zh-CN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-CN"; path = "zh-CN.lproj/NativeErrorPage.strings"; sourceTree = ""; }; 43509CB3291BF65400DF631E /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/JumpBackIn.strings; sourceTree = ""; }; 43509CB4291BF65400DF631E /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/ToolbarLocation.strings; sourceTree = ""; }; 4350E75F2AC1A19C004BA97D /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/Share.strings; sourceTree = ""; }; @@ -3753,6 +3764,7 @@ 4353DE762AC1A267005E189E /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = he.lproj/TabLocation.strings; sourceTree = ""; }; 4354415E29EF0682004EDDAF /* eu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eu; path = "eu.lproj/Edit Card.strings"; sourceTree = ""; }; 4354485A2B0B767600F22F17 /* eu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eu; path = eu.lproj/FirefoxHomepage.strings; sourceTree = ""; }; + 43548AB92C7C9A6A0004C846 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/NativeErrorPage.strings; sourceTree = ""; }; 43548D222A2DFAB400E28766 /* kk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kk; path = kk.lproj/Footer.strings; sourceTree = ""; }; 43548D232A2DFAB400E28766 /* kk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kk; path = kk.lproj/RememberCard.strings; sourceTree = ""; }; 43548D242A2DFAB400E28766 /* kk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kk; path = kk.lproj/UpdateCard.strings; sourceTree = ""; }; @@ -3929,6 +3941,7 @@ 4361333D2A091002009C8BBC /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Notification.strings; sourceTree = ""; }; 4361333E2A091002009C8BBC /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Settings.strings; sourceTree = ""; }; 4361333F2A091002009C8BBC /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/SnackBar.strings; sourceTree = ""; }; + 4361916A2C7C9D72005B31E3 /* pa-IN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pa-IN"; path = "pa-IN.lproj/NativeErrorPage.strings"; sourceTree = ""; }; 4361DF292C453DB200CE1295 /* sat-Olck */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "sat-Olck"; path = "sat-Olck.lproj/BottomSheet.strings"; sourceTree = ""; }; 4361DF2A2C453DB200CE1295 /* sat-Olck */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "sat-Olck"; path = "sat-Olck.lproj/ContextualHints.strings"; sourceTree = ""; }; 4361DF2B2C453DB200CE1295 /* sat-Olck */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "sat-Olck"; path = "sat-Olck.lproj/CredentialProvider.strings"; sourceTree = ""; }; @@ -3946,6 +3959,7 @@ 4363AC042A0BCE1D00A18A25 /* zh-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-TW"; path = "zh-TW.lproj/Upgrade.strings"; sourceTree = ""; }; 4363B6662BE8F3C2004D0CED /* kk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kk; path = kk.lproj/Microsurvey.strings; sourceTree = ""; }; 4363FDF12AEFC70A00FC80F2 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Shopping.strings; sourceTree = ""; }; + 4364018E2C7C9AE700FF64C6 /* es-AR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-AR"; path = "es-AR.lproj/NativeErrorPage.strings"; sourceTree = ""; }; 436403C428EAFBD6008A7F9B /* kk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kk; path = kk.lproj/JumpBackIn.strings; sourceTree = ""; }; 436403C528EAFBD6008A7F9B /* kk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kk; path = kk.lproj/ToolbarLocation.strings; sourceTree = ""; }; 43645E3629BA68D900CE6033 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/EngagementNotification.strings; sourceTree = ""; }; @@ -4112,6 +4126,7 @@ 436F42FD2A52E6E100E4C2A2 /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/SelectCreditCard.strings; sourceTree = ""; }; 436F68302AE68E3700BF46C9 /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/Share.strings; sourceTree = ""; }; 436F84692A4070C800279DAE /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/Onboarding.strings; sourceTree = ""; }; + 436FC4912C7C9D810083D324 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/NativeErrorPage.strings; sourceTree = ""; }; 436FC6A82A3734F30010789D /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Footer.strings; sourceTree = ""; }; 436FC6A92A3734F30010789D /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/RememberCard.strings; sourceTree = ""; }; 436FC6AA2A3734F40010789D /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/UpdateCard.strings; sourceTree = ""; }; @@ -4149,6 +4164,7 @@ 437327D62B305F6E0090FCBC /* dsb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = dsb; path = dsb.lproj/FirefoxLogins.strings; sourceTree = ""; }; 437327D72B305F6E0090FCBC /* dsb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = dsb; path = dsb.lproj/LoginsHelper.strings; sourceTree = ""; }; 437330442B554BE600BB1AFC /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/TabToolbar.strings"; sourceTree = ""; }; + 4373440E2C7C9AF500457D4D /* es-CL */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-CL"; path = "es-CL.lproj/NativeErrorPage.strings"; sourceTree = ""; }; 43736FDD2A406F2900546F4A /* eu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eu; path = eu.lproj/Footer.strings; sourceTree = ""; }; 43736FDE2A406F2900546F4A /* eu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eu; path = eu.lproj/RememberCard.strings; sourceTree = ""; }; 43736FDF2A406F2900546F4A /* eu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eu; path = eu.lproj/UpdateCard.strings; sourceTree = ""; }; @@ -4242,6 +4258,7 @@ 437AA7E72C32C753001A7826 /* kab */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kab; path = kab.lproj/EnhancedTrackingProtection.strings; sourceTree = ""; }; 437ABC202B8393050027444C /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/KeyboardAccessory.strings"; sourceTree = ""; }; 437ABC212B8393050027444C /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/PasswordAutofill.strings"; sourceTree = ""; }; + 437AE30F2C7C9A0C0053F7F3 /* bs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bs; path = bs.lproj/NativeErrorPage.strings; sourceTree = ""; }; 437B0B2C2A6E941500DD9F66 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/Alert.strings; sourceTree = ""; }; 437B0B2D2A6E941500DD9F66 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/Alerts.strings; sourceTree = ""; }; 437B0B2E2A6E941500DD9F66 /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/CustomizeFirefoxHome.strings; sourceTree = ""; }; @@ -4282,6 +4299,7 @@ 437CC8E02BE8F1D100CB4385 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Microsurvey.strings; sourceTree = ""; }; 437CCDC82A124D7000A10106 /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/FirefoxSync.strings; sourceTree = ""; }; 437CCDC92A124D7000A10106 /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/Upgrade.strings; sourceTree = ""; }; + 437CD9FF2C7C9A8B00A34E3E /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/NativeErrorPage.strings; sourceTree = ""; }; 437CFF60293E0AD6001F1948 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Alerts.strings; sourceTree = ""; }; 437CFF61293E0AD6001F1948 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/TabsTray.strings; sourceTree = ""; }; 437D59F62AC1A28E00D93351 /* hsb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hsb; path = hsb.lproj/Share.strings; sourceTree = ""; }; @@ -4296,6 +4314,7 @@ 437DFCD12AEFC7B500F701AE /* ka */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ka; path = ka.lproj/Shopping.strings; sourceTree = ""; }; 437E193A29F69ABA00F743E0 /* en-US */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-US"; path = "en-US.lproj/Notification.strings"; sourceTree = ""; }; 437E193B29F69ABB00F743E0 /* en-US */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-US"; path = "en-US.lproj/ZoomPageBar.strings"; sourceTree = ""; }; + 437E27022C7C9D8F00CE7490 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/NativeErrorPage.strings"; sourceTree = ""; }; 437E34352C3C03870025BFA9 /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/ResearchSurface.strings; sourceTree = ""; }; 437E6394293E0BF6008C190A /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/Alerts.strings; sourceTree = ""; }; 437E6395293E0BF6008C190A /* nb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nb; path = nb.lproj/TabsTray.strings; sourceTree = ""; }; @@ -4378,6 +4397,7 @@ 43858A832AF902E40010A4B7 /* kab */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kab; path = kab.lproj/Shopping.strings; sourceTree = ""; }; 438605AE2C3C010600C4CD23 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/EditAddress.strings; sourceTree = ""; }; 438605AF2C3C010600C4CD23 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/ScanQRCode.strings; sourceTree = ""; }; + 438613FD2C7C9E05005E3A65 /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/NativeErrorPage.strings; sourceTree = ""; }; 43866D292B8CAA5C00808188 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/KeyboardAccessory.strings; sourceTree = ""; }; 43866D2A2B8CAA5C00808188 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/PasswordAutofill.strings; sourceTree = ""; }; 4386E32C2C57AFCF00C97DCD /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Toolbar.strings; sourceTree = ""; }; @@ -4442,6 +4462,7 @@ 438B41BE2B5E865F00BA2E52 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/TabToolbar.strings; sourceTree = ""; }; 438C39022C57B042005CD2CC /* es-AR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-AR"; path = "es-AR.lproj/Toolbar.strings"; sourceTree = ""; }; 438C427F29D1B1EB0088717D /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/SnackBar.strings; sourceTree = ""; }; + 438C433E2C7C9D9F005AB958 /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/NativeErrorPage.strings"; sourceTree = ""; }; 438C789C2BE8F22600265DFC /* en-US */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-US"; path = "en-US.lproj/Microsurvey.strings"; sourceTree = ""; }; 438C8BD62C3C039500F49EC2 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/EditAddress.strings; sourceTree = ""; }; 438C8BD72C3C039500F49EC2 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/ScanQRCode.strings; sourceTree = ""; }; @@ -4523,6 +4544,8 @@ 43939B4F29E4277D00ADEA2A /* kab */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kab; path = "kab.lproj/Edit Card.strings"; sourceTree = ""; }; 4393C0C32A24BFE90013D0A2 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/DisplayCard.strings; sourceTree = ""; }; 439404FD29E4273000BCE280 /* ia */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ia; path = "ia.lproj/Edit Card.strings"; sourceTree = ""; }; + 43940EE22C7C9C0D000AA60B /* ia */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ia; path = ia.lproj/NativeErrorPage.strings; sourceTree = ""; }; + 439410F22C7C9E1400328C59 /* sl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sl; path = sl.lproj/NativeErrorPage.strings; sourceTree = ""; }; 43942A67293E0A64001BD183 /* eo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eo; path = eo.lproj/Alerts.strings; sourceTree = ""; }; 43942A68293E0A64001BD183 /* eo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eo; path = eo.lproj/SearchHeaderTitle.strings; sourceTree = ""; }; 43942A69293E0A64001BD183 /* eo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eo; path = eo.lproj/TabsTray.strings; sourceTree = ""; }; @@ -4540,6 +4563,7 @@ 4396410629C87A6700F74173 /* zh-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-TW"; path = "zh-TW.lproj/ErrorState.strings"; sourceTree = ""; }; 4396410729C87A6700F74173 /* zh-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-TW"; path = "zh-TW.lproj/Settings.strings"; sourceTree = ""; }; 4396410829C87A6700F74173 /* zh-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-TW"; path = "zh-TW.lproj/SnackBar.strings"; sourceTree = ""; }; + 43964FF82C7C9E89001C730A /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/NativeErrorPage.strings; sourceTree = ""; }; 439691A02AEFC7C900ED7ADA /* kk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kk; path = kk.lproj/Shopping.strings; sourceTree = ""; }; 4396BBE32A0BCCD200482ABA /* nn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nn; path = nn.lproj/FirefoxSync.strings; sourceTree = ""; }; 4396BBE42A0BCCD200482ABA /* nn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nn; path = nn.lproj/Upgrade.strings; sourceTree = ""; }; @@ -4773,6 +4797,7 @@ 43AD73D12C2051EC00C1442B /* hy-AM */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "hy-AM"; path = "hy-AM.lproj/AddressToolbar.strings"; sourceTree = ""; }; 43AD73D22C2051ED00C1442B /* hy-AM */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "hy-AM"; path = "hy-AM.lproj/EnhancedTrackingProtection.strings"; sourceTree = ""; }; 43AD73D32C2051ED00C1442B /* hy-AM */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "hy-AM"; path = "hy-AM.lproj/QRCode.strings"; sourceTree = ""; }; + 43ADBF222C7C9BAF006B6E34 /* he */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = he; path = he.lproj/NativeErrorPage.strings; sourceTree = ""; }; 43ADC80B29F69B27004444BA /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/Notification.strings; sourceTree = ""; }; 43ADC80C29F69B28004444BA /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = fi.lproj/ZoomPageBar.strings; sourceTree = ""; }; 43ADE8FD2B9F21540025934D /* th */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = th; path = th.lproj/KeyboardAccessory.strings; sourceTree = ""; }; @@ -4793,6 +4818,7 @@ 43AFD0D329F69A6E0001109D /* cy */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cy; path = cy.lproj/ZoomPageBar.strings; sourceTree = ""; }; 43B083B729F69DC10093BE71 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/Notification.strings; sourceTree = ""; }; 43B083B829F69DC10093BE71 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/ZoomPageBar.strings; sourceTree = ""; }; + 43B0B5692C7C9C2A00B2A5AE /* is */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = is; path = is.lproj/NativeErrorPage.strings; sourceTree = ""; }; 43B0CCAC29F69BCF00CBDC1D /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Notification.strings; sourceTree = ""; }; 43B0CCAD29F69BCF00CBDC1D /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/ZoomPageBar.strings; sourceTree = ""; }; 43B0CE2328EAFC58000500A2 /* nn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nn; path = nn.lproj/JumpBackIn.strings; sourceTree = ""; }; @@ -4825,6 +4851,7 @@ 43B1BCFD2B9F1D8E00126EF0 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/PasswordAutofill.strings; sourceTree = ""; }; 43B1EF182C3C019F00648D5A /* ia */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ia; path = ia.lproj/EditAddress.strings; sourceTree = ""; }; 43B1EF192C3C019F00648D5A /* ia */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ia; path = ia.lproj/ScanQRCode.strings; sourceTree = ""; }; + 43B210482C7C9EA500B136AD /* ug */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ug; path = ug.lproj/NativeErrorPage.strings; sourceTree = ""; }; 43B296302B305F1E00A5AA9B /* bs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bs; path = bs.lproj/ContextualHints.strings; sourceTree = ""; }; 43B296332B305F1E00A5AA9B /* bs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bs; path = bs.lproj/CredentialProvider.strings; sourceTree = ""; }; 43B296362B305F1E00A5AA9B /* bs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bs; path = bs.lproj/Credentials.strings; sourceTree = ""; }; @@ -4983,8 +5010,15 @@ 43BE95752A124BAD00DCFD17 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Upgrade.strings; sourceTree = ""; }; 43BED8DE2BE8F1F100E34361 /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/Microsurvey.strings; sourceTree = ""; }; 43BF382B2B8CA9C400EFDAF3 /* ia */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ia; path = ia.lproj/KeyboardAccessory.strings; sourceTree = ""; }; + 43BF3C5F2C7C9C380017A926 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/NativeErrorPage.strings; sourceTree = ""; }; 43BFD4502C3C04B400B76DE5 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = vi; path = vi.lproj/EditAddress.strings; sourceTree = ""; }; 43BFE5BA2C57B54100CFB4C5 /* zh-CN */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-CN"; path = "zh-CN.lproj/Toolbar.strings"; sourceTree = ""; }; + 43C09A7A2C7C9EB400BCD71D /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/ActivityStream.strings; sourceTree = ""; }; + 43C09A7B2C7C9EB400BCD71D /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/AddressToolbar.strings; sourceTree = ""; }; + 43C09A7C2C7C9EB400BCD71D /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/EditAddress.strings; sourceTree = ""; }; + 43C09A7D2C7C9EB400BCD71D /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/EnhancedTrackingProtection.strings; sourceTree = ""; }; + 43C09A7E2C7C9EB400BCD71D /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/ScanQRCode.strings; sourceTree = ""; }; + 43C09A7F2C7C9EB400BCD71D /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/Toolbar.strings; sourceTree = ""; }; 43C0B1D82BE8F26100E527D7 /* es-CL */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-CL"; path = "es-CL.lproj/Microsurvey.strings"; sourceTree = ""; }; 43C0DAB929D1B25700827785 /* kk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kk; path = kk.lproj/Alert.strings; sourceTree = ""; }; 43C0DABA29D1B25700827785 /* kk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = kk; path = kk.lproj/BiometricAuthentication.strings; sourceTree = ""; }; @@ -5006,6 +5040,7 @@ 43C4236D2AEFC88A00518309 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Shopping.strings"; sourceTree = ""; }; 43C426C42AEFC69B000D7D40 /* en-US */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-US"; path = "en-US.lproj/Shopping.strings"; sourceTree = ""; }; 43C437A72B554B9C00FBA497 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/TabToolbar.strings; sourceTree = ""; }; + 43C4422D2C7C9C4700ED0870 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/NativeErrorPage.strings; sourceTree = ""; }; 43C4A8562C3C002C00379C52 /* dsb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = dsb; path = dsb.lproj/EditAddress.strings; sourceTree = ""; }; 43C4A8572C3C002C00379C52 /* dsb */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = dsb; path = dsb.lproj/ScanQRCode.strings; sourceTree = ""; }; 43C4BFF329BF3DF1005359FB /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/EngagementNotification.strings"; sourceTree = ""; }; @@ -5112,7 +5147,9 @@ 43CEB4592B680459000F85A9 /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/Credentials.strings"; sourceTree = ""; }; 43CEB45A2B680459000F85A9 /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/TabToolbar.strings"; sourceTree = ""; }; 43CF280028B39A70008DF2C5 /* anp */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = anp; path = anp.lproj/BookmarkPanel.strings; sourceTree = ""; }; + 43CF316F2C7C9F0900D898EE /* zh-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-TW"; path = "zh-TW.lproj/NativeErrorPage.strings"; sourceTree = ""; }; 43CF76D92B5E84B9001CA9CD /* eu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eu; path = eu.lproj/TabToolbar.strings; sourceTree = ""; }; + 43CFB14C2C7C9A2B003B700F /* co */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = co; path = co.lproj/NativeErrorPage.strings; sourceTree = ""; }; 43CFD03D2B9F1D1000E7EB9E /* be */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = be; path = be.lproj/PasswordAutofill.strings; sourceTree = ""; }; 43D00492296FC48F00CB0F31 /* CreditCardSettingsEmptyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreditCardSettingsEmptyView.swift; sourceTree = ""; }; 43D04B0729E425A4007722F2 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = "de.lproj/Edit Card.strings"; sourceTree = ""; }; @@ -5315,6 +5352,7 @@ 43DE20222A52E453001EDCCF /* el */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = el; path = el.lproj/SelectCreditCard.strings; sourceTree = ""; }; 43DE406A2A0BCB1900D6F533 /* es-CL */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-CL"; path = "es-CL.lproj/FirefoxSync.strings"; sourceTree = ""; }; 43DE406B2A0BCB1900D6F533 /* es-CL */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-CL"; path = "es-CL.lproj/Upgrade.strings"; sourceTree = ""; }; + 43DE88092C7C9A3B00A7D4E0 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/NativeErrorPage.strings; sourceTree = ""; }; 43DEDA8D2B0B75FF003E54D4 /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/FirefoxHomepage.strings"; sourceTree = ""; }; 43DEE39E296C2CD600D13D0A /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/Alerts.strings; sourceTree = ""; }; 43DEE39F296C2CD600D13D0A /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = ca.lproj/JumpBackIn.strings; sourceTree = ""; }; @@ -5379,6 +5417,7 @@ 43E18BBF2A24C09100433C0C /* nn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nn; path = nn.lproj/DisplayCard.strings; sourceTree = ""; }; 43E1D7B029FFD6B5008F2117 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Notification.strings; sourceTree = ""; }; 43E1D7B129FFD6B5008F2117 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/ZoomPageBar.strings; sourceTree = ""; }; + 43E1DCD82C7C9AAB008E952F /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/NativeErrorPage.strings"; sourceTree = ""; }; 43E1FE0129F69D1200F5B25F /* sat-Olck */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "sat-Olck"; path = "sat-Olck.lproj/Alert.strings"; sourceTree = ""; }; 43E1FE0229F69D1200F5B25F /* sat-Olck */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "sat-Olck"; path = "sat-Olck.lproj/BiometricAuthentication.strings"; sourceTree = ""; }; 43E1FE0329F69D1200F5B25F /* sat-Olck */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "sat-Olck"; path = "sat-Olck.lproj/Edit Card.strings"; sourceTree = ""; }; @@ -5560,6 +5599,7 @@ 43EBF7072A3735DC00E56F21 /* rm */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = rm; path = rm.lproj/RememberCard.strings; sourceTree = ""; }; 43EBF7082A3735DC00E56F21 /* rm */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = rm; path = rm.lproj/UpdateCard.strings; sourceTree = ""; }; 43EC35B528B39E0F00E3513B /* mr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = mr; path = mr.lproj/BookmarkPanel.strings; sourceTree = ""; }; + 43EC361F2C7C9A4B00824F5E /* cy */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cy; path = cy.lproj/NativeErrorPage.strings; sourceTree = ""; }; 43EC4E1E2BE8F46200290013 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Microsurvey.strings; sourceTree = ""; }; 43EC6B9F2B14B34C00E417F1 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/FirefoxHomepage.strings; sourceTree = ""; }; 43EC79AA2C3C00BF00519D98 /* es-MX */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-MX"; path = "es-MX.lproj/KeyboardAccessory.strings"; sourceTree = ""; }; @@ -5586,6 +5626,7 @@ 43EE2FFB29FFD7D700C97C08 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Notification.strings; sourceTree = ""; }; 43EE2FFC29FFD7D700C97C08 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/ZoomPageBar.strings; sourceTree = ""; }; 43EE7D6828B39E20007D5A02 /* ms */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ms; path = ms.lproj/BookmarkPanel.strings; sourceTree = ""; }; + 43EE827C2C7C9D4600CDF5B9 /* nn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nn; path = nn.lproj/NativeErrorPage.strings; sourceTree = ""; }; 43EE84312BA85BB9003334F5 /* zh-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-TW"; path = "zh-TW.lproj/BottomSheet.strings"; sourceTree = ""; }; 43EECA382C3C00560032D70E /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/EditAddress.strings"; sourceTree = ""; }; 43EECA392C3C00560032D70E /* en-GB */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-GB"; path = "en-GB.lproj/ScanQRCode.strings"; sourceTree = ""; }; @@ -5595,6 +5636,7 @@ 43EF6F99293E0CB8006A4C7D /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/TabsTray.strings; sourceTree = ""; }; 43EF88BD2A3733B300AB9AAB /* co */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = co; path = co.lproj/Footer.strings; sourceTree = ""; }; 43EF88BE2A3733B300AB9AAB /* co */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = co; path = co.lproj/RememberCard.strings; sourceTree = ""; }; + 43F013FF2C7C9ABA00F8CF52 /* en-US */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-US"; path = "en-US.lproj/NativeErrorPage.strings"; sourceTree = ""; }; 43F034172AC1A2E800021EA0 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/TabLocation.strings; sourceTree = ""; }; 43F084E92A52E49F00C35028 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/CustomizeFirefoxHome.strings; sourceTree = ""; }; 43F084EA2A52E49F00C35028 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/SelectCreditCard.strings; sourceTree = ""; }; @@ -5756,6 +5798,10 @@ 43FEB816293E0C3A00DBC665 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Alerts.strings; sourceTree = ""; }; 43FEB817293E0C3A00DBC665 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/SearchHeaderTitle.strings; sourceTree = ""; }; 43FEB818293E0C3A00DBC665 /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/TabsTray.strings; sourceTree = ""; }; + 43FECBDA2C7C9AC900D644AE /* eo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eo; path = eo.lproj/EditAddress.strings; sourceTree = ""; }; + 43FECBDB2C7C9AC900D644AE /* eo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eo; path = eo.lproj/NativeErrorPage.strings; sourceTree = ""; }; + 43FECBDC2C7C9ACA00D644AE /* eo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eo; path = eo.lproj/ScanQRCode.strings; sourceTree = ""; }; + 43FECBDD2C7C9ACA00D644AE /* eo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eo; path = eo.lproj/Toolbar.strings; sourceTree = ""; }; 43FEE9662A24C0A3001C35F7 /* or */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = or; path = "or.lproj/Default Browser.strings"; sourceTree = ""; }; 43FF69D12C2050EC00D4B9C3 /* es-AR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-AR"; path = "es-AR.lproj/ActivityStream.strings"; sourceTree = ""; }; 43FF69D22C2050EC00D4B9C3 /* es-AR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-AR"; path = "es-AR.lproj/AddressToolbar.strings"; sourceTree = ""; }; @@ -12350,6 +12396,7 @@ 43C50B4E2A0BCAA800C6A134 /* FirefoxSync.strings */, 43A7153B2A2DF94F00DD5747 /* Footer.strings */, E4E0BB171AFBC9E4008D6260 /* Info.plist */, + 437AE30E2C7C9A0C0053F7F3 /* NativeErrorPage.strings */, 43E6BE142C57AF7600C2152C /* Toolbar.strings */, 43B627742C3C001E00A188E8 /* ScanQRCode.strings */, 43D3ED962C3BFFC900E33D46 /* EditAddress.strings */, @@ -13854,6 +13901,7 @@ 4308A4E62A52E38C001D652E /* SelectCreditCard.strings in Resources */, 43FA499D29C875C0005062DB /* EditCard.strings in Resources */, 43B627762C3C001E00A188E8 /* ScanQRCode.strings in Resources */, + 437AE3102C7C9A0C0053F7F3 /* NativeErrorPage.strings in Resources */, 433BADA029C8769800E34991 /* BiometricAuthentication.strings in Resources */, D58A202F25C9D96400105D25 /* BookmarkPanelDeleteConfirm.strings in Resources */, D59643EA25C9B8E000EAB8B9 /* HistoryPanel.strings in Resources */, @@ -17320,6 +17368,49 @@ name = TabsTray.strings; sourceTree = ""; }; + 437AE30E2C7C9A0C0053F7F3 /* NativeErrorPage.strings */ = { + isa = PBXVariantGroup; + children = ( + 437AE30F2C7C9A0C0053F7F3 /* bs */, + 43CFB14C2C7C9A2B003B700F /* co */, + 43DE88092C7C9A3B00A7D4E0 /* cs */, + 43EC361F2C7C9A4B00824F5E /* cy */, + 4345E88F2C7C9A5B00FC0D7D /* da */, + 43548AB92C7C9A6A0004C846 /* de */, + 437CD9FF2C7C9A8B00A34E3E /* el */, + 43E1DCD82C7C9AAB008E952F /* en-GB */, + 43F013FF2C7C9ABA00F8CF52 /* en-US */, + 43FECBDB2C7C9AC900D644AE /* eo */, + 4364018E2C7C9AE700FF64C6 /* es-AR */, + 4373440E2C7C9AF500457D4D /* es-CL */, + 430EC8982C7C9B5100759193 /* fi */, + 431D8FEE2C7C9B61001E041F /* fr */, + 43ADBF222C7C9BAF006B6E34 /* he */, + 4321F0522C7C9BE00001D0DD /* hsb */, + 43940EE22C7C9C0D000AA60B /* ia */, + 43B0B5692C7C9C2A00B2A5AE /* is */, + 43BF3C5F2C7C9C380017A926 /* it */, + 43C4422D2C7C9C4700ED0870 /* ja */, + 43400BC22C7C9C7100D8ECE9 /* kab */, + 434FE6142C7C9C7F00C44560 /* kk */, + 43EE827C2C7C9D4600CDF5B9 /* nn */, + 4361916A2C7C9D72005B31E3 /* pa-IN */, + 436FC4912C7C9D810083D324 /* pl */, + 437E27022C7C9D8F00CE7490 /* pt-BR */, + 438C433E2C7C9D9F005AB958 /* pt-PT */, + 4304BD432C7C9DCB0063AF05 /* ru */, + 438613FD2C7C9E05005E3A65 /* sk */, + 439410F22C7C9E1400328C59 /* sl */, + 430832542C7C9E4100F58087 /* sv */, + 43964FF82C7C9E89001C730A /* tr */, + 43B210482C7C9EA500B136AD /* ug */, + 4334C4F02C7C9EDE00FBEFCF /* vi */, + 43500A6B2C7C9EFB008E385F /* zh-CN */, + 43CF316F2C7C9F0900D898EE /* zh-TW */, + ); + name = NativeErrorPage.strings; + sourceTree = ""; + }; 43903A872C20502A00ACF76E /* ActivityStream.strings */ = { isa = PBXVariantGroup; children = ( @@ -17379,6 +17470,7 @@ 4300B0D92C57B06E00F609C1 /* es-MX */, 437E67412C57B4AB00A8791A /* th */, 43E0BE322C60EC4B004FED65 /* hr */, + 43C09A7A2C7C9EB400BCD71D /* uk */, ); name = ActivityStream.strings; sourceTree = ""; @@ -17440,6 +17532,7 @@ 4375F0E22C453BC4001F3A55 /* hu */, 437E67422C57B4AB00A8791A /* th */, 43E0BE332C60EC4B004FED65 /* hr */, + 43C09A7B2C7C9EB400BCD71D /* uk */, ); name = AddressToolbar.strings; sourceTree = ""; @@ -17502,6 +17595,7 @@ 4300B0DB2C57B06E00F609C1 /* es-MX */, 437E67442C57B4AB00A8791A /* th */, 43E0BE382C60EC4B004FED65 /* hr */, + 43C09A7D2C7C9EB400BCD71D /* uk */, ); name = EnhancedTrackingProtection.strings; sourceTree = ""; @@ -18630,6 +18724,8 @@ 437E67462C57B4AB00A8791A /* th */, 433D64C62C60EE1100CEC389 /* nb */, 43C9CD472C6A26D9002F86B4 /* hr */, + 43FECBDC2C7C9ACA00D644AE /* eo */, + 43C09A7E2C7C9EB400BCD71D /* uk */, ); name = ScanQRCode.strings; sourceTree = ""; @@ -18894,6 +18990,8 @@ 4396C29A2C57B42700837488 /* si */, 437E67432C57B4AB00A8791A /* th */, 43E0BE372C60EC4B004FED65 /* hr */, + 43FECBDA2C7C9AC900D644AE /* eo */, + 43C09A7C2C7C9EB400BCD71D /* uk */, ); name = EditAddress.strings; sourceTree = ""; @@ -19157,6 +19255,8 @@ 433D64C72C60EE1100CEC389 /* nb */, 43E7071E2C6A26FC00A29AE4 /* hu */, 43A04D712C73605C0052F8EB /* eu */, + 43FECBDD2C7C9ACA00D644AE /* eo */, + 43C09A7F2C7C9EB400BCD71D /* uk */, ); name = Toolbar.strings; sourceTree = ""; diff --git a/firefox-ios/Shared/Supporting Files/bs.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/bs.lproj/EnhancedTrackingProtection.strings index 46572e591e84..75d66b5d8089 100644 --- a/firefox-ios/Shared/Supporting Files/bs.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/bs.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Isključili ste zaštitu"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Zaštićeni ste. Ako nešto uočimo, obavijestit ćemo vas."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "Vaša veza nije sigurna."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Budite oprezni na ovoj stranici"; diff --git a/firefox-ios/Shared/Supporting Files/bs.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/bs.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..57cd5df52ede --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/bs.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "Učitaj ponovo"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "Došlo je do SSL greške i nije moguće uspostaviti sigurnosnu vezu sa serverom."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "Budite oprezni. Nešto ne izgleda kako treba."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "Pokušajte se povezati na drugom uređaju. Provjerite svoj modem ili ruter. Prekinite vezu i ponovo se povežite na Wi-Fi."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "Izgleda da postoji problem s vašom internet vezom."; + diff --git a/firefox-ios/Shared/Supporting Files/bs.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/bs.lproj/Settings.strings index ce72cd192d34..e3de4d33abd7 100644 --- a/firefox-ios/Shared/Supporting Files/bs.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/bs.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Upravljaj adresama"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "Adresa za %@"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "SAČUVANE ADRESE"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Sačuvaj adrese na %@"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "Sigurno sačuvajte svoje podatke da biste im kasnije mogli brzo pristupiti."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "Uključuje brojeve telefona i email adrese"; diff --git a/firefox-ios/Shared/Supporting Files/ca.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/ca.lproj/EnhancedTrackingProtection.strings index d67a4d1c475e..d2bb5734b439 100644 --- a/firefox-ios/Shared/Supporting Files/ca.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/ca.lproj/EnhancedTrackingProtection.strings @@ -43,8 +43,7 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Heu desactivat les proteccions"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Esteu protegit. Si detectem alguna cosa, us ho farem saber."; /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ diff --git a/firefox-ios/Shared/Supporting Files/co.lproj/CredentialProvider.strings b/firefox-ios/Shared/Supporting Files/co.lproj/CredentialProvider.strings index c107301efc77..6b00efdbd975 100644 --- a/firefox-ios/Shared/Supporting Files/co.lproj/CredentialProvider.strings +++ b/firefox-ios/Shared/Supporting Files/co.lproj/CredentialProvider.strings @@ -5,7 +5,7 @@ "LoginsList.NoLoginsFound.Title.v122" = "Nisuna parolla d’intesa arregistrata"; /* Label displayed when a user searches for an item, and no matches can be found against the search query */ -"LoginsList.NoMatchingResult.Title.v122" = "Nisuna parolla d’intesa trova"; +"LoginsList.NoMatchingResult.Title.v122" = "Ùn si trova nisuna parolla d’intesa"; /* Placeholder text for search field in the credential provider list */ "LoginsList.Search.Placeholder.v122" = "Ricercà parolle d’intesa"; diff --git a/firefox-ios/Shared/Supporting Files/co.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/co.lproj/EnhancedTrackingProtection.strings index 4feb67ce2738..7b3d1004f580 100644 --- a/firefox-ios/Shared/Supporting Files/co.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/co.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Cunnessione micca assicurata"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Ùn si trova nisunu perseguitatore"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Canistrelli di spiunagiu intersiti : %@"; @@ -43,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Avete disattivatu e prutezzioni"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Site prutetti. S’è no fighjemu qualcosa, a vi feremu sapè."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "A vostra cunnessione ùn hè micca assicurata."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Fate casu nant’à stu situ"; diff --git a/firefox-ios/Shared/Supporting Files/co.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/co.lproj/Microsurvey.strings index 980178212a95..54bdcaf851d0 100644 --- a/firefox-ios/Shared/Supporting Files/co.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/co.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Diselezziunatu"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Inchiesta"; + diff --git a/firefox-ios/Shared/Supporting Files/co.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/co.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..89bccd413774 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/co.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "Attualizà"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "Un sbagliu SSL hè accadutu è ùn si pò stabilisce una cunnessione sicura cù u servitore."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "Fate casu. Pare ch’ella ci sia un prublema."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "Pruvate di cunnettevi nant’à un altru apparechju. Verificate u vostru modem o « router ». Discunnittitevi è ricunnittitevi à u Wi-Fi."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "Pare ch’ella ci sia un prublema cù a vostra cunnessione internet."; + diff --git a/firefox-ios/Shared/Supporting Files/co.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/co.lproj/Settings.strings index 3306ba56806c..c133a9e2ab6b 100644 --- a/firefox-ios/Shared/Supporting Files/co.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/co.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Urganizà l’indirizzi"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "Indirizzu per %@"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "INDIRIZZI ARREGISTRATI"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Arregistrà l’indirizzi in %@"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "Arregistrate e vostre infurmazioni in tutta sicurità per accedeci prestu prestu un’altra volta."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "Include i numeri di telefonu è l’indirizzi elettronichi"; diff --git a/firefox-ios/Shared/Supporting Files/co.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/co.lproj/Toolbar.strings index 775392f15b94..5244f79135cf 100644 --- a/firefox-ios/Shared/Supporting Files/co.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/co.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Unghjetta nova"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Chjode st’unghjetta"; + diff --git a/firefox-ios/Shared/Supporting Files/cs.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/cs.lproj/EnhancedTrackingProtection.strings index e84882d3b573..62ce9463afec 100644 --- a/firefox-ios/Shared/Supporting Files/cs.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/cs.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Vypnuli jste ochranu"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Jste chráněni. Pokud něco zjistíme, dáme vám vědět."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "Vaše připojení není zabezpečené."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Buďte na této stránce opatrní"; diff --git a/firefox-ios/Shared/Supporting Files/cs.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/cs.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..f67b00fb2bb4 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/cs.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "Obnovit"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "Došlo k chybě protokolu SSL a zabezpečené připojení k serveru nelze navázat."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "Buďte opatrní. Něco není v pořádku."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "Zkuste se připojit na jiném zařízení. Zkontrolujte modem nebo router. Odpojte se a znovu se připojte k Wi-Fi."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "Zdá se, že došlo k problému s připojením k internetu."; + diff --git a/firefox-ios/Shared/Supporting Files/cs.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/cs.lproj/Settings.strings index 804523c0fe9a..bc16f1c8f97c 100644 --- a/firefox-ios/Shared/Supporting Files/cs.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/cs.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Správa adres"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "Adresa pro %@"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "ULOŽENÉ ADRESY"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Uložit adresy do %@"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "Bezpečně si uložte své informace, abyste k nim měli později rychlý přístup."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "Zahrnuje telefonní čísla a e-mailové adresy"; diff --git a/firefox-ios/Shared/Supporting Files/cy.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/cy.lproj/EnhancedTrackingProtection.strings index 1ba16ceece97..1e0a725cbf1c 100644 --- a/firefox-ios/Shared/Supporting Files/cy.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/cy.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Rydych wedi diffodd y mesurau diogelwch"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Rydych wedi'ch diogelu. Os byddwn yn sylwi ar rywbeth, byddwn yn rhoi gwybod ichi."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "Nid yw eich cysylltiad yn ddiogel."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Byddwch yn ofalus ar y wefan hon"; diff --git a/firefox-ios/Shared/Supporting Files/cy.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/cy.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..430367c5177d --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/cy.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "Ail-lwytho"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "Mae gwall SSL wedi digwydd ac nid oes modd gwneud cysylltiad diogel â'r gweinydd."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "Byddwch yn ofalus. Nid yw rhywbeth yn edrych yn iawn."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "Ceisiwch gysylltu ar ddyfais wahanol. Gwiriwch eich modem neu lwybrydd. Datgysylltwch ac ailgysylltwch â'r Wi-Fi."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "Mae'n ymddangos bod problem gyda'ch cysylltiad rhyngrwyd."; + diff --git a/firefox-ios/Shared/Supporting Files/cy.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/cy.lproj/Settings.strings index 9ad9bca7e336..b91970353a49 100644 --- a/firefox-ios/Shared/Supporting Files/cy.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/cy.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Rheoli cyfeiriadau"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "Cyfeiriad %@"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "CYFEIRIADAU WEDI'U CADW"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Cadw Cyfeiriadau i %@"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "Cadwch eich manylion yn ddiogel er mwyn cael mynediad cyflym atyn nhw'n nes ymlaen."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "Yn cynnwys rhifau ffôn a chyfeiriadau e-bost"; diff --git a/firefox-ios/Shared/Supporting Files/da.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/da.lproj/EnhancedTrackingProtection.strings index d2ad7e917480..e8448f4d96d9 100644 --- a/firefox-ios/Shared/Supporting Files/da.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/da.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Du har slået beskyttelse fra"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Du er beskyttet. Vi giver dig besked, hvis vi opdager noget."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "Din forbindelse er ikke sikker."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Vær forsigtig på dette websted"; diff --git a/firefox-ios/Shared/Supporting Files/da.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/da.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..5a90c7f02a15 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/da.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "Genindlæs"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "Der er opstået en SSL-fejl, og en sikker forbindelse til serveren kan ikke oprettes."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "Vær forsigtig. Noget ser ikke rigtigt ud."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "Prøv at oprette forbindelse med en anden enhed. Kontroller dit modem eller din router. Afbryd wi-fi-forbindelsen og opret den igen."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "Det ser ud til, at der er et problem med din internetforbindelse."; + diff --git a/firefox-ios/Shared/Supporting Files/da.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/da.lproj/Settings.strings index 442c9e9ccfef..353ccfff463d 100644 --- a/firefox-ios/Shared/Supporting Files/da.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/da.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Håndter adresser"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "Adresse til %@"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "GEMTE ADRESSER"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Gem adresser i %@"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "Gem dine oplysninger sikkert for at have adgang til dem igen senere."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "Inkluderer telefonnumre og mailadresser"; diff --git a/firefox-ios/Shared/Supporting Files/de.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/de.lproj/EnhancedTrackingProtection.strings index 6a5e61cee85e..0d948a827f6e 100644 --- a/firefox-ios/Shared/Supporting Files/de.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/de.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Sie haben die Schutzmaßnahmen deaktiviert"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Sie sind geschützt. Wenn wir etwas entdecken, sagen wir Ihnen es."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "Ihre Verbindung ist nicht sicher."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Seien Sie vorsichtig auf dieser Website"; diff --git a/firefox-ios/Shared/Supporting Files/de.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/de.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..3dc1f254dabb --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/de.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "Neu laden"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "Ein SSL-Fehler ist aufgetreten, daher kann keine sichere Verbindung zu diesem Server hergestellt werden."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "Seien Sie vorsichtig. Irgendetwas stimmt hier nicht."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "Versuchen Sie, auf einem anderen Gerät eine Verbindung herzustellen. Überprüfen Sie Ihr Modem oder Router. Trennen Sie die WLAN-Verbindung und stellen Sie die Verbindung wieder her."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "Anscheinend gibt es ein Problem mit Ihrer Internetverbindung."; + diff --git a/firefox-ios/Shared/Supporting Files/de.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/de.lproj/Settings.strings index 6dfe889e8efc..464baee6a577 100644 --- a/firefox-ios/Shared/Supporting Files/de.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/de.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Adressen verwalten"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "Adresse für %@"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "GESPEICHERTE ADRESSEN"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Adressen in %@ speichern"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "Speichern Sie Ihre Daten sicher, um später schnell darauf zugreifen zu können."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "Enthält Telefonnummern und E-Mail-Adressen"; diff --git a/firefox-ios/Shared/Supporting Files/dsb.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/dsb.lproj/EnhancedTrackingProtection.strings index 7f70e84de583..b58f023e08a2 100644 --- a/firefox-ios/Shared/Supporting Files/dsb.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/dsb.lproj/EnhancedTrackingProtection.strings @@ -46,8 +46,7 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Sćo znjemóžnił šćity"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Sćo šćitany. Jolic něco namakajomy, dajomy wam to k wěsći."; /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ diff --git a/firefox-ios/Shared/Supporting Files/el.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/el.lproj/EnhancedTrackingProtection.strings index d89bd44bd3ab..284b45140cf5 100644 --- a/firefox-ios/Shared/Supporting Files/el.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/el.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Απενεργοποιήσατε την προστασία"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Προστατεύεστε. Αν εντοπίσουμε κάτι, θα σας ενημερώσουμε."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "Η σύνδεση δεν είναι ασφαλής."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Να προσέχετε σε αυτόν τον ιστότοπο"; diff --git a/firefox-ios/Shared/Supporting Files/el.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/el.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..7d6b825dbb6e --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/el.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "Ανανέωση"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "Προέκυψε σφάλμα SSL και δεν ήταν δυνατή η ασφαλής σύνδεση με τον διακομιστή."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "Να προσέχετε. Κάτι δεν πάει καλά."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "Δοκιμάστε να συνδεθείτε από διαφορετική συσκευή. Ελέγξτε το modem ή το router σας. Αποσυνδέστε και επανασυνδέστε το Wi-Fi."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "Φαίνεται ότι υπάρχει κάποιο πρόβλημα με τη σύνδεσή σας στο διαδίκτυο."; + diff --git a/firefox-ios/Shared/Supporting Files/el.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/el.lproj/Settings.strings index 20d4b6dba3d1..85c55b7140b8 100644 --- a/firefox-ios/Shared/Supporting Files/el.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/el.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Διαχείριση διευθύνσεων"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "Διεύθυνση για %@"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "ΑΠΟΘΗΚΕΥΜΕΝΕΣ ΔΙΕΥΘΥΝΣΕΙΣ"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Αποθήκευση διευθύνσεων σε %@"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "Αποθηκεύστε με ασφάλεια τις πληροφορίες σας για γρήγορη πρόσβαση αργότερα."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "Περιλαμβάνει αριθμούς τηλεφώνου και διευθύνσεις email"; diff --git a/firefox-ios/Shared/Supporting Files/en-CA.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/en-CA.lproj/EnhancedTrackingProtection.strings index 6cce6fc2d9ac..927fcf187f5e 100644 --- a/firefox-ios/Shared/Supporting Files/en-CA.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/en-CA.lproj/EnhancedTrackingProtection.strings @@ -46,8 +46,7 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "You turned off protections"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "You’re protected. If we spot something, we’ll let you know."; /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ diff --git a/firefox-ios/Shared/Supporting Files/en-GB.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/en-GB.lproj/EnhancedTrackingProtection.strings index 553df1876512..ea0746ea56aa 100644 --- a/firefox-ios/Shared/Supporting Files/en-GB.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/en-GB.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "You turned off protections"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "You’re protected. If we spot something, we’ll let you know."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "Your connection is not secure."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Be careful on this site"; diff --git a/firefox-ios/Shared/Supporting Files/en-GB.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/en-GB.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..ae3df133d866 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/en-GB.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "Reload"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "An SSL error has occurred and a secure connection to the server cannot be made."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "Be careful. Something doesn’t look right."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "Try connecting on a different device. Check your modem or router. Disconnect and reconnect to Wi-Fi."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "Looks like there’s a problem with your internet connection."; + diff --git a/firefox-ios/Shared/Supporting Files/en-GB.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/en-GB.lproj/Settings.strings index 6f4479457e46..cb1c111955d7 100644 --- a/firefox-ios/Shared/Supporting Files/en-GB.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/en-GB.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Manage addresses"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "Address for %@"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "SAVED ADDRESSES"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Save Addresses to %@"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "Securely save your information to get quick access to it later."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "Includes phone numbers and email addresses"; diff --git a/firefox-ios/Shared/Supporting Files/en-US.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/en-US.lproj/EnhancedTrackingProtection.strings index 6cce6fc2d9ac..1d21d985912b 100644 --- a/firefox-ios/Shared/Supporting Files/en-US.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/en-US.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "You turned off protections"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "You’re protected. If we spot something, we’ll let you know."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "Your connection is not secure."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Be careful on this site"; diff --git a/firefox-ios/Shared/Supporting Files/en-US.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/en-US.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..ae3df133d866 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/en-US.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "Reload"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "An SSL error has occurred and a secure connection to the server cannot be made."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "Be careful. Something doesn’t look right."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "Try connecting on a different device. Check your modem or router. Disconnect and reconnect to Wi-Fi."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "Looks like there’s a problem with your internet connection."; + diff --git a/firefox-ios/Shared/Supporting Files/en-US.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/en-US.lproj/Settings.strings index 893403cf54b1..9e6dd70facb6 100644 --- a/firefox-ios/Shared/Supporting Files/en-US.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/en-US.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Manage addresses"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "Address for %@"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "SAVED ADDRESSES"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Save Addresses to %@"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "Securely save your information to get quick access to it later."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "Includes phone numbers and email addresses"; diff --git a/firefox-ios/Shared/Supporting Files/eo.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/eo.lproj/EditAddress.strings new file mode 100644 index 000000000000..7e1ecbc2c07d --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/eo.lproj/EditAddress.strings @@ -0,0 +1,141 @@ +/* Title for the cancel button in the remove address alert. */ +"Addresses.EditAddress.Alert.CancelButton.v129" = "Nuligi"; + +/* Message explaining the consequences of removing an address from all synced devices. */ +"Addresses.EditAddress.Alert.Message.v129" = "La adreso estos forigita el ĉiuj viaj spegulitaj aparatoj."; + +/* Title for the remove button in the remove address alert. */ +"Addresses.EditAddress.Alert.RemoveButton.v129" = "Forigi"; + +/* Title for the alert indicating the action to remove an address. */ +"Addresses.EditAddress.Alert.Title.v129" = "Forigi adreson"; + +/* Title for the interface option where users can add a new address for autofill purposes. This facilitates quicker form completion by automatically filling in the user's address information. */ +"Addresses.EditAddress.AutofillAddAddressTitle.v129" = "Aldoni adreson"; + +/* Label for the area field, allowing users to specify a particular area within a city or region. This detail can improve the specificity and accuracy of autofilled addresses. */ +"Addresses.EditAddress.AutofillAddressArea.v129" = "Regiono"; + +/* Label for the field where users input the city part of their address. This information is crucial for mail delivery and service provision, ensuring accurate city identification in autofill settings. */ +"Addresses.EditAddress.AutofillAddressCity.v129" = "Urbo"; + +/* Label for the field where users can specify just the country, used in contexts where full address details are not required. Simplifies autofill when only country information is necessary. */ +"Addresses.EditAddress.AutofillAddressCountryOnly.v129" = "Lando"; + +/* Label for the country or region field in address forms, allowing users to specify their country or territorial region. This is fundamental for international mail and services, ensuring autofill accuracy across borders. */ +"Addresses.EditAddress.AutofillAddressCountryRegion.v129" = "Lando aŭ regiono"; + +/* Label for the county field, crucial for addressing in regions where county lines play a key role in postal services. Enhances autofill accuracy by including county information. */ +"Addresses.EditAddress.AutofillAddressCounty.v129" = "Municipo"; + +/* Label for the department field, used in countries like France and Colombia where departments are a key administrative division. Ensures correct departmental information is autofilled. */ +"Addresses.EditAddress.AutofillAddressDepartment.v129" = "Sekcio"; + +/* Label for the district field in the address form, allowing users to specify their district for more precise location identification. This aids in refining address details for accurate autofill. */ +"Addresses.EditAddress.AutofillAddressDistrict.v129" = "Distrikto"; + +/* Label for the Do/Si field, pertinent to addresses in South Korea. Do/Si refers to provincial level divisions, and specifying this enhances address accuracy in autofill settings. */ +"Addresses.EditAddress.AutofillAddressDoSi.v129" = "Do/Si"; + +/* Label for the Eircode field, specific to Ireland. It's a unique postal code system that helps in precise location identification, enhancing the effectiveness of autofill. */ +"Addresses.EditAddress.AutofillAddressEircode.v129" = "Koda poŝto (Eircode)"; + +/* Label for the email address field, where users input their email. Critical for digital communication and account verification, this ensures email addresses are autofilled accurately. */ +"Addresses.EditAddress.AutofillAddressEmail.v129" = "Retpoŝto"; + +/* Label for the emirate field, essential for addresses in the United Arab Emirates. Including emirate details ensures the autofill feature accurately represents user addresses. */ +"Addresses.EditAddress.AutofillAddressEmirate.v129" = "Emirlando"; + +/* Label for the field where users specify the name of an island, if applicable. Important for addresses in archipelagic regions, aiding in precise location identification during autofill. */ +"Addresses.EditAddress.AutofillAddressIsland.v129" = "Insulo"; + +/* Label for the field where the user inputs their full name as part of an address form. Essential for personalized form submissions and ensuring information accuracy in autofilled forms. */ +"Addresses.EditAddress.AutofillAddressName.v129" = "Nomo"; + +/* Label for the field where users can input the name of their neighborhood. This detail adds precision to addresses, especially in densely populated areas, improving the accuracy of autofill. */ +"Addresses.EditAddress.AutofillAddressNeighborhood.v129" = "Kvartalo"; + +/* Label for the oblast field, relevant for addresses in countries like Russia and Ukraine. Oblasts are a significant administrative division, and their specification aids in autofill accuracy. */ +"Addresses.EditAddress.AutofillAddressOblast.v129" = "Sendependa provinco"; + +/* Label for the input field designated for the organization's name related to the address. Helps in distinguishing addresses used for business or personal purposes in autofill settings. */ +"Addresses.EditAddress.AutofillAddressOrganization.v129" = "Organizo"; + +/* Label for the parish field, significant in places where parishes are used for local administration and addressing. Ensures users can specify parish details for better autofill accuracy. */ +"Addresses.EditAddress.AutofillAddressParish.v129" = "Paroĥo"; + +/* Label for the PIN (Postal Index Number) field, used in India. It's a code representing a specific area, crucial for accurate mail delivery and autofill functionality. */ +"Addresses.EditAddress.AutofillAddressPin.v129" = "Pin"; + +/* Label for the postal code field, universally used in address forms to specify the area code for mail sorting. Essential for autofill to ensure mail and services are accurately routed. */ +"Addresses.EditAddress.AutofillAddressPostalCode.v129" = "Poŝtkodo"; + +/* Label for the post town field, used primarily in the UK and some other regions for mail sorting. Essential for users in applicable areas to specify for correct mail delivery through autofill. */ +"Addresses.EditAddress.AutofillAddressPostTown.v129" = "Poŝta urbo"; + +/* Label for the prefecture field, essential for addresses in countries like Japan where prefectures are a major administrative division. Aids in precise location specification for autofill. */ +"Addresses.EditAddress.AutofillAddressPrefecture.v129" = "Prefektejo"; + +/* Label for the province field, required in countries where provinces are a primary administrative division. Helps in pinpointing the user's location more accurately for autofill purposes. */ +"Addresses.EditAddress.AutofillAddressProvince.v129" = "Provinco"; + +/* Label for the state field, a necessary component of addresses in many countries, especially the USA. It ensures that state-specific details are correctly filled in forms using autofill. */ +"Addresses.EditAddress.AutofillAddressState.v129" = "Ŝtato"; + +/* Label for the suburb field, enabling users to add suburb details to their address. This is important for accurate delivery and services in suburban areas, enhancing autofill functionality. */ +"Addresses.EditAddress.AutofillAddressSuburb.v129" = "Suburbo"; + +/* Label for the telephone number field, allowing users to input their contact number. This is essential for communication and service provision, ensuring contact details are autofilled correctly. */ +"Addresses.EditAddress.AutofillAddressTel.v129" = "Telefono"; + +/* Label for the input field for the townland, a specific type of land division used in rural areas. Enhances address detail for users in regions where townlands are a common addressing component. */ +"Addresses.EditAddress.AutofillAddressTownland.v129" = "Kampara regiono"; + +/* Label for the field to input the name of a village or township. This is crucial for addresses in rural areas, ensuring the autofill feature accurately captures all necessary geographical details. */ +"Addresses.EditAddress.AutofillAddressVillageTownship.v129" = "Vilaĝo aŭ municipo"; + +/* Label for the ZIP code field, primarily used in the United States for mail sorting. Key for autofill to accurately complete addresses for shipping, billing, and service provision. */ +"Addresses.EditAddress.AutofillAddressZip.v129" = "Kodo ZIP"; + +/* Label for the button to cancel the current autofill operation or exit the form without saving changes. Provides users with an option to back out of a process without making any modifications. */ +"Addresses.EditAddress.AutofillCancelButton.v129" = "Nuligi"; + +/* Title for the option allowing users to edit an existing saved address. This is used within the settings for autofill, enabling users to update their address details for accurate form autofilling. */ +"Addresses.EditAddress.AutofillEditAddressTitle.v129" = "Modifi adreson"; + +/* Title for the input field where users can enter their street address. This is used within the settings for autofill, allowing users to provide their street address for accurate form autofilling. */ +"Addresses.EditAddress.AutofillEditStreetAddressTitle.v129" = "Strata adreso"; + +/* Label for the button to save the current address details entered or edited by the user. This action confirms the user's changes and updates their autofill settings accordingly. */ +"Addresses.EditAddress.AutofillSaveButton.v129" = "Konservi"; + +/* Title for the option allowing users to view an existing saved address. This is used within the settings for autofill, enabling users to see their address details for accurate form autofilling. */ +"Addresses.EditAddress.AutofillViewAddressTitle.v129" = "Vidi adreson"; + +/* Button label for closing the view where user can view their address info. */ +"Addresses.EditAddress.CloseNavBarButtonLabel.v129" = "Fermi"; + +/* Button label for editing the address details shown in the form. */ +"Addresses.EditAddress.EditNavBarButtonLabel.v129" = "Modifi"; + +/* Title for button that offers the user the option to remove an address. */ +"Addresses.EditAddress.RemoveAddressButtonTitle.v129" = "Forigi adreson"; + +/* Toast message confirming that an address has been successfully removed. */ +"Addresses.Toast.AddressRemovedConfirmation.v129" = "Adreso forigita"; + +/* Toast message confirming that an address has been successfully saved. */ +"Addresses.Toast.AddressSavedConfirmation.v129" = "Adreso konservita"; + +/* Toast message indicating an error occurred while trying to save an address. */ +"Addresses.Toast.AddressSaveError.v129" = "Ne eblis konservi la adreson"; + +/* Toast message indicating an error occurred while trying to remove an address. */ +"Addresses.Toast.AddressSaveError.v130" = "Ne eblis forigi la adreson"; + +/* Suggestion to try again after an error occurred while trying to save an address. */ +"Addresses.Toast.AddressSaveRetrySuggestion.v129" = "Klopodi denove"; + +/* Toast message confirming that an address has been successfully updated. */ +"Addresses.Toast.AddressUpdatedConfirmation.v129" = "Informo pri adreso ĝisdatigita"; + diff --git a/firefox-ios/Shared/Supporting Files/eo.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/eo.lproj/EnhancedTrackingProtection.strings index 46aad18b23d1..3f6c80d8b2c3 100644 --- a/firefox-ios/Shared/Supporting Files/eo.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/eo.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,18 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Nesekura konekto"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Neniu spurilo trovita"; + +/* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Interretejaj spurilaj kuketoj: %@"; + +/* Text to let users know how many fingerprinters were blocked on the current website. The placeholder will show the number of fingerprinters detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.Fingerprinter.v129" = "Identigiloj de ciferecaj spuroj: %@"; + +/* Text to let users know how many social media trackers were blocked on the current website. The placeholder will show the number of such cookies detected */ +"Menu.EnhancedTrackingProtection.Details.Trackers.SocialMedia.v129" = "Sociretaj spuriloj: %@"; + /* Text to let users know how many trackers were blocked on the current website. Placeholder for the number of trackers blocked */ "Menu.EnhancedTrackingProtection.Details.Trackers.v128" = "Blokitaj spuriloj: %@"; @@ -34,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Vi malŝaltis protektojn"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Vi estas protektita. Se ni malkovras ion, ni sciigos vin."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "Via konekto ne estas sekura."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Estu singarda en tiu ĉi retejo"; @@ -53,6 +67,9 @@ /* A switch to disable enhanced tracking protection inside the menu. */ "Menu.EnhancedTrackingProtection.SwitchOff.Text.v128" = "Protektoj estas MALAKTIVAJ. Ni sugestas reaktivigi ilin."; +/* A switch to disable enhanced tracking protection inside the menu. */ +"Menu.EnhancedTrackingProtection.SwitchOff.Text.v129" = "Protektoj estas MALAKTIVAJ. Ni sugestas reaktivigi ilin."; + /* A switch to disable enhanced tracking protection inside the menu. */ "Menu.EnhancedTrackingProtection.SwitchOn.Text.v128" = "Se io misfunkcias en tiu ĉi retejo, provu malŝalti ĝin."; diff --git a/firefox-ios/Shared/Supporting Files/eo.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/eo.lproj/Microsurvey.strings index 9f79f1280ae6..f53cc0c68444 100644 --- a/firefox-ios/Shared/Supporting Files/eo.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/eo.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Ne elektita"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Enekto"; + diff --git a/firefox-ios/Shared/Supporting Files/eo.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/eo.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..78a305e2f9e3 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/eo.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "Reŝargi"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "Okazis eraro SSL kaj ne eblas sekure konektiĝi al la servilo."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "Estu singarda. Io ne ĝustas."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "Provu konektiĝi el alia aparato. Kontrolu vian modemon aŭ retalirilon. Malkonektiĝu kaj rekonektiĝu al sendrata reto (Wi-Fi)."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "Ŝajne estas problemo kun via retaliro."; + diff --git a/firefox-ios/Shared/Supporting Files/eo.lproj/PasswordAutofill.strings b/firefox-ios/Shared/Supporting Files/eo.lproj/PasswordAutofill.strings index 1e9e1034f5ab..b563511a9ba4 100644 --- a/firefox-ios/Shared/Supporting Files/eo.lproj/PasswordAutofill.strings +++ b/firefox-ios/Shared/Supporting Files/eo.lproj/PasswordAutofill.strings @@ -1,3 +1,6 @@ +/* This label is used in a cell found in the list of autofill login options in place of an actual username to denote that no username was saved for this login */ +"PasswordAutofill.LoginListCellNoUsername.v129" = "(sen nomo de uzanto)"; + /* This label is used for a button in the password list screen allowing users to manage their saved passwords. It's meant to direct users to where they can add, remove, or edit their saved passwords. */ "PasswordAutofill.ManagePasswordsButton.v124" = "Administri pasvortojn"; diff --git a/firefox-ios/Shared/Supporting Files/eo.lproj/ScanQRCode.strings b/firefox-ios/Shared/Supporting Files/eo.lproj/ScanQRCode.strings new file mode 100644 index 000000000000..9e3e3703ddec --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/eo.lproj/ScanQRCode.strings @@ -0,0 +1,9 @@ +/* Allow button to open URL from scanned QR Code */ +"ScanQRCode.ConfirmOpenURL.AllowButton.v129" = "Permesi"; + +/* Deny button to cancel opening URL from scanned QR Code */ +"ScanQRCode.ConfirmOpenURL.DenyButton.v129" = "Rifuzi"; + +/* Text of the prompt to ask user permission to open a URL from a scanned QR code. Placeholder is app name. */ +"ScanQRCode.ConfirmOpenURL.Message.v129" = "Ĉu permesi la malfermon de %@?"; + diff --git a/firefox-ios/Shared/Supporting Files/eo.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/eo.lproj/Settings.strings index 3809e47f6a73..2b08faf8dd7d 100644 --- a/firefox-ios/Shared/Supporting Files/eo.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/eo.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Administri adresojn"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "Adreso por %@"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "KONSERVITAJ ADRESOJN"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Konservi adresojn en %@"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "Sekure konservi viajn informojn por rapidi aliri ilin poste."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "Telefonnumeroj kaj retpoŝtaj adresoj inkluzivitaj"; diff --git a/firefox-ios/Shared/Supporting Files/eo.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/eo.lproj/Toolbar.strings new file mode 100644 index 000000000000..a7ae34040b66 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/eo.lproj/Toolbar.strings @@ -0,0 +1,6 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Nova langeto"; + +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Fermi tiun ĉi langeton"; + diff --git a/firefox-ios/Shared/Supporting Files/es-AR.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/es-AR.lproj/EnhancedTrackingProtection.strings index 1ad8a0417440..04510ffdccbf 100644 --- a/firefox-ios/Shared/Supporting Files/es-AR.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/es-AR.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Desactivaste las protecciones"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Estás protegido. Si detectamos algo, te lo haremos saber."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "La conexión no es segura."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Tené cuidado en este sitio"; diff --git a/firefox-ios/Shared/Supporting Files/es-AR.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/es-AR.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..f0956f82c0d2 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/es-AR.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "Recargar"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "Se produjo un error de SSL y no se puede establecer una conexión segura con el servidor."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "Cuidado. Algo no parece estar bien."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "Probá conectarte a un dispositivo diferente. Verificá tu módem o router. Desconectá y volvé a conectarte al wifi."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "Parece que hay un problema con la conexión a Internet."; + diff --git a/firefox-ios/Shared/Supporting Files/es-AR.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/es-AR.lproj/Settings.strings index 2bf2c6a33a63..9ce09a106ffd 100644 --- a/firefox-ios/Shared/Supporting Files/es-AR.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/es-AR.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Administrar direcciones"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "Dirección para %@"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "DIRECCIONES GUARDADAS"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Guardar direcciones en %@"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "Guardá tu información de forma segura para acceder a ella más tarde."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "Incluye números de teléfono y direcciones de correo electrónico"; diff --git a/firefox-ios/Shared/Supporting Files/es-CL.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/es-CL.lproj/EnhancedTrackingProtection.strings index eca8546e3277..51bbe314225f 100644 --- a/firefox-ios/Shared/Supporting Files/es-CL.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/es-CL.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Desactivaste las protecciones"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Estás bajo protección. Si detectamos algo, te lo haremos saber."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "Tu conexión no es segura."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Ten cuidado en este sitio"; diff --git a/firefox-ios/Shared/Supporting Files/es-CL.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/es-CL.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..1844a8e51246 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/es-CL.lproj/NativeErrorPage.strings @@ -0,0 +1,9 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "Recargar"; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "Ten cuidado. Algo no parece estar bien."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "Parece que hay un problema con tu conexión a Internet."; + diff --git a/firefox-ios/Shared/Supporting Files/es-CL.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/es-CL.lproj/Settings.strings index 7b23f4a84661..a129aedc8e73 100644 --- a/firefox-ios/Shared/Supporting Files/es-CL.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/es-CL.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Administrar direcciones"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "Direcciones para %@"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "DIRECCIONES GUARDADAS"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Guardar direcciones en %@"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "Guarda tu información de forma segura para acceder a ella rápidamente más tarde."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "Incluye números de teléfono y direcciones de correo electrónico"; diff --git a/firefox-ios/Shared/Supporting Files/es.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/es.lproj/EnhancedTrackingProtection.strings index 53785323b4d8..607a7ed303fa 100644 --- a/firefox-ios/Shared/Supporting Files/es.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/es.lproj/EnhancedTrackingProtection.strings @@ -43,8 +43,7 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Has desactivado las protecciones"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Estás protegido. Si detectamos algo, te lo haremos saber."; /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ diff --git a/firefox-ios/Shared/Supporting Files/eu.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/eu.lproj/EnhancedTrackingProtection.strings index 20f4d4b5b7a5..47124f3ea71c 100644 --- a/firefox-ios/Shared/Supporting Files/eu.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/eu.lproj/EnhancedTrackingProtection.strings @@ -46,8 +46,7 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Babesak desgaitu dituzu"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Babestuta zaude. Zerbait ikusten badugu, jakinaraziko dizugu."; /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ diff --git a/firefox-ios/Shared/Supporting Files/fi.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/fi.lproj/EnhancedTrackingProtection.strings index 8856d3e79ed0..e5cb919b106d 100644 --- a/firefox-ios/Shared/Supporting Files/fi.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/fi.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Poistit suojaukset käytöstä"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Olet suojattu. Jos havaitsemme jotain, ilmoitamme sinulle."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "Yhteys ei ole suojattu."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Ole varovainen tällä sivustolla"; diff --git a/firefox-ios/Shared/Supporting Files/fi.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/fi.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..2f090f25b788 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/fi.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "Päivitä"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "Tapahtui SSL-virhe, eikä suojattua yhteyttä palvelimeen voida muodostaa."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "Ole varovainen. Jokin ei vaikuta olevan oikein."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "Yritä muodostaa yhteys toisella laitteella. Tarkista modeemi tai reititin. Katkaise Wi-Fi-yhteys ja yhdistä se uudelleen."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "Vaikuttaa siltä, että Internet-yhteydessäsi on ongelma."; + diff --git a/firefox-ios/Shared/Supporting Files/fi.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/fi.lproj/Settings.strings index afbb09f2c004..44c456932d26 100644 --- a/firefox-ios/Shared/Supporting Files/fi.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/fi.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Hallitse osoitteita"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "Käyttäjän %@ osoite"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "TALLENNETUT OSOITTEET"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Tallenna osoitteet %@iin"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "Tallenna tietosi turvallisesti, jotta saat ne käyttöösi nopeasti myöhemmin."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "Sisältää puhelinnumerot ja sähköpostiosoitteet"; diff --git a/firefox-ios/Shared/Supporting Files/fr.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/fr.lproj/EnhancedTrackingProtection.strings index 7a1dbc311147..05eef5c43a83 100644 --- a/firefox-ios/Shared/Supporting Files/fr.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/fr.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Vous avez désactivé les protections"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Vous êtes protégé·e. Si nous remarquons quelque chose, nous vous le ferons savoir."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "La connexion n’est pas sécurisée."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Faites attention sur ce site"; diff --git a/firefox-ios/Shared/Supporting Files/fr.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/fr.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..6d00254ac71f --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/fr.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "Actualiser"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "Une erreur SSL s’est produite et une connexion sécurisée avec le serveur ne peut pas être établie."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "Faites preuve de prudence, il semble y avoir un problème."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "Essayez de vous connecter sur un autre appareil. Vérifiez votre modem ou votre routeur. Déconnectez-vous puis reconnectez-vous au Wi-Fi."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "Il semble y avoir un problème avec votre connexion Internet."; + diff --git a/firefox-ios/Shared/Supporting Files/fr.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/fr.lproj/Settings.strings index 7cb747140475..cba0f4498912 100644 --- a/firefox-ios/Shared/Supporting Files/fr.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/fr.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Gérer les adresses"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "Adresse pour %@"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "ADRESSES ENREGISTRÉES"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Enregistrez les adresses dans %@"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "Enregistrez vos informations en toute sécurité pour y accéder rapidement plus tard."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "Y compris les numéros de téléphone et les adresses e-mail"; diff --git a/firefox-ios/Shared/Supporting Files/he.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/he.lproj/EnhancedTrackingProtection.strings index a441fa95994d..b3dc3347f448 100644 --- a/firefox-ios/Shared/Supporting Files/he.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/he.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "כיבית את ההגנות"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "ההגנה פעילה. אם נזהה משהו חריג, נודיע לך."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "החיבור שלך אינו מאובטח."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "יש להיזהר באתר זה"; diff --git a/firefox-ios/Shared/Supporting Files/he.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/he.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..4c6066f82612 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/he.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "טעינה מחדש"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "אירעה שגיאת SSL ולא ניתן ליצור חיבור מאובטח לשרת."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "נא להיזהר. משהו לא נראה תקין."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "נא לנסות להתחבר במכשיר אחר, לבדוק את המודם או הנתב שלך, ולהתנתק ולהתחבר מחדש ל־Wi-Fi."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "נראה שיש בעיה בחיבור האינטרנט שלך."; + diff --git a/firefox-ios/Shared/Supporting Files/he.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/he.lproj/Settings.strings index b0d3a1410b64..c629fb89c391 100644 --- a/firefox-ios/Shared/Supporting Files/he.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/he.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "ניהול כתובות"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "כתובת עבור %@"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "כתובות שמורות"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "שמירת כתובות ל־%@"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "שמירה של המידע שלך בצורה מאובטחת כדי לקבל גישה מהירה אליו מאוחר יותר."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "כולל מספרי טלפון וכתובות דוא״ל"; diff --git a/firefox-ios/Shared/Supporting Files/hr.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/hr.lproj/EnhancedTrackingProtection.strings index 84c3e4acd865..a079d8493d52 100644 --- a/firefox-ios/Shared/Supporting Files/hr.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/hr.lproj/EnhancedTrackingProtection.strings @@ -46,8 +46,7 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Isključio/la si zaštitu"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Zaštićen/a si. Ako nešto uočimo, javit ćemo ti."; /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ diff --git a/firefox-ios/Shared/Supporting Files/hsb.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/hsb.lproj/EnhancedTrackingProtection.strings index 88541b5313b1..0ffc291916f7 100644 --- a/firefox-ios/Shared/Supporting Files/hsb.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/hsb.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Sće škity znjemóžnił"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Sće škitany. Jeli něšto namakamy, zdźělimy wam to."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "Waš zwisk wěsty njeje."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Budźće kedźbliwy na tutym sydle"; diff --git a/firefox-ios/Shared/Supporting Files/hsb.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/hsb.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..b9783fa96963 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/hsb.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "Znowa začitać"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "SSL-zmylk je nastał a wěsty zwisk ze serwerom njeda so wutworić."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "Budźće kedźbliwy. Něšto w porjadku njeje."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "Spytajće z druhim gratom zwjazać. Přepruwujće swój modem abo router. Dźělće zwisk WLAN a zwjazajće znowa."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "Zda so, zo je problem z wašim internetnym zwiskom."; + diff --git a/firefox-ios/Shared/Supporting Files/hsb.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/hsb.lproj/Settings.strings index 49f003b531d2..e7b8adebf8b3 100644 --- a/firefox-ios/Shared/Supporting Files/hsb.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/hsb.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Adresy rjadować"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "Adresa za %@"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "SKŁADOWANE ADRESY"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Adresy do %@ składować"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "Składujće swoje informacije wěsć, zo byšće pozdźišo spěšny přistup k njemu dóstał."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "Wobsahuje telefonowe čisła a e-mejlowe adresy"; diff --git a/firefox-ios/Shared/Supporting Files/hu.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/hu.lproj/EnhancedTrackingProtection.strings index d4f3c1d48eca..e8e9c44ddff9 100644 --- a/firefox-ios/Shared/Supporting Files/hu.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/hu.lproj/EnhancedTrackingProtection.strings @@ -46,8 +46,7 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Kikapcsolta a védelmeket"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Védve van. Ha látunk valamit, értesíteni fogjuk."; /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ diff --git a/firefox-ios/Shared/Supporting Files/hy-AM.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/hy-AM.lproj/EnhancedTrackingProtection.strings index e631ae3eafbc..306576b16613 100644 --- a/firefox-ios/Shared/Supporting Files/hy-AM.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/hy-AM.lproj/EnhancedTrackingProtection.strings @@ -46,8 +46,7 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Դուք անջատեցիք պաշտպանությունը"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Դուք պաշտպանված եք: Եթե ինչ-որ բան նկատենք, ձեզ կտեղեկացնենք։"; /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ diff --git a/firefox-ios/Shared/Supporting Files/ia.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/ia.lproj/EnhancedTrackingProtection.strings index a2db7054d821..68d14a28b811 100644 --- a/firefox-ios/Shared/Supporting Files/ia.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/ia.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Tu disactivava le protectiones"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Tu es protegite. Si nos discoperi alco, lo facera saper vos."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "Tu connexion non es secur."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Sia attente in iste sito"; diff --git a/firefox-ios/Shared/Supporting Files/ia.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/ia.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..7d900804b56b --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/ia.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "Recargar"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "Un error SSL ha occurrite e un connexion secur al servitor non pote esser facite."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "Attention! Alco non pare correcte."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "Prova a connecter te ab un altere apparato. Controla le modem o le router. Disactiva e reactiva le connexion Wi-Fi."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "Il pare que il ha un problema con tu connexion internet."; + diff --git a/firefox-ios/Shared/Supporting Files/ia.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/ia.lproj/Settings.strings index eb7129a33bf7..bbf259b21582 100644 --- a/firefox-ios/Shared/Supporting Files/ia.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/ia.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Gerer adresses"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "Adresse pro %@"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "ADRESSES SALVATE"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Salvar adresses a %@"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "Reserva tu informationes con securitate pro postea haber accesso facile a illos."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "Include numeros de telephono e adresses email"; diff --git a/firefox-ios/Shared/Supporting Files/is.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/is.lproj/EnhancedTrackingProtection.strings index 030e1ba6bb35..324377d19a3d 100644 --- a/firefox-ios/Shared/Supporting Files/is.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/is.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Þú slökktir á vörnum"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Þú ert varin/n. Ef við komum auga á eitthvað látum við þig vita."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "Tengingin þín er ekki örugg."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Farðu varlega á þessum vef"; diff --git a/firefox-ios/Shared/Supporting Files/is.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/is.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..c459d22d20ab --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/is.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "Endurhlaða"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "SSL-villa kom upp og ekki er hægt að koma á öruggri tengingu við netþjóninn."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "Farðu varlega. Eitthvað lítur ekki út fyrir að vera rétt."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "Prófaðu að tengjast í öðru tæki. Athugaðu mótaldið þitt eða beininn. Aftengdu og tengdu aftur við Wi-Fi."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "Það virðist vera vandamál með nettenginguna þína."; + diff --git a/firefox-ios/Shared/Supporting Files/is.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/is.lproj/Settings.strings index b181fa12c35a..eaf0c6c7e89e 100644 --- a/firefox-ios/Shared/Supporting Files/is.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/is.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Sýsla með tölvupóstföng"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "Póstfang fyrir %@"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "VISTAÐAR SLÓÐIR"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Vista póstföng í %@"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "Vistaðu upplýsingarnar þínar á öruggan hátt til að fá skjótan aðgang að þeim síðar."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "Þar með talin símanúmer og tölvupóstföng"; diff --git a/firefox-ios/Shared/Supporting Files/it.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/it.lproj/EnhancedTrackingProtection.strings index 014da643b184..a1922e9e1798 100644 --- a/firefox-ios/Shared/Supporting Files/it.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/it.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Hai disattivato le protezioni"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Sei protetto. Se rileviamo qualcosa, te lo faremo sapere."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "Questa connessione non è sicura."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Fai attenzione su questo sito"; diff --git a/firefox-ios/Shared/Supporting Files/it.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/it.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..b55e3ec7517e --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/it.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "Ricarica"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "Si è verificato un errore SSL e non è possibile stabilire una connessione sicura al server."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "Fai attenzione. Sembra che ci sia un problema."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "Prova a connetterti da un altro dispositivo, controlla il modem o il router, disattiva e riattiva la connessione Wi-Fi."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "Sembra che ci sia un problema con la connessione a Internet."; + diff --git a/firefox-ios/Shared/Supporting Files/it.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/it.lproj/Settings.strings index 8a61e5698fc3..720869182667 100644 --- a/firefox-ios/Shared/Supporting Files/it.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/it.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Gestisci indirizzi"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "Indirizzo per %@"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "INDIRIZZI SALVATI"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Salva indirizzi in %@"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "Salva le tue informazioni in modo sicuro per accedervi rapidamente in seguito."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "Include numeri di telefono e indirizzi email"; diff --git a/firefox-ios/Shared/Supporting Files/ja.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/ja.lproj/EnhancedTrackingProtection.strings index b465bd779463..1eb11225f5cc 100644 --- a/firefox-ios/Shared/Supporting Files/ja.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/ja.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "保護をオフにしました"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "現在保護されています。何か問題があればお知らせします。"; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "接続が安全ではありません。"; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "このサイトでは注意してください"; diff --git a/firefox-ios/Shared/Supporting Files/ja.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/ja.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..f0771b4878cf --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/ja.lproj/NativeErrorPage.strings @@ -0,0 +1,6 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "再読み込み"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "SSL エラーが発生したため、サーバーへの安全な接続を確立できません。"; + diff --git a/firefox-ios/Shared/Supporting Files/kab.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/kab.lproj/EnhancedTrackingProtection.strings index 6d7dd4f17d0e..6d74b8d750ed 100644 --- a/firefox-ios/Shared/Supporting Files/kab.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/kab.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Tuqqna taraɣelsant"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Ulac ineḍfaren i yettwafen"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Inagan n tuqqna i uḍfaṛ gar yismal: %@"; @@ -43,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Tsenseḍ ammesten"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Tettummestneḍ. Ma yella ncukk deg kra, ad ak-d-nini."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "Tuqqna-inek d taraɣelsant."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Ḥader asmel-a"; diff --git a/firefox-ios/Shared/Supporting Files/kab.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/kab.lproj/Microsurvey.strings index 1acd77db5c44..2c54c3fac8e7 100644 --- a/firefox-ios/Shared/Supporting Files/kab.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/kab.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Ur yettwafran ara"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Aḥedqis"; + diff --git a/firefox-ios/Shared/Supporting Files/kab.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/kab.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..88bf07e9b5af --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/kab.lproj/NativeErrorPage.strings @@ -0,0 +1,9 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "Smiren"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "Teḍra-d tuccḍa SSL, tuqqna taɣellsant akked uqeddac tegguma ad teqεed."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "Ḥader. Yella wayen ur nteddu ara akken ilaq."; + diff --git a/firefox-ios/Shared/Supporting Files/kab.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/kab.lproj/Settings.strings index 3178d09c1af2..cdd6453b832b 100644 --- a/firefox-ios/Shared/Supporting Files/kab.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/kab.lproj/Settings.strings @@ -1,6 +1,15 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Sefrek tansiwin"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "Tansa i %@"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "TANSIWIN I YETTWASKELSEN"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Sekles tansiwin i %@"; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "Seddu ula uṭṭunen n tiliɣri d tansiwin n yimayl"; diff --git a/firefox-ios/Shared/Supporting Files/kab.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/kab.lproj/Toolbar.strings index 143a987fc343..753a6ffd5cde 100644 --- a/firefox-ios/Shared/Supporting Files/kab.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/kab.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Iccer amaynut"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Mdel iccer-a"; + diff --git a/firefox-ios/Shared/Supporting Files/kk.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/kk.lproj/EnhancedTrackingProtection.strings index 15d422718540..153d270337f4 100644 --- a/firefox-ios/Shared/Supporting Files/kk.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/kk.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Сіз қорғаныстарды өшірдіңіз"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Сіз қорғалғансыз. Бірдеңені байқасақ, сізге хабарлаймыз."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "Сіздің байланысыңыз қауіпсіз емес."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Бұл сайтта абай болыңыз"; diff --git a/firefox-ios/Shared/Supporting Files/kk.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/kk.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..56829ca548af --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/kk.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "Қайта жүктеу"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "SSL қатесі орын алды және серверге қауіпсіз байланысу мүмкін емес."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "Сақ болыңыз. Бірдеңе дұрыс емес сияқты."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "Басқа құрылғыда қосылып көріңіз. Модемді немесе маршрутизаторды тексеріңіз. Wi-Fi желісіне байланысты ажыратыңыз және қайта қосылыңыз."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "Интернет байланысыңызда мәселе бар сияқты."; + diff --git a/firefox-ios/Shared/Supporting Files/kk.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/kk.lproj/Settings.strings index 7a8cebdc02d9..e503f9211ee2 100644 --- a/firefox-ios/Shared/Supporting Files/kk.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/kk.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Адрестерді басқару"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "%@ үшін адрес"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "САҚТАЛҒАН АДРЕСТЕР"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Адрестерді %@ ішіне сақтау"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "Кейінірек жылдам қол жеткізу үшін ақпаратыңызды қауіпсіз сақтаңыз."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "Телефон нөмірлері мен электрондық пошта адрестерін қамтиды"; diff --git a/firefox-ios/Shared/Supporting Files/ko.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/ko.lproj/EnhancedTrackingProtection.strings index 6166d612cc83..4fe6162b4c28 100644 --- a/firefox-ios/Shared/Supporting Files/ko.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/ko.lproj/EnhancedTrackingProtection.strings @@ -46,8 +46,7 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "보호 기능을 사용 중지했습니다."; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "보호받고 있습니다. 뭔가를 발견하면 알려드리겠습니다."; /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ diff --git a/firefox-ios/Shared/Supporting Files/nb.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/nb.lproj/EnhancedTrackingProtection.strings index c1ba2097de4d..c25c87785d64 100644 --- a/firefox-ios/Shared/Supporting Files/nb.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/nb.lproj/EnhancedTrackingProtection.strings @@ -46,8 +46,7 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Du har slått av beskyttelse"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Du er beskyttet. Om vi oppdager noe sier vi ifra."; /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ diff --git a/firefox-ios/Shared/Supporting Files/nl.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/nl.lproj/EnhancedTrackingProtection.strings index aca50e279ff4..f8e494d2d8c5 100644 --- a/firefox-ios/Shared/Supporting Files/nl.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/nl.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Verbinding niet beveiligd"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Geen trackers gevonden"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Cross-site-trackingcookies: %@"; @@ -43,8 +46,7 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "U hebt beschermingen uitgeschakeld"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "U bent beschermd. Als we iets ontdekken, laten we u dat weten."; /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ diff --git a/firefox-ios/Shared/Supporting Files/nn.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/nn.lproj/EnhancedTrackingProtection.strings index cdd322017fad..729c4301c0b1 100644 --- a/firefox-ios/Shared/Supporting Files/nn.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/nn.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Du har slått av vern"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Du er verna. Om vi oppdagar noko seier vi ifrå."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "Tilkoplinga di er ikkje trygg."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Ver forsiktig på denne nettstaden"; diff --git a/firefox-ios/Shared/Supporting Files/nn.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/nn.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..c3ecadb4df60 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/nn.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "Oppdater"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "Det har oppstått ein SSL-feil og ei sikker tilkopling til sørvaren kan ikkje opprettast."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "Ver varsam. Noko ser ikkje rett ut."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "Prøv å kople til på ei anna eining. Sjekk modemet eller ruteren. Kople frå og kople til Wi-fi igjen."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "Det ser ut til at det er eit problem med internett-tilkoplinga di."; + diff --git a/firefox-ios/Shared/Supporting Files/nn.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/nn.lproj/Settings.strings index 48feb496d21a..650ace073f0a 100644 --- a/firefox-ios/Shared/Supporting Files/nn.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/nn.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Handsam adresser"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "Adresse for %@"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "LAGRA ADRESSER"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Lagre adresser ti %@"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "Lagre informasjonen din på ein sikker måte for å få rask tilgang til den seinare."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "Inkluderer telefonnummer og e-postadresser"; diff --git a/firefox-ios/Shared/Supporting Files/pa-IN.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/pa-IN.lproj/EnhancedTrackingProtection.strings index b70d4cb411fd..b57bab1a1968 100644 --- a/firefox-ios/Shared/Supporting Files/pa-IN.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/pa-IN.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "ਤੁਸੀਂ ਸੁਰੱਖਿਆਵਾਂ ਨੂੰ ਬੰਦ ਕੀਤਾ ਹੈ"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "ਤੁਸੀਂ ਸੁਰੱਖਿਅਤ ਹੋ। ਜੇ ਸਾਨੂੰ ਕੁਝ ਲੱਭਿਆ ਤਾਂ ਅਸੀਂ ਤੁਹਾਨੂੰ ਦੱਸਾਂਗੇ।"; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "ਤੁਹਾਡਾ ਕਨੈਕਸ਼ਨ ਸੁਰੱਖਿਅਤ ਨਹੀਂ ਹੈ।"; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "ਇਸ ਸਾਈਟ ਤੋਂ ਸਾਵਧਾਨ ਰਹੋ"; diff --git a/firefox-ios/Shared/Supporting Files/pa-IN.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/pa-IN.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..0a1ae13d967b --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/pa-IN.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "ਮੁੜ-ਲੋਡ"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "ਇੱਕ SSL ਗਲਤੀ ਆਈ ਹੈ ਅਤੇ ਸਰਵਰ ਨਾਲ ਸੁਰੱਖਿਅਤ ਕਨੈਕਸ਼ਨ ਨਹੀਂ ਬਣਾਇਆ ਜਾ ਸਕਦਾ ਹੈ।"; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "ਧਿਆਨ ਰੱਖੋ। ਕੁਝ ਸਹੀ ਨਹੀਂ ਜਾਪਦਾ ਹੈ।"; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "ਵੱਖਰੇ ਡਿਵਾਈਸ ਨਾਲ ਕਨੈਕਟ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੋ। ਆਪਣੇ ਮਾਡਮ ਜਾਂ ਰਾਊਟਰ ਦੀ ਜਾਂਚ ਕਰੋ। Wi-Fi ਤੋਂ ਡਿਸ-ਕਨੈਕਟ ਕਰਕੇ ਫੇਰ ਕਨੈਕਟ ਕਰੋ।"; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "ਤੁਹਾਡੇ ਇੰਟਰਨੈੱਟ ਕਨੈਕਸ਼ਨ ਨਾਲ ਸਮੱਸਿਆ ਜਾਪਦੀ ਹੈ।"; + diff --git a/firefox-ios/Shared/Supporting Files/pa-IN.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/pa-IN.lproj/Settings.strings index 891bd0b305fb..1846d5c389b5 100644 --- a/firefox-ios/Shared/Supporting Files/pa-IN.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/pa-IN.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "ਸਿਰਨਾਵਿਆਂ ਦਾ ਇੰਤਜ਼ਾਮ ਕਰੋ"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "%@ ਲਈ ਸਿਰਨਾਵਾਂ"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "ਸੰਭਾਲੇ ਹੋਏ ਸਿਰਨਾਵੇਂ"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "%@ ਲਈ ਸਿਰਨਾਵੇਂ ਨੂੰ ਸੰਭਾਲੋ"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "ਆਪਣੀ ਜਾਣਕਾਰੀ ਨੂੰ ਮੁੜ ਕੇ ਫ਼ੌਰਨ ਵਰਤਣ ਲਈ ਆਪਣੀ ਜਾਣਕਾਰੀ ਨੂੰ ਸੁਰੱਖਿਅਤ ਢੰਗ ਨਾਲ ਸੰਭਾਲੋ।"; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "ਫ਼ੋਨ ਨੰਬਰਾਂ ਅਤੇ ਈਮੇਲ ਸਿਰਨਾਵਿਆਂ ਸਮੇਤ"; diff --git a/firefox-ios/Shared/Supporting Files/pl.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/pl.lproj/EnhancedTrackingProtection.strings index 15290c3cf1b2..f25c12ac87a2 100644 --- a/firefox-ios/Shared/Supporting Files/pl.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/pl.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Niezabezpieczone połączenie"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Nie znaleziono żadnych elementów śledzących"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Ciasteczka śledzące między witrynami: %@"; @@ -43,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Wyłączono ochronę"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Ochrona jest włączona. Jeśli coś zauważymy, damy Ci znać."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "Połączenie nie jest zabezpieczone."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Zachowaj ostrożność na tej witrynie"; diff --git a/firefox-ios/Shared/Supporting Files/pl.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/pl.lproj/Microsurvey.strings index d8d0b65b71aa..a02df5a96ab3 100644 --- a/firefox-ios/Shared/Supporting Files/pl.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/pl.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Nie zaznaczone"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Ankieta"; + diff --git a/firefox-ios/Shared/Supporting Files/pl.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/pl.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..a6ed4b346454 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/pl.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "Wczytaj ponownie"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "Wystąpił błąd SSL i nie można nawiązać zabezpieczonego połączenia z serwerem."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "Zachowaj ostrożność. Coś tu nie gra."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "Spróbuj połączyć się na innym urządzeniu. Sprawdź modem lub router. Rozłącz się i ponownie połącz z siecią Wi-Fi."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "Wystąpił problem z połączeniem z Internetem."; + diff --git a/firefox-ios/Shared/Supporting Files/pl.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/pl.lproj/Settings.strings index fcbe938cd8ed..c3c65f001ff1 100644 --- a/firefox-ios/Shared/Supporting Files/pl.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/pl.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Zarządzaj adresami"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "Adres dla „%@”"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "Zachowane adresy"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Zachowuj adresy w przeglądarce %@"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "Bezpiecznie zachowuj swoje dane, aby później mieć do nich szybki dostęp."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "W tym numery telefonów i adresy e-mail"; diff --git a/firefox-ios/Shared/Supporting Files/pl.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/pl.lproj/Toolbar.strings index 0cabac60c3a7..68e4bc3db0b3 100644 --- a/firefox-ios/Shared/Supporting Files/pl.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/pl.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Nowa karta"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Zamknij tę kartę"; + diff --git a/firefox-ios/Shared/Supporting Files/pt-BR.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/pt-BR.lproj/EnhancedTrackingProtection.strings index 967245e5d29a..2db5546d452d 100644 --- a/firefox-ios/Shared/Supporting Files/pt-BR.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/pt-BR.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Você desativou proteções"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Você está protegido. Se detectarmos algo, avisaremos você."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "Sua conexão não é segura."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Tenha cuidado neste site"; diff --git a/firefox-ios/Shared/Supporting Files/pt-BR.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/pt-BR.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..f22292ec0249 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/pt-BR.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "Recarregar"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "Ocorreu um erro de SSL e não foi possível estabelecer uma conexão segura com o servidor."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "Tenha cuidado. Algo não parece estar certo."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "Experimente se conectar usando outro dispositivo. Verifique seu modem ou roteador. Desconecte e reconecte ao WiFi."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "Parece que há um problema na sua conexão com a internet."; + diff --git a/firefox-ios/Shared/Supporting Files/pt-BR.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/pt-BR.lproj/Settings.strings index e8b9588a7d29..28cf8903ebf4 100644 --- a/firefox-ios/Shared/Supporting Files/pt-BR.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/pt-BR.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Gerenciar endereços"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "Endereço de %@"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "ENDEREÇOS SALVOS"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Salvar endereços no %@"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "Salvar suas informações com segurança para ter acesso rápido a elas mais tarde."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "Incluir números de telefone e endereços de email"; diff --git a/firefox-ios/Shared/Supporting Files/pt-PT.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/pt-PT.lproj/EnhancedTrackingProtection.strings index 9e306740d0b9..b6ae16087aa9 100644 --- a/firefox-ios/Shared/Supporting Files/pt-PT.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/pt-PT.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Desativou as proteções"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Está protegido. Se detetarmos algo, iremos fornecer-lhe essa informação."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "A sua ligação não é segura."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Tenha cuidado neste site"; diff --git a/firefox-ios/Shared/Supporting Files/pt-PT.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/pt-PT.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..6f9a2764824d --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/pt-PT.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "Recarregar"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "Ocorreu um erro de SSL e não foi possível estabelecer uma ligação segura com o servidor."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "Tenha cuidado. Algo não parece bem."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "Tente ligar-se num dispositivo diferente. Verifique o seu modem ou router. Desligue-se e volte a ligar-se ao Wi-Fi."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "Parece que há um problema com a sua ligação à Internet."; + diff --git a/firefox-ios/Shared/Supporting Files/pt-PT.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/pt-PT.lproj/Settings.strings index 66f31fc9d05e..4e9b68793000 100644 --- a/firefox-ios/Shared/Supporting Files/pt-PT.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/pt-PT.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Gerir endereços"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "Endereço para %@"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "ENDEREÇOS GUARDADOS"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Guardar endereços no %@"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "Guarde a sua informação com segurança para obter acesso rápido à mesma mais tarde."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "Inclui números de telefone e endereços de e-mail"; diff --git a/firefox-ios/Shared/Supporting Files/rm.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/rm.lproj/EnhancedTrackingProtection.strings index 7c3f2dbe6615..649bb4f8df3a 100644 --- a/firefox-ios/Shared/Supporting Files/rm.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/rm.lproj/EnhancedTrackingProtection.strings @@ -43,8 +43,7 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Ti has deactivà las protecziuns"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Ti es protegì. Sche nus scuvrin insatge, t’infurmain nus."; /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ diff --git a/firefox-ios/Shared/Supporting Files/ru.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/ru.lproj/EnhancedTrackingProtection.strings index eacf941173c6..34bd742d18e7 100644 --- a/firefox-ios/Shared/Supporting Files/ru.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/ru.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Вы отключили защиту"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Вы защищены. Если мы что-то заметим, мы сообщим вам."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "Ваше соединение не защищено."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Будьте осторожны на этом сайте"; diff --git a/firefox-ios/Shared/Supporting Files/ru.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/ru.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..db4dc6871dc2 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/ru.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "Обновить"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "Произошла ошибка SSL, и не удалось установить защищённое соединение с сервером."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "Будьте осторожны. Что-то выглядит неправильно."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "Попробуйте подключиться на другом устройстве. Проверьте ваш модем или маршрутизатор. Отключитесь и снова подключитесь к Wi-Fi."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "Похоже, есть проблема с вашим интернет-соединением."; + diff --git a/firefox-ios/Shared/Supporting Files/ru.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/ru.lproj/Settings.strings index 8b0218ae8910..ee1358dca57b 100644 --- a/firefox-ios/Shared/Supporting Files/ru.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/ru.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Управление адресами"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "Адрес для %@"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "СОХРАНЁННЫЕ АДРЕСА"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Сохранять адреса в %@"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "Надежно сохраните вашу информацию, чтобы получить к ней быстрый доступ в будущем."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "Включает номера телефонов и адреса электронной почты"; diff --git a/firefox-ios/Shared/Supporting Files/sk.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/sk.lproj/EnhancedTrackingProtection.strings index 2feb454e52ce..864a78a82dd7 100644 --- a/firefox-ios/Shared/Supporting Files/sk.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/sk.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Ochrana je vypnutá"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Ste chránení. Ak niečo zistíme, dáme vám vedieť."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "Vaše pripojenie nie je zabezpečené."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Buďte opatrní na tejto stránke"; diff --git a/firefox-ios/Shared/Supporting Files/sk.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/sk.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..8f31cda145dd --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/sk.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "Obnoviť"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "Vyskytla sa chyba SSL a nie je možné vytvoriť zabezpečené pripojenie k serveru."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "Buďte opatrní. Niečo nie je v poriadku."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "Skúste sa pripojiť na inom zariadení. Skontrolujte modem alebo smerovač. Odpojte sa a znova sa pripojte k sieti Wi-Fi."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "Zdá sa, že sa vyskytol problém s vaším internetovým pripojením."; + diff --git a/firefox-ios/Shared/Supporting Files/sk.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/sk.lproj/Settings.strings index 4bcba1675ebd..b53845a4ce94 100644 --- a/firefox-ios/Shared/Supporting Files/sk.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/sk.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Spravovať adresy"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "Adresa pre %@"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "ULOŽENÉ ADRESY"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Uložiť adresy do %@u"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "Bezpečne si uložte svoje informácie, aby ste k nim neskôr mali rýchly prístup."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "Zahŕňa telefónne čísla a e‑mailové adresy"; diff --git a/firefox-ios/Shared/Supporting Files/sl.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/sl.lproj/EnhancedTrackingProtection.strings index 0fda15ff5683..fa537a86a7bd 100644 --- a/firefox-ios/Shared/Supporting Files/sl.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/sl.lproj/EnhancedTrackingProtection.strings @@ -22,6 +22,9 @@ /* Text to let users know that the current website is not secure. */ "Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Povezava ni varna"; +/* Text to let users know that no trackers were found on the current website. */ +"Menu.EnhancedTrackingProtection.Details.NoTrackers.v131" = "Ni najdenih sledilcev"; + /* Text to let users know how many cross-site tracking cookies were blocked on the current website. The placeholder will show the number of such cookies detected */ "Menu.EnhancedTrackingProtection.Details.Trackers.CrossSite.v129" = "Piškotkov za sledenje med spletnimi mesti: %@"; @@ -43,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Zaščito ste izključili"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Zaščiteni ste. Če kaj opazimo, vas obvestimo."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "Vaša povezava ni varna."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Previdno na tem spletnem mestu"; diff --git a/firefox-ios/Shared/Supporting Files/sl.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/sl.lproj/Microsurvey.strings index a3da1bdaecdd..b58438bcbc65 100644 --- a/firefox-ios/Shared/Supporting Files/sl.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/sl.lproj/Microsurvey.strings @@ -67,3 +67,6 @@ /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ "Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Neizbrano"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Anketa"; + diff --git a/firefox-ios/Shared/Supporting Files/sl.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/sl.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..eb118bc21494 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/sl.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "Ponovno naloži"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "Prišlo je do napake SSL, zaradi katere ni mogoče vzpostaviti varne povezave s strežnikom."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "Previdno. Nekaj ni videti v redu."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "Poskusite se povezati z drugo napravo. Preverite modem ali usmerjevalnik. Odklopite se in se ponovno povežite z Wi-Fi."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "Videti je, da obstaja težava z vašo internetno povezavo."; + diff --git a/firefox-ios/Shared/Supporting Files/sl.lproj/Onboarding.strings b/firefox-ios/Shared/Supporting Files/sl.lproj/Onboarding.strings index 91f3c0464c33..bcad1e6ca0f5 100644 --- a/firefox-ios/Shared/Supporting Files/sl.lproj/Onboarding.strings +++ b/firefox-ios/Shared/Supporting Files/sl.lproj/Onboarding.strings @@ -19,6 +19,9 @@ /* String used to describe the option to continue to the next onboarding card in Firefox Onboarding screens. Placeholder is for the app name. */ "Onboarding.Customization.Intro.Continue.Action.v123" = "Prilagodi %@"; +/* String used to describe the description label of the customization onboarding page in our Onboarding screens. */ +"Onboarding.Customization.Intro.Description.v123" = "Izberite si temo in orodno vrstico, ki se bo ujemala z vašim edinstvenim slogom brskanja."; + /* String used to describe the option to skip the customization cards in Firefox Onboarding screens and start browsing. */ "Onboarding.Customization.Intro.Skip.Action.v123" = "Začnite brskati"; @@ -91,6 +94,9 @@ /* String used to describes the description of what Firefox is on the Sync onboarding page for current version in our Onboarding screens. Placeholder is for the app name. */ "Onboarding.Sync.Description.v120" = "Prijavljeni in sinhronizirani ste varnejši. %@ šifrira vaša gesla, zaznamke in ostale podatke."; +/* String used to describes the description of what Firefox is on the Sync onboarding page for current version in our Onboarding screens. Placeholder is for the app name. */ +"Onboarding.Sync.Description.v123" = "%@ ob vključeni sinhronizaciji šifrira vaša gesla, zaznamke in drugo."; + /* String used to describes the option to skip the Sync sign in during onboarding for the current version in Firefox Onboarding screens. */ "Onboarding.Sync.SignIn.Action.v114" = "Prijava"; diff --git a/firefox-ios/Shared/Supporting Files/sl.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/sl.lproj/Settings.strings index 024e3ec29e9b..812d48e3af7e 100644 --- a/firefox-ios/Shared/Supporting Files/sl.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/sl.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Upravljanje naslovov"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "Naslov za %@"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "SHRANJENI NASLOVI"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Shranjuj naslove v %@"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "Varno si shranite podatke za kasnejši hiter dostop."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "Vključuje telefonske številke in e-poštne naslove"; @@ -94,6 +106,9 @@ /* Title for alternate search engines settings section in the Search page in the Settings menu. */ "Settings.Search.AlternateSearchEngines.Title.v124.v2" = "Pomožni iskalniki"; +/* Footer for the `default search engine` settings section in the Search Settings page, which explains in more details what the `Show Search Suggestions` setting includes. */ +"Settings.Search.DefaultSearchEngine.Footer.v122" = "Rezultati iskanja, zgodovine, zaznamkov in drugo"; + /* Title for the `default search engine` settings section in the Search page in the Settings menu. */ "Settings.Search.DefaultSearchEngine.Title.v121" = "Privzeti iskalnik"; @@ -154,3 +169,6 @@ /* In the Search page of the Settings menu, the description for the setting to enable Suggestions from sponsors. Placeholder is for the app name - Firefox. */ "Settings.Search.Suggest.ShowSponsoredSuggestions.Description.v124" = "Podprite %@ z občasnimi sponzoriranimi predlogi"; +/* In the Search page of the Settings menu, the title for the setting to enable Suggestions from sponsors. */ +"Settings.Search.Suggest.ShowSponsoredSuggestions.Title.v124" = "Predlogi sponzorjev"; + diff --git a/firefox-ios/Shared/Supporting Files/sl.lproj/Shopping.strings b/firefox-ios/Shared/Supporting Files/sl.lproj/Shopping.strings index d9be01264e20..36b44801b085 100644 --- a/firefox-ios/Shared/Supporting Files/sl.lproj/Shopping.strings +++ b/firefox-ios/Shared/Supporting Files/sl.lproj/Shopping.strings @@ -1,12 +1,48 @@ +/* Contextual hints are little popups that appear for the users informing them of new features. This one indicates that a user can tap on the shopping button to start using the Shopping feature. */ +"ContextualHints.Shopping.NotOptedIn.v120" = "Pred nakupom se pozanimajte, ali lahko zaupate mnenjem o tem izdelku."; + +/* Contextual hints are little popups that appear for the users informing them of new features. This one is a call to action for the popup describing the Shopping feature. It indicates that a user can go directly to the Shopping feature by tapping the text of the action. */ +"ContextualHints.Shopping.NotOptedInAction.v120" = "Preizkusite pregledovalnik mnenj"; + +/* Contextual hints are little popups that appear for the users informing them of new features. This is a call to action for the popup that appears after the user has opted in for the Shopping feature. It indicates that a user can directly open the review checker by tapping the text of the action. */ +"ContextualHints.Shopping.OptedInAction.v120" = "Odpri pregledovalnik mnenj"; + +/* Contextual hints are little popups that appear for the users informing them of new features. This one appears after the user has opted in and informs him if he wants use the review checker by tapping the Shopping button. */ +"ContextualHints.Shopping.OptedInBody.v120" = "Ali so ta mnenja zanesljiva? Preverite zdaj za ogled prilagojene ocene."; + +/* Footer label from the Fakespot Ad card displayed for the related product we advertise. This is displayed below the ad card, suggested as an alternative to the product reviewed. The first parameter will be replaced by the Fakespot app name */ +"Shopping.AdCard.Footer.v121" = "Naročnik oglasa je %@"; + +/* Title label for the Fakespot Ad card. This is displayed above a product image, suggested as an alternative to the product reviewed. */ +"Shopping.AdCard.Title.v121" = "Več za razmislek"; + +/* Description adjusted of the rating card displayed in the shopping review quality bottom sheet. */ +"Shopping.AdjustedRating.Description.v121" = "Temelji na zanesljivih mnenjih"; + +/* Accessibility label, associated to adjusted rating stars. %@ is a decimal value from 0 to 5 that will only use a tenth (example: 3.5). */ +"Shopping.AdjustedRating.StarsAccessibilityLabel.v120" = "%@ od 5 zvezdic"; + +/* Title of the adjusted rating card displayed in the shopping review quality bottom sheet. */ +"Shopping.AdjustedRating.Title.v120" = "Prilagojena ocena"; + /* Button text of the confirmation displayed in the shopping review quality bottom sheet. */ "Shopping.ConfirmationCard.Button.Text.v120" = "Razumem"; +/* Title of the confirmation displayed in the shopping review quality bottom sheet. */ +"Shopping.ConfirmationCard.Title.v120" = "Analiza je posodobljena"; + +/* Section title of the review highlights displayed in the shopping review quality bottom sheet. */ +"Shopping.HighlightsCard.Competitiveness.Title.v120" = "Konkurenčnost"; + /* Title of the button that shows less reviews in the review highlights displayed in the shopping review quality bottom sheet. */ "Shopping.HighlightsCard.LessButton.Title.v120" = "Prikaži manj"; /* Title of the button that shows more reviews in the review highlights displayed in the shopping review quality bottom sheet. */ "Shopping.HighlightsCard.MoreButton.Title.v120" = "Prikaži več"; +/* Section title of the review highlights displayed in the shopping review quality bottom sheet, specifically focusing on the quality, design, and condition of the product's packaging. This may include details about the box, protective materials, presentation, and overall packaging experience. */ +"Shopping.HighlightsCard.Packaging.Title.v120" = "Embalaža"; + /* Section title of the review highlights displayed in the shopping review quality bottom sheet. */ "Shopping.HighlightsCard.Price.Title.v120" = "Cena"; @@ -19,18 +55,198 @@ /* Title of the review highlights displayed in the shopping review quality bottom sheet. */ "Shopping.HighlightsCard.Title.v120" = "Poudarki iz nedavnih mnenj"; +/* Title for info card when Fakespot cannot analyze reviews for a certain product type */ +"Shopping.InfoCard.FakespotDoesNotAnalyzeReviews.Description.v120" = "Za nekatere vrste izdelkov žal ne moremo preveriti kakovosti mnenj. Na primer za darilne kartice ter pretočne videe, glasbo in igre."; + +/* Title for info card when Fakespot cannot analyze reviews for a certain product type */ +"Shopping.InfoCard.FakespotDoesNotAnalyzeReviews.Title.v120" = "Teh mnenj ne moremo preveriti"; + +/* Description text for an information card used in the review checker section. This message is displayed when the reviews for a product are not yet available but are expected to be provided within the next 24 hours. It serves to inform users of the short wait for reviews and encourages them to return soon for the updated information. */ +"Shopping.InfoCard.InfoComingSoon.Description.v121" = "Podatki o mnenjih za ta izdelek bi morali biti pripravljeni v 24 urah. Preverite znova kasneje."; + +/* Title for an information card that is displayed in the review checker section when certain details about a product or feature are not currently available but are expected to be provided soon. The message should imply that the user can look forward to receiving more information shortly. */ +"Shopping.InfoCard.InfoComingSoon.Title.v121" = "Kmalu bo na voljo še več vsebine"; + +/* Primary action title for info card when the product needs analysis */ +"Shopping.InfoCard.NeedsAnalysis.PrimaryAction.v120" = "Preveri zdaj"; + +/* Title for info card when the product needs analysis */ +"Shopping.InfoCard.NeedsAnalysis.Title.v120" = "Novi podatki za pregled"; + +/* Description for info card when no information is available at the moment */ +"Shopping.InfoCard.NoInfoAvailableRightNow.Description.v120" = "Poskušamo odpraviti težavo. Preverite znova pozneje."; + +/* Title for info card when no information is available at the moment */ +"Shopping.InfoCard.NoInfoAvailableRightNow.Title.v120" = "Trenutno ni na voljo nobenih podatkov"; + +/* Description for info card when there are not enough reviews for a product */ +"Shopping.InfoCard.NotEnoughReviews.Description.v120" = "Ko bo za ta izdelek na voljo več mnenj, bomo lahko preverili njihovo kakovost."; + +/* Title for info card when there are not enough reviews for a product */ +"Shopping.InfoCard.NotEnoughReviews.Title.v120" = "Ni še dovolj mnenj"; + +/* Description for the information card displayed by the review checker feature when the product the user is looking at is out of stock. This description is used for info card where the user can report if it's back in stock. */ +"Shopping.InfoCard.ProductNotInStock.Description.v121" = "Če opazite, da je izdelek znova na zalogi, nam to sporočite in preverili bomo mnenja."; + +/* Primary action label for the information card displayed by the review checker feature when the product the user is looking at is out of stock. This primary action label is used for info card button where the user can report if it's back in stock. */ +"Shopping.InfoCard.ProductNotInStock.PrimaryAction.v121" = "Sporoči, da je izdelek znova na zalogi"; + +/* Title for the information card displayed by the review checker feature when the product the user is looking at is out of stock. This title is used for info card where the user can report if it's back in stock. */ +"Shopping.InfoCard.ProductNotInStock.Title.v121" = "Izdelek ni na voljo"; + +/* Description for info card when the product is in analysis mode */ +"Shopping.InfoCard.ProgressAnalysis.Description.v120" = "To lahko traja približno 60 sekund."; + +/* Title for info card when the product is in analysis mode */ +"Shopping.InfoCard.ProgressAnalysis.Title.v120" = "Preverjanje kakovosti mnenj"; + +/* Title for info card when the product is in analysis mode. The placeholder represents the percentage of the analysis progress, ranging between 1 and 100. */ +"Shopping.InfoCard.ProgressAnalysis.Title.v123" = "Preverjanje kakovosti mnenj (%@)"; + +/* This description appears beneath the confirmation title on the information card to inform the user that their report regarding the product stock status has been received and is being processed. It serves to set the expectation that the review information will be updated within 24 hours and invites the user to revisit the product page for updates. */ +"Shopping.InfoCard.ReportSubmittedByCurrentUser.Description.v121" = "Podatki o mnenjih za ta izdelek bi morali biti pripravljeni v 24 urah. Preverite znova kasneje."; + +/* This title is displayed on the information card as a confirmation message after a user reports that a previously out-of-stock product is now available. It's meant to acknowledge the user's contribution and encourage community engagement by letting them know their report has been successfully submitted. */ +"Shopping.InfoCard.ReportSubmittedByCurrentUser.Title.v121" = "Hvala za sporočilo!"; + +/* Text for the analyzer button displayed when an analysis can be updated for a product. */ +"Shopping.NoAnalysisCard.AnalyzerButton.Title.v120" = "Preveri kakovost mnenj"; + +/* Text for the body label, to check the reliability of a product. */ +"Shopping.NoAnalysisCard.BodyLabel.Title.v120" = "Če želite preveriti, ali so ocene tega izdelka zanesljive, preverite kakovost mnenj. Traja le približno 60 sekund."; + +/* Title for card displayed when a shopping product has not been analysed yet. */ +"Shopping.NoAnalysisCard.HeadlineLabel.Title.v120" = "O teh mnenjih še ni podatkov"; + +/* Text for the disclaimer that appears underneath the rating image of the Shopping Experience Opt In onboarding Card (Fakespot). The parameter will be replaced by the Fakespot app name. After the colon, what appears are two links, each on their own line. The first link is to a Privacy policy. The second link is to Terms of use. */ +"Shopping.OptInCard.Disclaimer.Text.v120" = "Z izbiro “Da, poskusi” se strinjate z naslednjimi dokumenti %@a:"; + +/* Text for the disclaimer that appears underneath the rating image of the Shopping Experience Opt In onboarding Card (Fakespot). After the colon, there will be two links, each on their own line. The first link is to a Privacy policy. The second link is to Terms of use. */ +"Shopping.OptInCard.Disclaimer.Text.v123" = "Z izbiro “Da, poskusi” se strinjate z naslednjimi dokumenti:"; + +/* Label for the first paragraph of the Shopping Experience Opt In onboarding Card (Fakespot). The first parameter will be the website the user is coming from when viewing this screen (default Amazon). The second parameter will be replaced by the app name. This string is almost identical with 'Shopping.OptInCard.FirstParagraph.Description', but without Best Buy and Walmart websites, which are not available in many locales. */ +"Shopping.OptInCard.FirstParagraph.AmazonOnly.Description.v122" = "Pred nakupom preverite, kako zanesljiva so mnenja o izdelkih v trgovini %1$@. Pregledovalnik mnenj, preizkusna zmogljivost %2$@a, je vgrajen neposredno v brskalnik."; + +/* Label for the first paragraph of the Shopping Experience Opt In onboarding Card (Fakespot). The first parameter will be the website the user is coming from when viewing this screen (default Amazon). The second parameter will be replaced by the app name. The third and fourth parameters will be the other two websites that are currently supported (Amazon, Best Buy or Walmart) besides the one used for the first parameter. */ +"Shopping.OptInCard.FirstParagraph.Description.v120" = "Pred nakupom preverite, kako zanesljiva so mnenja o izdelkih v trgovini %1$@. Pregledovalnik mnenj, preizkusna zmogljivost %2$@a, je vgrajen neposredno v brskalnik. Deluje tudi v trgovinah %3$@ in %4$@."; + +/* Label for the header of the Shopping Experience Opt In onboarding Card (Fakespot) */ +"Shopping.OptInCard.HeaderLabel.Title.v120" = "Preizkusite naš zaupanja vreden vodnik po ocenah izdelkov"; + /* Label for the Learn more button in the Shopping Experience Opt In onboarding Card (Fakespot) */ "Shopping.OptInCard.LearnMoreButtonTitle.Title.v120" = "Več o tem"; +/* Text for the main button of the Shopping Experience Opt In onboarding Card (Fakespot) */ +"Shopping.OptInCard.MainButton.Title.v120" = "Da, poskusi"; + +/* Show Firefox Browser Privacy Policy page from the Privacy section in the Shopping Experience Opt In onboarding Card (Fakespot). See https://www.mozilla.org/privacy/firefox/ */ +"Shopping.OptInCard.PrivacyPolicy.Button.Title.v120" = "Pravilnik o zasebnosti"; + +/* Show Firefox Browser Privacy Policy page from the Privacy section in the Shopping Experience Opt In onboarding Card (Fakespot). The parameter will be replace by the Firefox app name. */ +"Shopping.OptInCard.PrivacyPolicy.Button.Title.v123" = "Obvestilo o zasebnosti %@a"; + /* Text for the secondary button of the Shopping Experience Opt In onboarding Card (Fakespot) */ "Shopping.OptInCard.SecondaryButton.Title.v120" = "Ne zdaj"; +/* Label for the second paragraph of the Shopping Experience Opt In onboarding Card (Fakespot). The first parameter will be replaced by the Fakespot app name. The second parameter will be replaced the company name of Mozilla. */ +"Shopping.OptInCard.SecondParagraph.Description.v120" = "%2$@ %1$@ vam omogoča, da se izognete pristranskim in nepristnim mnenjem. Naš model umetne inteligence se nenehno izboljšuje, da vas ščiti med nakupovanjem."; + /* Show Firefox Browser Terms of Use page from the Privacy section in the Shopping Experience Opt In onboarding Card (Fakespot). See https://www.mozilla.org/privacy/firefox/ */ "Shopping.OptInCard.TermsOfUse.Button.Title.v120" = "Pogoji uporabe"; +/* Show Fakespot Terms of Use page in the Shopping Experience Opt In onboarding Card (Fakespot). The parameter will be replace by the Fakespot name. */ +"Shopping.OptInCard.TermsOfUse.Button.Title.v123" = "Pogoji uporabe %@a"; + +/* Accessibility label for the Grade labels used in 'How we determine review quality' card and 'How reliable are these reviews' card displayed in the shopping review quality bottom sheet. The placeholder will be replaced by a grade letter (e.g. A). The grading system contains letters from A-F. */ +"Shopping.ReliabilityScore.Grade.A11y.Label.v120" = "Ocena %@"; + +/* Title of the reliability card displayed in the shopping review quality bottom sheet. */ +"Shopping.ReviewQuality.ReliabilityCardTitle.v120" = "Kako zanesljiva so ta mnenja?"; + +/* Description of the reliability ratings for rating 'A' and 'B' displayed in the shopping review quality bottom sheet. */ +"Shopping.ReviewQuality.ReliabilityRating.AB.Description.v120" = "Zanesljiva mnenja"; + +/* Description of the reliability rating 'C' displayed in the shopping review quality bottom sheet. */ +"Shopping.ReviewQuality.ReliabilityRating.C.Description.v120" = "Mešanica zanesljivih in nezanesljivih mnenj"; + +/* Description of the reliability ratings for rating 'D' and 'F' displayed in the shopping review quality bottom sheet. */ +"Shopping.ReviewQuality.ReliabilityRating.DF.Description.v120" = "Nezanesljiva mnenja"; + +/* Adjusted rating label from How we determine review quality card displayed in the shopping review quality bottom sheet. The *text inside asterisks* denotes part of the string to bold, please leave the text inside the '*' so that it is bolded correctly. */ +"Shopping.ReviewQualityCard.AdjustedRating.Label.v120" = "*Prilagojena ocena* temelji samo na mnenjih, za katere menimo, da so zanesljiva."; + +/* Accessibility label for the up chevron, from 'How we determine review quality' card displayed in the shopping review quality bottom sheet. */ +"Shopping.ReviewQualityCard.Collapse.AccessibilityLabel.v120" = "Strani kartico Kako določamo kakovost mnenj"; + +/* Accessibility label for the down chevron, from 'How we determine review quality' card displayed in the shopping review quality bottom sheet. */ +"Shopping.ReviewQualityCard.Expand.AccessibilityLabel.v120" = "Razširi kartico Kako določamo kakovost mnenj"; + +/* Label of the headline from How we determine review quality card displayed in the shopping review quality bottom sheet. The first parameter will be replaced by the Fakespot app name and the second parameter by the company name of Mozilla. */ +"Shopping.ReviewQualityCard.Headline.Label.v120" = "Za preverjanje zanesljivosti mnenj o izdelkih uporabljamo tehnologijo umetne inteligence %2$@ %1$@. To vam bo pomagalo oceniti zgolj kakovost mnenja, ne pa tudi izdelka."; + +/* Highlights label from How we determine review quality card displayed in the shopping review quality bottom sheet. The parameter substitutes the partner website the user is coming from. The *text inside asterisks* denotes part of the string to bold, please leave the text inside the '*' so that it is bolded correctly. */ +"Shopping.ReviewQualityCard.Highlights.Label.v120" = "*Poudarki* so vzeti iz mnenj v trgovini %1@ v zadnjih 80. dneh, za katera menimo, da so zanesljiva."; + +/* Highlights label from How we determine review quality card displayed in the shopping review quality bottom sheet. The parameter substitutes the partner website the user is coming from. The *text inside asterisks* denotes part of the string to bold, please leave the text inside the '*' so that it is bolded correctly. */ +"Shopping.ReviewQualityCard.Highlights.Label.v126" = "*Poudarki* so vzeti iz mnenj v trgovini %@ v zadnjih 80. dneh, za katera menimo, da so zanesljiva."; + +/* Title of the 'How we determine review quality' card displayed in the shopping review quality bottom sheet. */ +"Shopping.ReviewQualityCard.Label.Title.v120" = "Kako določamo kakovost mnenj"; + +/* The title of the learn more button from How we determine review quality card displayed in the shopping review quality bottom sheet. The placeholder will be replaced with the Fakespot app name. */ +"Shopping.ReviewQualityCard.LearnMoreButton.Title.v120" = "Več o tem, kako %@ določa kakovost pregledov"; + +/* Mixed reviews label from How we determine review quality card displayed in the shopping review quality bottom sheet. */ +"Shopping.ReviewQualityCard.MixedReviews.Label.v120" = "Menimo, da obstaja mešanica zanesljivih in nezanesljivih mnenj"; + +/* Reliable reviews label from How we determine review quality card displayed in the shopping review quality bottom sheet. */ +"Shopping.ReviewQualityCard.ReliableReviews.Label.v120" = "Zanesljiva mnenja. Verjamemo, da so jih napisale resnične stranke, ki so pustile poštene in nepristranske ocene."; + +/* Label of the sub headline from How we determine review quality card displayed in the shopping review quality bottom sheet. The *text inside asterisks* denotes part of the string to bold, please leave the text inside the '*' so that it is bolded correctly. */ +"Shopping.ReviewQualityCard.SubHeadline.Label.v120" = "Vsako mnenje o izdelku ocenimo s *črkovno oceno* od A do F."; + +/* Unreliable reviews label from How we determine review quality card displayed in the shopping review quality bottom sheet. */ +"Shopping.ReviewQualityCard.UnreliableReviews.Label.v120" = "Nezanesljiva mnenja. Menimo, da so verjetno lažna ali pa so jih napisali pristranski ocenjevalci."; + +/* Accessibility label for the up chevron icon used to collapse or minimize the Settings Card within the shopping product review bottom sheet. */ +"Shopping.SettingsCard.Collapse.AccessibilityLabel.v120" = "Strni kartico z nastavitvami"; + +/* Accessibility label for the down chevron icon used to expand or show the details of the Settings Card within the shopping product review bottom sheet. */ +"Shopping.SettingsCard.Expand.AccessibilityLabel.v120" = "Razširi kartico z nastavitvami"; + +/* Accessibility hint for the recommended products label and switch, grouped together. When the group is selected in VoiceOver mode, the hint is read to help the user understand what action can be performed. */ +"Shopping.SettingsCard.Expand.GroupedRecommendedProductsAndSwitch.AccessibilityHint.v123" = "Dvotapnite za preklop nastavitve."; + +/* Accessibility label for the recommended products label and switch, grouped together. The first placeholder is for the recommended products label, and the second placeholder is for the state of the switch: On/Off. */ +"Shopping.SettingsCard.Expand.GroupedRecommendedProductsAndSwitch.AccessibilityLabel.v123" = "%1$@, preklopni gumb, %2$@."; + +/* Action title of the footer underneath the Settings Card displayed in the shopping review quality bottom sheet. The first parameter will be replaced by the Fakespot app name and the second parameter by the company name of Mozilla. */ +"Shopping.SettingsCard.Footer.Action.v120" = "Pregledovalnik mnenj uporablja tehnologijo %2$@ %1$@"; + /* Title of the settings card displayed in the shopping review quality bottom sheet. */ "Shopping.SettingsCard.Label.Title.v120" = "Nastavitve"; +/* Label of the switch from settings card displayed in the shopping review quality bottom sheet. The placeholder will be replaced with the app name. */ +"Shopping.SettingsCard.RecommendedProducts.Label.v120" = "Prikaži izdelke, ki jih priporoča %@"; + +/* Toggled Off accessibility switch value from Settings Card within the shopping product review bottom sheet. */ +"Shopping.SettingsCard.SwitchValueOff.AccessibilityLabel.v123" = "Izključeno"; + +/* Toggled On accessibility value, from Settings Card within the shopping product review bottom sheet. */ +"Shopping.SettingsCard.SwitchValueOn.AccessibilityLabel.v123" = "Vključeno"; + +/* Label of the button from settings card displayed in the shopping review quality bottom sheet. */ +"Shopping.SettingsCard.TurnOffButton.Title.v120" = "Izklopi pregledovalnik mnenj"; + +/* Beta label for the header of the Shopping Experience (Fakespot) sheet */ +"Shopping.Sheet.Beta.Title.v120" = "BETA"; + +/* Accessibility label for close button that dismisses the Shopping Experience (Fakespot) sheet. */ +"Shopping.Sheet.Close.AccessibilityLabel.v121" = "Zapri pregledovalnik mnenj"; + +/* Label for the header of the Shopping Experience (Fakespot) sheet */ +"Shopping.Sheet.Title.v120" = "Pregledovalnik mnenj"; + /* Text for body of error card displayed to the user when the device is disconnected from the network. */ "Shopping.WarningCard.CheckNoConnection.Description.v120" = "Preverite povezavo z omrežjem in poskusite znova naložiti stran."; diff --git a/firefox-ios/Shared/Supporting Files/sl.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/sl.lproj/Toolbar.strings index 0d6618af83fe..b1bc596d2c98 100644 --- a/firefox-ios/Shared/Supporting Files/sl.lproj/Toolbar.strings +++ b/firefox-ios/Shared/Supporting Files/sl.lproj/Toolbar.strings @@ -1,3 +1,6 @@ /* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ "Toolbar.NewTab.Button.v130" = "Nov zavihek"; +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Zapri zavihek"; + diff --git a/firefox-ios/Shared/Supporting Files/sq.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/sq.lproj/EnhancedTrackingProtection.strings index c4174e83c610..431ac9e922ba 100644 --- a/firefox-ios/Shared/Supporting Files/sq.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/sq.lproj/EnhancedTrackingProtection.strings @@ -46,8 +46,7 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Keni mbyllur mbrojtjet"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Jeni i mbrojtur. Nëse vërejmë gjë, do t’ua bëjmë të ditur."; /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ diff --git a/firefox-ios/Shared/Supporting Files/su.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/su.lproj/EnhancedTrackingProtection.strings index 4c7b21974854..a3a18a8ddc7c 100644 --- a/firefox-ios/Shared/Supporting Files/su.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/su.lproj/EnhancedTrackingProtection.strings @@ -43,8 +43,7 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Anjeun mareuman panyalindungan"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Anjeun ditangtayungan. Upama urang manggih hiji hal, kami bakal ngiberan anjeun."; /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ diff --git a/firefox-ios/Shared/Supporting Files/sv.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/sv.lproj/EnhancedTrackingProtection.strings index 7bca90587bed..928b93e6561b 100644 --- a/firefox-ios/Shared/Supporting Files/sv.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/sv.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Du stängde av skydden"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Du är skyddad. Om vi upptäcker något meddelar vi dig."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "Din anslutning är inte säker."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Var försiktig med den här sidan"; diff --git a/firefox-ios/Shared/Supporting Files/sv.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/sv.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..44a186d5592e --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/sv.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "Ladda om"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "Ett SSL-fel har uppstått och en säker anslutning till servern kan inte göras."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "Var försiktig. Något ser inte rätt ut."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "Prova att ansluta på en annan enhet. Kontrollera ditt modem eller router. Koppla ner och återanslut till Wi-Fi."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "Det verkar finnas ett problem med din internetanslutning."; + diff --git a/firefox-ios/Shared/Supporting Files/sv.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/sv.lproj/Settings.strings index cfd687e9008b..cc1ead1f3be6 100644 --- a/firefox-ios/Shared/Supporting Files/sv.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/sv.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Hantera adresser"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "Adress för %@"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "SPARADE ADRESSER"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Spara adresser till %@"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "Spara din information säkert för att få snabb åtkomst till den senare."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "Inkluderar telefonnummer och e-postadresser"; diff --git a/firefox-ios/Shared/Supporting Files/th.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/th.lproj/EnhancedTrackingProtection.strings index 60cd1544405d..db37098f558e 100644 --- a/firefox-ios/Shared/Supporting Files/th.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/th.lproj/EnhancedTrackingProtection.strings @@ -43,8 +43,7 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "คุณปิดการป้องกัน"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "คุณได้รับการปกป้อง หากเราพบสิ่งใดเราจะแจ้งให้คุณทราบ"; /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ diff --git a/firefox-ios/Shared/Supporting Files/tr.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/tr.lproj/EnhancedTrackingProtection.strings index ba7dd3dc6c96..6fd19302c05d 100644 --- a/firefox-ios/Shared/Supporting Files/tr.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/tr.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Korumaları kapattınız"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Koruma altındasınız. Bir şey tespit edersek size haber vereceğiz."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "Bağlantınız güvenli değil."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Bu sitede dikkatli olun"; diff --git a/firefox-ios/Shared/Supporting Files/tr.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/tr.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..8b515f0a645e --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/tr.lproj/NativeErrorPage.strings @@ -0,0 +1,9 @@ +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "Bir SSL hatası oluştu ve sunucuyla güvenli bağlantı kurulamadı."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "Farklı bir cihazdan bağlanmayı deneyin. Modeminizi veya yönlendiricinizi kontrol edin. Wi-Fi bağlantınızı kesip yeniden bağlanın."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "İnternet bağlantınızla ilgili bir sorun var."; + diff --git a/firefox-ios/Shared/Supporting Files/tr.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/tr.lproj/Settings.strings index d63254316dc4..118bb9141d38 100644 --- a/firefox-ios/Shared/Supporting Files/tr.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/tr.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Adresleri yönet"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "%@ adresi"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "KAYITLI ADRESLER"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Adresleri %@ uygulamasına kaydet"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "Bilgilerinizi daha sonra hızlıca erişmek için güvenli bir şekilde kaydedin."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "Telefon numaraları ve e-posta adresleri de dahildir"; diff --git a/firefox-ios/Shared/Supporting Files/ug.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/ug.lproj/EnhancedTrackingProtection.strings index 7ad58ec9f376..91099c4039c4 100644 --- a/firefox-ios/Shared/Supporting Files/ug.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/ug.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "قوغداشنى تاقىۋەتتىڭىز"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "قوغدالدىڭىز. ئەگەر بىرەر نەرسە بايقىساق، سىزگە بىلدۈرىمىز."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "باغلىنىشىڭىز بىخەتەر ئەمەس."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "بۇ تور بېكەتتىن ئېھتىيات قىلىڭ"; diff --git a/firefox-ios/Shared/Supporting Files/ug.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/ug.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..c5f367ed8469 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/ug.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "قايتا يۈكلە"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "SSL خاتالىقى يۈز بەردى، مۇلازىمېتىرغا بىخەتەر باغلىنالمايدۇ."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "ئېھتىيات قىلىڭ. بىرەر نەرسە توغرا ئەمەستەك قىلىدۇ."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "باشقا ئۈسكۈنىگە باغلاپ سىناپ بېقىڭ. مودېمىڭىز ياكى يېتەكلىگۈچىڭىزنى تەكشۈرۈڭ. باغلىنىشنى ئۈزۈپ ئاندىن سىمسىز تور يەنى Wi-Fi غا قايتا باغلاڭ."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "ئىنتېرنېت باغلىنىشىڭىزدا مەسىلە باردەك قىلىدۇ."; + diff --git a/firefox-ios/Shared/Supporting Files/ug.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/ug.lproj/Settings.strings index 4f2aeb8289fb..615ad26289d3 100644 --- a/firefox-ios/Shared/Supporting Files/ug.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/ug.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "ئادرېس باشقۇرۇش"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "%@ نىڭ ئادرېسى"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "ساقلانغان ئادرېس"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "ئاردرېسنى %@ غا ساقلايدۇ"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "كېيىنچە تېز زىيارەت قىلىش ئۈچۈن ئۇچۇرلىرىڭىزنى بىخەتەر ساقلايدۇ."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "تېلېفون نومۇرى ۋە ئېلخەت ئادرېسىنى ئۆز ئىچىگە ئالىدۇ"; diff --git a/firefox-ios/Shared/Supporting Files/uk.lproj/ActivityStream.strings b/firefox-ios/Shared/Supporting Files/uk.lproj/ActivityStream.strings new file mode 100644 index 000000000000..8c4479770654 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/uk.lproj/ActivityStream.strings @@ -0,0 +1,3 @@ +/* String used in the section title of the Bookmarks section on Home Screen. */ +"ActivityStream.Bookmarks.Title.v128" = "Закладки"; + diff --git a/firefox-ios/Shared/Supporting Files/uk.lproj/AddressToolbar.strings b/firefox-ios/Shared/Supporting Files/uk.lproj/AddressToolbar.strings new file mode 100644 index 000000000000..e0e415b919f2 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/uk.lproj/AddressToolbar.strings @@ -0,0 +1,3 @@ +/* Accessibility label for the address field in the address toolbar. */ +"AddressToolbar.Location.A11y.Label.v128" = "Введіть запит чи адресу"; + diff --git a/firefox-ios/Shared/Supporting Files/uk.lproj/CustomizeFirefoxHome.strings b/firefox-ios/Shared/Supporting Files/uk.lproj/CustomizeFirefoxHome.strings index 1a191ed1322e..86b116668ad8 100644 --- a/firefox-ios/Shared/Supporting Files/uk.lproj/CustomizeFirefoxHome.strings +++ b/firefox-ios/Shared/Supporting Files/uk.lproj/CustomizeFirefoxHome.strings @@ -1,3 +1,6 @@ +/* In the settings menu, in the Firefox homepage customization section, this is the title for the option that allows users to toggle Bookmarks section on the Firefox homepage on or off */ +"Settings.Home.Option.Bookmarks.v128" = "Закладки"; + /* In the settings menu, in the Firefox homepage customization section, this is the subtitle for the option that allows users to turn the Pocket Recommendations section on the Firefox homepage on or off. The placeholder is the pocket app name. */ "Settings.Home.Option.ThoughtProvokingStories.subtitle.v116" = "Пропоновані статті від %@"; diff --git a/firefox-ios/Shared/Supporting Files/uk.lproj/EditAddress.strings b/firefox-ios/Shared/Supporting Files/uk.lproj/EditAddress.strings new file mode 100644 index 000000000000..4eda5e78c5b1 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/uk.lproj/EditAddress.strings @@ -0,0 +1,96 @@ +/* Title for the cancel button in the remove address alert. */ +"Addresses.EditAddress.Alert.CancelButton.v129" = "Скасувати"; + +/* Title for the remove button in the remove address alert. */ +"Addresses.EditAddress.Alert.RemoveButton.v129" = "Вилучити"; + +/* Title for the alert indicating the action to remove an address. */ +"Addresses.EditAddress.Alert.Title.v129" = "Вилучити адресу"; + +/* Title for the interface option where users can add a new address for autofill purposes. This facilitates quicker form completion by automatically filling in the user's address information. */ +"Addresses.EditAddress.AutofillAddAddressTitle.v129" = "Додати адресу"; + +/* Label for the field where users input the city part of their address. This information is crucial for mail delivery and service provision, ensuring accurate city identification in autofill settings. */ +"Addresses.EditAddress.AutofillAddressCity.v129" = "Місто"; + +/* Label for the field where users can specify just the country, used in contexts where full address details are not required. Simplifies autofill when only country information is necessary. */ +"Addresses.EditAddress.AutofillAddressCountryOnly.v129" = "Країна"; + +/* Label for the country or region field in address forms, allowing users to specify their country or territorial region. This is fundamental for international mail and services, ensuring autofill accuracy across borders. */ +"Addresses.EditAddress.AutofillAddressCountryRegion.v129" = "Країна або регіон"; + +/* Label for the district field in the address form, allowing users to specify their district for more precise location identification. This aids in refining address details for accurate autofill. */ +"Addresses.EditAddress.AutofillAddressDistrict.v129" = "Район"; + +/* Label for the emirate field, essential for addresses in the United Arab Emirates. Including emirate details ensures the autofill feature accurately represents user addresses. */ +"Addresses.EditAddress.AutofillAddressEmirate.v129" = "Емірат"; + +/* Label for the field where users specify the name of an island, if applicable. Important for addresses in archipelagic regions, aiding in precise location identification during autofill. */ +"Addresses.EditAddress.AutofillAddressIsland.v129" = "Острів"; + +/* Label for the field where the user inputs their full name as part of an address form. Essential for personalized form submissions and ensuring information accuracy in autofilled forms. */ +"Addresses.EditAddress.AutofillAddressName.v129" = "Ім'я"; + +/* Label for the field where users can input the name of their neighborhood. This detail adds precision to addresses, especially in densely populated areas, improving the accuracy of autofill. */ +"Addresses.EditAddress.AutofillAddressNeighborhood.v129" = "Околиці"; + +/* Label for the oblast field, relevant for addresses in countries like Russia and Ukraine. Oblasts are a significant administrative division, and their specification aids in autofill accuracy. */ +"Addresses.EditAddress.AutofillAddressOblast.v129" = "Область"; + +/* Label for the input field designated for the organization's name related to the address. Helps in distinguishing addresses used for business or personal purposes in autofill settings. */ +"Addresses.EditAddress.AutofillAddressOrganization.v129" = "Організація"; + +/* Label for the parish field, significant in places where parishes are used for local administration and addressing. Ensures users can specify parish details for better autofill accuracy. */ +"Addresses.EditAddress.AutofillAddressParish.v129" = "Парафія"; + +/* Label for the postal code field, universally used in address forms to specify the area code for mail sorting. Essential for autofill to ensure mail and services are accurately routed. */ +"Addresses.EditAddress.AutofillAddressPostalCode.v129" = "Поштовий індекс"; + +/* Label for the post town field, used primarily in the UK and some other regions for mail sorting. Essential for users in applicable areas to specify for correct mail delivery through autofill. */ +"Addresses.EditAddress.AutofillAddressPostTown.v129" = "Поштове містечко"; + +/* Label for the prefecture field, essential for addresses in countries like Japan where prefectures are a major administrative division. Aids in precise location specification for autofill. */ +"Addresses.EditAddress.AutofillAddressPrefecture.v129" = "Префектура"; + +/* Label for the suburb field, enabling users to add suburb details to their address. This is important for accurate delivery and services in suburban areas, enhancing autofill functionality. */ +"Addresses.EditAddress.AutofillAddressSuburb.v129" = "Передмістя"; + +/* Label for the telephone number field, allowing users to input their contact number. This is essential for communication and service provision, ensuring contact details are autofilled correctly. */ +"Addresses.EditAddress.AutofillAddressTel.v129" = "Телефон"; + +/* Label for the input field for the townland, a specific type of land division used in rural areas. Enhances address detail for users in regions where townlands are a common addressing component. */ +"Addresses.EditAddress.AutofillAddressTownland.v129" = "Містечко"; + +/* Label for the field to input the name of a village or township. This is crucial for addresses in rural areas, ensuring the autofill feature accurately captures all necessary geographical details. */ +"Addresses.EditAddress.AutofillAddressVillageTownship.v129" = "Село чи селище"; + +/* Label for the ZIP code field, primarily used in the United States for mail sorting. Key for autofill to accurately complete addresses for shipping, billing, and service provision. */ +"Addresses.EditAddress.AutofillAddressZip.v129" = "Поштовий індекс"; + +/* Label for the button to cancel the current autofill operation or exit the form without saving changes. Provides users with an option to back out of a process without making any modifications. */ +"Addresses.EditAddress.AutofillCancelButton.v129" = "Скасувати"; + +/* Title for the option allowing users to edit an existing saved address. This is used within the settings for autofill, enabling users to update their address details for accurate form autofilling. */ +"Addresses.EditAddress.AutofillEditAddressTitle.v129" = "Редагувати адресу"; + +/* Title for the input field where users can enter their street address. This is used within the settings for autofill, allowing users to provide their street address for accurate form autofilling. */ +"Addresses.EditAddress.AutofillEditStreetAddressTitle.v129" = "Вулиця"; + +/* Label for the button to save the current address details entered or edited by the user. This action confirms the user's changes and updates their autofill settings accordingly. */ +"Addresses.EditAddress.AutofillSaveButton.v129" = "Зберегти"; + +/* Title for the option allowing users to view an existing saved address. This is used within the settings for autofill, enabling users to see their address details for accurate form autofilling. */ +"Addresses.EditAddress.AutofillViewAddressTitle.v129" = "Переглянути адресу"; + +/* Button label for closing the view where user can view their address info. */ +"Addresses.EditAddress.CloseNavBarButtonLabel.v129" = "Закрити"; + +/* Button label for editing the address details shown in the form. */ +"Addresses.EditAddress.EditNavBarButtonLabel.v129" = "Редагувати"; + +/* Toast message confirming that an address has been successfully saved. */ +"Addresses.Toast.AddressSavedConfirmation.v129" = "Адресу збережено"; + +/* Toast message indicating an error occurred while trying to save an address. */ +"Addresses.Toast.AddressSaveError.v129" = "Не вдалося зберегти адресу"; + diff --git a/firefox-ios/Shared/Supporting Files/uk.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/uk.lproj/EnhancedTrackingProtection.strings new file mode 100644 index 000000000000..17c2eb044f1f --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/uk.lproj/EnhancedTrackingProtection.strings @@ -0,0 +1,30 @@ +/* The text for the clear cookies and site data alert button inside the enhanced tracking protection screen. */ +"Menu.EnhancedTrackingProtection.ClearData.AlertCancelButton.v128" = "Скасувати"; + +/* The text for the clear cookies and site data alert button inside the enhanced tracking protection screen. */ +"Menu.EnhancedTrackingProtection.ClearData.AlertOkButton.v128" = "Очистити"; + +/* The title for the clear cookies and site data alert inside the enhanced tracking protection screen. */ +"Menu.EnhancedTrackingProtection.ClearData.AlertTitle.v128" = "Стерти файли cookie та дані сайтів"; + +/* The title for the clear cookies and site data button inside the enhanced tracking protection screen. */ +"Menu.EnhancedTrackingProtection.ClearData.ButtonTitle.v128" = "Стерти файли cookie та дані сайтів"; + +/* Text to let users know that the current website is not secure. */ +"Menu.EnhancedTrackingProtection.Details.ConnectionUnsecure.v128" = "Незахищене з'єднання"; + +/* Header for the enhanced tracking protection screen when the user has opted out of the feature. Placeholder will be replaced by the app name */ +"Menu.EnhancedTrackingProtection.Off.Header.v128" = "%@ не працює. Ми пропонуємо знову ввімкнути захист."; + +/* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ +"Menu.EnhancedTrackingProtection.Off.Title.v128" = "Ви вимкнули захист"; + +/* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Будьте обережні на цьому сайті"; + +/* Title for the enhanced tracking protection screen when the user has selected to be protected. The placeholder will have the value of the app name */ +"Menu.EnhancedTrackingProtection.On.Title.v128" = "%@ на сторожі"; + +/* A switch to disable enhanced tracking protection inside the menu. */ +"Menu.EnhancedTrackingProtection.SwitchOff.Text.v128" = "Захист ВИМКНЕНО. Ми пропонуємо ввімкнути його знову."; + diff --git a/firefox-ios/Shared/Supporting Files/uk.lproj/Microsurvey.strings b/firefox-ios/Shared/Supporting Files/uk.lproj/Microsurvey.strings index abe1c2626560..0e0326b3bfa1 100644 --- a/firefox-ios/Shared/Supporting Files/uk.lproj/Microsurvey.strings +++ b/firefox-ios/Shared/Supporting Files/uk.lproj/Microsurvey.strings @@ -43,6 +43,21 @@ /* On the microsurvey, this is the title for one of the options that the user can select to answer the survey. */ "Microsurvey.Survey.Options.LikertScaleOption5.v127" = "Дуже незадоволені"; +/* On the microsurvey, this is the title for one of the options that the user can select to answer the survey. It indicates that the user has not use the feature that the survey is inquiring about. */ +"Microsurvey.Survey.Options.LikertScaleOption6.v129" = "Я цим не користуюсь"; + +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states the order the survey option in the list of options. First placeholder is the number the option is in the list and the second placeholder is the total number of options such as 1 out of 6. */ +"Microsurvey.Survey.OptionsOrder.AccessibilityLabel.v129" = "%1$@ з %2$@"; + /* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this the title of a link on the survey and allows the user to navigate to our privacy policy details. */ "Microsurvey.Survey.PrivacyPolicyLink.v127" = "Положення про приватність"; +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was selected. */ +"Microsurvey.Survey.RadioButton.Selected.AccessibilityLabel.v129" = "Вибрано"; + +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label that states whether the survey option was not selected. */ +"Microsurvey.Survey.RadioButton.Unselected.AccessibilityLabel.v129" = "Не вибрано"; + +/* After engaging with the microsurvey prompt, the microsurvey pops up as a bottom sheet for the user to answer, this is the accessibility label used to announce that the sheet has appeared. */ +"Microsurvey.Survey.Sheet.AccessibilityLabel.v130" = "Опитування"; + diff --git a/firefox-ios/Shared/Supporting Files/uk.lproj/PasswordAutofill.strings b/firefox-ios/Shared/Supporting Files/uk.lproj/PasswordAutofill.strings index 99f9c596b913..d3bb8a57e0ce 100644 --- a/firefox-ios/Shared/Supporting Files/uk.lproj/PasswordAutofill.strings +++ b/firefox-ios/Shared/Supporting Files/uk.lproj/PasswordAutofill.strings @@ -1,3 +1,6 @@ +/* This label is used in a cell found in the list of autofill login options in place of an actual username to denote that no username was saved for this login */ +"PasswordAutofill.LoginListCellNoUsername.v129" = "(без імені користувача)"; + /* This label is used for a button in the password list screen allowing users to manage their saved passwords. It's meant to direct users to where they can add, remove, or edit their saved passwords. */ "PasswordAutofill.ManagePasswordsButton.v124" = "Керувати паролями"; diff --git a/firefox-ios/Shared/Supporting Files/uk.lproj/ScanQRCode.strings b/firefox-ios/Shared/Supporting Files/uk.lproj/ScanQRCode.strings new file mode 100644 index 000000000000..beb544f138d1 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/uk.lproj/ScanQRCode.strings @@ -0,0 +1,6 @@ +/* Allow button to open URL from scanned QR Code */ +"ScanQRCode.ConfirmOpenURL.AllowButton.v129" = "Дозволити"; + +/* Deny button to cancel opening URL from scanned QR Code */ +"ScanQRCode.ConfirmOpenURL.DenyButton.v129" = "Заборонити"; + diff --git a/firefox-ios/Shared/Supporting Files/uk.lproj/Toolbar.strings b/firefox-ios/Shared/Supporting Files/uk.lproj/Toolbar.strings new file mode 100644 index 000000000000..7710091148f4 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/uk.lproj/Toolbar.strings @@ -0,0 +1,6 @@ +/* Accessibility label for the new tab button that can be displayed in the navigation or address toolbar. */ +"Toolbar.NewTab.Button.v130" = "Нова вкладка"; + +/* Label for button on action sheet, accessed via long pressing tab toolbar button, that closes the current tab when pressed */ +"Toolbar.Tab.CloseThisTab.Button.v130" = "Закрити цю вкладку"; + diff --git a/firefox-ios/Shared/Supporting Files/vi.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/vi.lproj/EnhancedTrackingProtection.strings index 95d3b59f1233..5c56f6f58d9e 100644 --- a/firefox-ios/Shared/Supporting Files/vi.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/vi.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "Bạn đã tắt trình chống"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "Bạn đã được bảo vệ. Nếu chúng tôi phát hiện ra điều gì đó, chúng tôi sẽ cho bạn biết."; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "Kết nối của bạn không an toàn."; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "Hãy cẩn thận trên trang web này"; diff --git a/firefox-ios/Shared/Supporting Files/vi.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/vi.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..2054303aaa95 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/vi.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "Tải lại"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "Đã xảy ra lỗi SSL và không thể thực hiện kết nối an toàn tới máy chủ."; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "Hãy cẩn thận. Có điều gì đó không ổn."; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "Hãy thử kết nối trên một thiết bị khác. Kiểm tra modem hoặc bộ định tuyến của bạn. Ngắt kết nối và kết nối lại với Wi-Fi."; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "Có vẻ như đã xảy ra sự cố với kết nối Internet của bạn."; + diff --git a/firefox-ios/Shared/Supporting Files/vi.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/vi.lproj/Settings.strings index b2367344bb57..22cc1388f1ff 100644 --- a/firefox-ios/Shared/Supporting Files/vi.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/vi.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "Quản lý địa chỉ"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "Địa chỉ cho %@"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "ĐỊA CHỈ ĐÃ LƯU"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "Lưu địa chỉ đến %@"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "Lưu thông tin của bạn một cách an toàn để có thể truy cập nhanh vào thông tin đó sau này."; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "Bao gồm số điện thoại và địa chỉ email"; diff --git a/firefox-ios/Shared/Supporting Files/zh-CN.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/zh-CN.lproj/EnhancedTrackingProtection.strings index 38208254c721..68df14f4f94c 100644 --- a/firefox-ios/Shared/Supporting Files/zh-CN.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/zh-CN.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "已关闭保护"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "您已受保护,我们会在发现异常情况时告知您。"; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "您的连接不安全。"; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "请谨慎浏览此网站"; diff --git a/firefox-ios/Shared/Supporting Files/zh-CN.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/zh-CN.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..d3a54061165f --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/zh-CN.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "重新加载"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "发生 SSL 错误,无法与服务器建立安全连接。"; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "当心,看来有异常情况。"; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "请尝试通过其他设备连接,检查调制解调器或路由器,断开 Wi-Fi 连接后重新连接。"; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "您的网络连接似乎出了点问题。"; + diff --git a/firefox-ios/Shared/Supporting Files/zh-CN.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/zh-CN.lproj/Settings.strings index 9df6c6312330..436c2a04e0f5 100644 --- a/firefox-ios/Shared/Supporting Files/zh-CN.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/zh-CN.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "管理地址"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "%@ 的地址"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "保存的地址"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "将地址保存到 %@"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "安全保存信息,以便日后使用。"; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "包括电话号码和邮箱地址"; diff --git a/firefox-ios/Shared/Supporting Files/zh-TW.lproj/EnhancedTrackingProtection.strings b/firefox-ios/Shared/Supporting Files/zh-TW.lproj/EnhancedTrackingProtection.strings index 677c4e9062d0..cf4f5bd4427b 100644 --- a/firefox-ios/Shared/Supporting Files/zh-TW.lproj/EnhancedTrackingProtection.strings +++ b/firefox-ios/Shared/Supporting Files/zh-TW.lproj/EnhancedTrackingProtection.strings @@ -46,10 +46,12 @@ /* Title for the enhanced tracking protection screen when the user has opted out of the feature. */ "Menu.EnhancedTrackingProtection.Off.Title.v128" = "您已關閉保護"; -/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. - Header for the enhanced tracking protection screen when the user has selected to be protected. */ +/* Header for the enhanced tracking protection screen when the user has selected to be protected. */ "Menu.EnhancedTrackingProtection.On.Header.v128" = "您已受到保護,若我們發現某些不安全的地方會再通知您。"; +/* Header for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ +"Menu.EnhancedTrackingProtection.On.NotSecure.Header.v128" = "您的連線並不安全。"; + /* Title for the enhanced tracking protection screen when the user has selected to be protected but the connection is not secure. */ "Menu.EnhancedTrackingProtection.On.NotSecure.Title.v128" = "在此網站請小心"; diff --git a/firefox-ios/Shared/Supporting Files/zh-TW.lproj/NativeErrorPage.strings b/firefox-ios/Shared/Supporting Files/zh-TW.lproj/NativeErrorPage.strings new file mode 100644 index 000000000000..fa9403a18aa6 --- /dev/null +++ b/firefox-ios/Shared/Supporting Files/zh-TW.lproj/NativeErrorPage.strings @@ -0,0 +1,15 @@ +/* On error page, this is the text on a button that will try to load the page again. */ +"NativeErrorPage.ButtonLabel.v131" = "重新載入"; + +/* On error page, this is the description for generic error. */ +"NativeErrorPage.GenericError.Description.v131" = "發生 SSL 錯誤,無法與伺服器建立安全連線。"; + +/* On error page, this is the title for generic error. */ +"NativeErrorPage.GenericError.TitleLabel.v131" = "請小心,有些東西不對勁。"; + +/* On error page, this is the description for no internet connection. */ +"NativeErrorPage.NoInternetConnection.Description.v131" = "您可以試著連線到其他裝置、檢查您的數據機或路由器,或將 Wi-Fi 斷線重連。"; + +/* On error page, this is the title for no internet connection */ +"NativeErrorPage.NoInternetConnection.TitleLabel.v131" = "您的網路連線可能有點問題。"; + diff --git a/firefox-ios/Shared/Supporting Files/zh-TW.lproj/Settings.strings b/firefox-ios/Shared/Supporting Files/zh-TW.lproj/Settings.strings index 6526c0220f06..71f08b346e6d 100644 --- a/firefox-ios/Shared/Supporting Files/zh-TW.lproj/Settings.strings +++ b/firefox-ios/Shared/Supporting Files/zh-TW.lproj/Settings.strings @@ -1,6 +1,18 @@ +/* This label is used for a button in the address list screen allowing users to manage their saved addresses. It's meant to direct users to where they can add, remove, or edit their saved addresses. */ +"Addresses.ManageAddressesButton.v130" = "管理已存地址"; + +/* Accessibility label for an address list item in autofill settings screen. The %@ parameter is the address of the user that will read the name, street, city, state, postal code if available. */ +"Addresses.Settings.ListItemA11y.v130" = "%@ 的地址"; + /* On the autofill settings screen, a label for the section that displays the list of saved addresses. This label adds additional context for users regarding the toggle switch that allows saving and autofilling of addresses for webpages. */ "Addresses.Settings.SavedAddressesSectionTitle.v124" = "已儲存的地址"; +/* Title text for the content unavailable view informing users they can create or add new addresses. %@ is the name of the app. */ +"Addresses.Settings.SaveToFirefox.Title.v130" = "將地址儲存至 %@"; + +/* Description text for the content unavailable view informing users they can create or add new addresses. */ +"Addresses.Settings.SecureSaveInfo.Description.v130" = "安全地儲存您的資訊,以便之後快速存取。"; + /* On the autofill settings screen, a label under the title label to add additional context for user in regards to what the toggle switch that allow saving and autofilling of addresses for webpages does, letting users know that this action includes phone numbers and email addresses. */ "Addresses.Settings.Switch.Description.v124" = "包含電話號碼與電子郵件地址"; diff --git a/firefox-ios/Shared/co.lproj/Localizable.strings b/firefox-ios/Shared/co.lproj/Localizable.strings index db4d391d61df..8054abe741a5 100644 --- a/firefox-ios/Shared/co.lproj/Localizable.strings +++ b/firefox-ios/Shared/co.lproj/Localizable.strings @@ -611,7 +611,7 @@ "LibraryPanel.History.DeleteGroupedItem.v104" = "Squassà"; /* In the history panel, users will be able to search terms in their browsing history. This label is shown when there is no results after querying the search terms in the user's history. */ -"LibraryPanel.History.NoHistoryFound.v99" = "Nisunu elementu trovu in a cronolugia"; +"LibraryPanel.History.NoHistoryFound.v99" = "Ùn si trova nunda in a cronolugia"; /* In the history panel, this is the title on the button that navigates the user to a screen showing their recently closed tabs. */ "LibraryPanel.History.RecentlyClosedTabs.v99" = "Unghjette chjose pocu fà"; diff --git a/firefox-ios/Shared/co.lproj/LoginManager.strings b/firefox-ios/Shared/co.lproj/LoginManager.strings index 4bc94679709c..45f7e04bef53 100644 --- a/firefox-ios/Shared/co.lproj/LoginManager.strings +++ b/firefox-ios/Shared/co.lproj/LoginManager.strings @@ -50,10 +50,10 @@ "Modified %@" = "Mudificatu %@"; /* Label displayed when no logins are found after searching. */ -"No logins found" = "Alcuna identificazione di cunnessione trova"; +"No logins found" = "Ùn si trova nisuna identificazione di cunnessione"; /* Label displayed when no logins are found after searching. */ -"NoLoginsFound.Title.v122" = "Nisuna parolla d’intesa trova"; +"NoLoginsFound.Title.v122" = "Ùn si trova nisuna parolla d’intesa"; /* Open and Fill website text selection menu item */ "Open & Fill" = "Apre è rinsignà"; diff --git a/firefox-ios/Shared/eo.lproj/Localizable.strings b/firefox-ios/Shared/eo.lproj/Localizable.strings index e2f2c6ab3169..a58f8e4d3132 100644 --- a/firefox-ios/Shared/eo.lproj/Localizable.strings +++ b/firefox-ios/Shared/eo.lproj/Localizable.strings @@ -515,7 +515,7 @@ "Hotkeys.Reload.DiscoveryTitle" = "Reŝargi paĝon"; /* A label indicating the keyboard shortcut of directly accessing the URL, location, bar. This label is displayed inside the Discoverability overlay when a user presses the Command key. The Discoverability overlay and shortcut become available only when a user has connected a hardware keyboard to an iPad. See https://drive.google.com/file/d/1gH3tbvDceg7yG5N67NIHS-AXgDgCzBHN/view?usp=sharing for more details. */ -"Hotkeys.SelectLocationBar.DiscoveryTitle" = "Elekti adresstrion"; +"Hotkeys.SelectLocationBar.DiscoveryTitle" = "Elekti la readresan strion"; /* A label indicating the keyboard shortcut of switching to a subsequent tab. This label is displayed inside the Discoverability overlay when a user presses the Command key. The Discoverability overlay and shortcut become available only when a user has connected a hardware keyboard to an iPad. See https://drive.google.com/file/d/1gH3tbvDceg7yG5N67NIHS-AXgDgCzBHN/view?usp=sharing for more details. */ "Hotkeys.ShowNextTab.DiscoveryTitle" = "Montri venontan langeton"; diff --git a/firefox-ios/Shared/uk.lproj/Localizable.strings b/firefox-ios/Shared/uk.lproj/Localizable.strings index b7ef1b2d2b10..5cc610a6fd2c 100644 --- a/firefox-ios/Shared/uk.lproj/Localizable.strings +++ b/firefox-ios/Shared/uk.lproj/Localizable.strings @@ -757,6 +757,9 @@ /* Label for the button, displayed in the menu, takes you to History screen when pressed. */ "Menu.History.Label" = "Історія"; +/* Label for the new private tab button in the menu page. Pressing this button opens a new private tab. */ +"Menu.NewPrivateTab.Label" = "Нова приватна вкладка"; + /* Label for the new tab button in the menu page. Pressing this button opens a new tab. */ "Menu.NewTab.v99" = "Нова вкладка"; @@ -1144,6 +1147,9 @@ /* The placeholder for URL Field when saving a custom search engine */ "Settings.AddCustomEngine.URLPlaceholder" = "Адреса URL (%s заміниться на запит)"; +/* Title of setting to block opening external apps when pressing links. */ +"Settings.BlockOpeningExternalApps.Title" = "Блокувати відкриття зовнішніх програм"; + /* Button in Data Management that clears all items. */ "Settings.ClearAllWebsiteData.Clear.Button" = "Стерти всі дані вебсайтів"; @@ -1399,6 +1405,9 @@ /* Description displayed under the ”Offer to Open Copied Link” option. See https://bug1223660.bmoattachments.org/attachment.cgi?id=8898349 */ "Settings.OfferClipboardBar.Status" = "При запуску Firefox"; +/* Description displayed under the ”Offer to Open Copied Link” option. See https://bug1223660.bmoattachments.org/attachment.cgi?id=8898349. Placeholder is for the app name. */ +"Settings.OfferClipboardBar.Status.v128" = "Під час відкриття %@"; + /* Description displayed under the ”Offer to Open Copied Link” option. See https://bug1223660.bmoattachments.org/attachment.cgi?id=8898349 */ "Settings.OfferClipboardBar.StatusV2" = "При запуску Firefox"; diff --git a/firefox-ios/Shared/uk.lproj/Menu.strings b/firefox-ios/Shared/uk.lproj/Menu.strings index 80b4ab379ef6..c6e4a4923d86 100644 --- a/firefox-ios/Shared/uk.lproj/Menu.strings +++ b/firefox-ios/Shared/uk.lproj/Menu.strings @@ -4,6 +4,12 @@ /* Label for the button, displayed in the menu, used to copy the current page link to the clipboard. */ "Menu.CopyLink.Title" = "Копіювати посилання"; +/* Toast displayed to user after downlaod pdf was pressed. */ +"Menu.DownloadPDF.Confirm.v129" = "Успішно завантажено PDF"; + +/* Label for the button, displayed in the menu, downloads a pdf when pressed. */ +"Menu.DownloadPDF.Label.v129" = "Завантажити PDF"; + /* Label for the button, displayed in the menu, used to open the toolbar to search for text within the current page. */ "Menu.FindInPageAction.Title" = "Знайти на сторінці"; From fed68723b500d85e921a695fdb992bc687292a46 Mon Sep 17 00:00:00 2001 From: Winnie Teichmann <4530+thatswinnie@users.noreply.github.com> Date: Mon, 26 Aug 2024 16:43:07 +0100 Subject: [PATCH 109/128] Refactor FXIOS-9820 Enable Swiftlint rules for SwiftUI accessibility (#21569) * Enable Swiftlint rules for SwiftUI a11y * Address warnings * Fix spelling * Fix tests * Add a11y ids * Fix new Swiftlint warnings --- .swiftlint.yml | 2 ++ .../Autofill/AutofillHeaderView.swift | 1 + .../CreditCardBottomSheetViewController.swift | 1 + .../CreditCardItemRow.swift | 7 ++++--- .../CreditCardTableViewController.swift | 1 + .../Logic/CreditCardValidator.swift | 18 ++++++++-------- .../ViewComponents/CreditCardInputField.swift | 7 +++++-- .../Frontend/Autofill/LoginCellView.swift | 1 + .../WidgetKit/ImageButtonWithLabel.swift | 6 +++--- .../WidgetKit/OpenTabs/OpenTabsWidget.swift | 8 +++---- .../Tests/XCUITests/CreditCardsTests.swift | 21 +++++++------------ 11 files changed, 39 insertions(+), 34 deletions(-) diff --git a/.swiftlint.yml b/.swiftlint.yml index 760c7222b5a7..f24c1f9155fa 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -82,6 +82,8 @@ only_rules: # Only enforce these rules, ignore all others - vertical_whitespace_closing_braces - vertical_whitespace_opening_braces - yoda_condition + - accessibility_label_for_image + - accessibility_trait_for_button # These rules were originally opted into. Disabling for now to get # Swiftlint up and running. diff --git a/firefox-ios/Client/Frontend/Autofill/AutofillHeaderView.swift b/firefox-ios/Client/Frontend/Autofill/AutofillHeaderView.swift index 366e88858e80..b09bbbc3c082 100644 --- a/firefox-ios/Client/Frontend/Autofill/AutofillHeaderView.swift +++ b/firefox-ios/Client/Frontend/Autofill/AutofillHeaderView.swift @@ -39,6 +39,7 @@ struct AutofillHeaderView: View { .resizable() .aspectRatio(contentMode: .fit) .frame(width: UX.logoSize, height: UX.logoSize) + .accessibilityHidden(true) VStack(alignment: .leading) { Text(title) .font(.body) diff --git a/firefox-ios/Client/Frontend/Autofill/CreditCard/CreditCardBottomSheet/CreditCardBottomSheetViewController.swift b/firefox-ios/Client/Frontend/Autofill/CreditCard/CreditCardBottomSheet/CreditCardBottomSheetViewController.swift index a14c538afd69..416ff39e6ca5 100644 --- a/firefox-ios/Client/Frontend/Autofill/CreditCard/CreditCardBottomSheet/CreditCardBottomSheetViewController.swift +++ b/firefox-ios/Client/Frontend/Autofill/CreditCard/CreditCardBottomSheet/CreditCardBottomSheetViewController.swift @@ -301,6 +301,7 @@ class CreditCardBottomSheetViewController: UIViewController, hostingCell.selectionStyle = .none hostingCell.isAccessibilityElement = true hostingCell.accessibilityAttributedLabel = viewModel.a11yLabel(for: creditCard) + hostingCell.accessibilityIdentifier = "creditCardCell_\(indexPath.row)" return hostingCell } diff --git a/firefox-ios/Client/Frontend/Autofill/CreditCard/CreditCardSettingsView/CreditCardItemRow.swift b/firefox-ios/Client/Frontend/Autofill/CreditCard/CreditCardSettingsView/CreditCardItemRow.swift index 7a9144b616c5..f85d4ffcbf6a 100644 --- a/firefox-ios/Client/Frontend/Autofill/CreditCard/CreditCardSettingsView/CreditCardItemRow.swift +++ b/firefox-ios/Client/Frontend/Autofill/CreditCard/CreditCardSettingsView/CreditCardItemRow.swift @@ -88,6 +88,7 @@ struct CreditCardItemRow: View { didSelectAction?() } } + .accessibility(addTraits: .isButton) Rectangle() .fill(separatorColor) .frame(maxWidth: .infinity) @@ -108,14 +109,14 @@ struct CreditCardItemRow: View { } func getImage(creditCard: CreditCard) -> Image { - let defaultImage = Image(StandardImageIdentifiers.Large.creditCard) + let defaultImage = Image(decorative: StandardImageIdentifiers.Large.creditCard) guard let type = CreditCardType(rawValue: creditCard.ccType.uppercased()), - let image = type.image else { + let image = type.imageName else { return defaultImage } - return Image(uiImage: image) + return Image(decorative: image) } func applyTheme(theme: Theme) { diff --git a/firefox-ios/Client/Frontend/Autofill/CreditCard/CreditCardSettingsView/CreditCardTableViewController.swift b/firefox-ios/Client/Frontend/Autofill/CreditCard/CreditCardSettingsView/CreditCardTableViewController.swift index fac8e0358285..e2f0fa07bc5b 100644 --- a/firefox-ios/Client/Frontend/Autofill/CreditCard/CreditCardSettingsView/CreditCardTableViewController.swift +++ b/firefox-ios/Client/Frontend/Autofill/CreditCard/CreditCardSettingsView/CreditCardTableViewController.swift @@ -211,6 +211,7 @@ extension CreditCardTableViewController: UITableViewDelegate, hostingCell.contentView.backgroundColor = .clear hostingCell.selectionStyle = .none hostingCell.isAccessibilityElement = true + hostingCell.accessibilityIdentifier = "creditCardCell_\(indexPath.row)" return hostingCell } } diff --git a/firefox-ios/Client/Frontend/Autofill/CreditCard/Logic/CreditCardValidator.swift b/firefox-ios/Client/Frontend/Autofill/CreditCard/Logic/CreditCardValidator.swift index be39bb6f7475..a4d4fa06c49b 100644 --- a/firefox-ios/Client/Frontend/Autofill/CreditCard/Logic/CreditCardValidator.swift +++ b/firefox-ios/Client/Frontend/Autofill/CreditCard/Logic/CreditCardValidator.swift @@ -14,24 +14,24 @@ enum CreditCardType: String, Equatable, CaseIterable { case mir = "MIR" case unionpay = "UNIONPAY" - var image: UIImage? { + var imageName: String? { switch self { case .visa: - return UIImage(named: ImageIdentifiers.logoVisa) + return ImageIdentifiers.logoVisa case .mastercard: - return UIImage(named: ImageIdentifiers.logoMastercard) + return ImageIdentifiers.logoMastercard case .amex: - return UIImage(named: ImageIdentifiers.logoAmex) + return ImageIdentifiers.logoAmex case .diners: - return UIImage(named: ImageIdentifiers.logoDiners) + return ImageIdentifiers.logoDiners case .jcb: - return UIImage(named: ImageIdentifiers.logoJcb) + return ImageIdentifiers.logoJcb case .discover: - return UIImage(named: ImageIdentifiers.logoDiscover) + return ImageIdentifiers.logoDiscover case .mir: - return UIImage(named: ImageIdentifiers.logoMir) + return ImageIdentifiers.logoMir case .unionpay: - return UIImage(named: ImageIdentifiers.logoUnionpay) + return ImageIdentifiers.logoUnionpay } } diff --git a/firefox-ios/Client/Frontend/Autofill/CreditCard/ViewComponents/CreditCardInputField.swift b/firefox-ios/Client/Frontend/Autofill/CreditCard/ViewComponents/CreditCardInputField.swift index 4d8c69234ba1..0a473463c8e3 100644 --- a/firefox-ios/Client/Frontend/Autofill/CreditCard/ViewComponents/CreditCardInputField.swift +++ b/firefox-ios/Client/Frontend/Autofill/CreditCard/ViewComponents/CreditCardInputField.swift @@ -7,7 +7,7 @@ import Foundation import SwiftUI import Shared -enum CreditCardInputType { +enum CreditCardInputType: String { case name, number, expiration } @@ -204,7 +204,10 @@ struct CreditCardInputField: View { if inputType == .expiration { _ = self.updateInputValidity() } - }.accessibilityLabel(fieldHeadline) + } + .accessibilityLabel(fieldHeadline) + .accessibilityIdentifier(inputType.rawValue) + .accessibility(addTraits: .isButton) } // MARK: Helper diff --git a/firefox-ios/Client/Frontend/Autofill/LoginCellView.swift b/firefox-ios/Client/Frontend/Autofill/LoginCellView.swift index b66a9eb531bc..b8215b7c461b 100644 --- a/firefox-ios/Client/Frontend/Autofill/LoginCellView.swift +++ b/firefox-ios/Client/Frontend/Autofill/LoginCellView.swift @@ -47,6 +47,7 @@ struct LoginCellView: View { .padding(.leading, 16) .foregroundColor(iconPrimary) .alignmentGuide(.midAccountAndName) { $0[VerticalAlignment.center] } + .accessibilityHidden(true) VStack(alignment: .leading) { Text(login.decryptedUsername.isEmpty ? String.PasswordAutofill.LoginListCellNoUsername : login.decryptedUsername) diff --git a/firefox-ios/WidgetKit/ImageButtonWithLabel.swift b/firefox-ios/WidgetKit/ImageButtonWithLabel.swift index 7fa3b2a1e2c7..8906e09683d8 100644 --- a/firefox-ios/WidgetKit/ImageButtonWithLabel.swift +++ b/firefox-ios/WidgetKit/ImageButtonWithLabel.swift @@ -91,11 +91,11 @@ struct ImageButtonWithLabel: View { } Spacer() if link == .search && isSmall { - Image(StandardImageIdentifiers.Large.search) + Image(decorative: StandardImageIdentifiers.Large.search) .scaledToFit() .frame(height: 24.0) } else { - Image(link.imageName) + Image(decorative: link.imageName) .scaledToFit() .frame(height: 24.0) } @@ -103,7 +103,7 @@ struct ImageButtonWithLabel: View { if isSmall { HStack(alignment: .bottom) { Spacer() - Image("faviconFox") + Image(decorative: "faviconFox") .scaledToFit() .frame(height: 24.0) } diff --git a/firefox-ios/WidgetKit/OpenTabs/OpenTabsWidget.swift b/firefox-ios/WidgetKit/OpenTabs/OpenTabsWidget.swift index 826bb3f865d9..0ba727176fca 100644 --- a/firefox-ios/WidgetKit/OpenTabs/OpenTabsWidget.swift +++ b/firefox-ios/WidgetKit/OpenTabs/OpenTabsWidget.swift @@ -37,7 +37,7 @@ struct OpenTabsView: View { if entry.favicons[tab.imageKey] != nil { (entry.favicons[tab.imageKey])!.resizable().frame(width: 16, height: 16) } else { - Image(StandardImageIdentifiers.Large.globe) + Image(decorative: StandardImageIdentifiers.Large.globe) .foregroundColor(Color.white) .frame(width: 16, height: 16) } @@ -59,7 +59,7 @@ struct OpenTabsView: View { var openFirefoxButton: some View { HStack(alignment: .center, spacing: 15) { - Image(StandardImageIdentifiers.Small.externalLink).foregroundColor(Color.white) + Image(decorative: StandardImageIdentifiers.Small.externalLink).foregroundColor(Color.white) Text("Open Firefox") .foregroundColor(Color.white).lineLimit(1) .font(.system(size: 13, weight: .semibold, design: .default)) @@ -82,7 +82,7 @@ struct OpenTabsView: View { Text(String.NoOpenTabsLabel) HStack { Spacer() - Image(StandardImageIdentifiers.Small.externalLink) + Image(decorative: StandardImageIdentifiers.Small.externalLink) Text(String.OpenFirefoxLabel) .foregroundColor(Color.white).lineLimit(1) .font(.system(size: 13, weight: .semibold, design: .default)) @@ -97,7 +97,7 @@ struct OpenTabsView: View { if entry.tabs.count > numberOfTabsToDisplay { HStack(alignment: .center, spacing: 15) { - Image(StandardImageIdentifiers.Small.externalLink) + Image(decorative: StandardImageIdentifiers.Small.externalLink) .foregroundColor(Color.white) .frame(width: 16, height: 16) Text( diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/CreditCardsTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/CreditCardsTests.swift index 5395da02d675..70756e6ea97c 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/CreditCardsTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/CreditCardsTests.swift @@ -14,14 +14,9 @@ class CreditCardsTests: BaseTestCase { var expiration: XCUIElement! func initCardFields() { - nameOnCard = app.otherElements.textFields.element(boundBy: 0) - cardNr = app.otherElements.textFields.element(boundBy: 1) - expiration = app.otherElements.textFields.element(boundBy: 2) - if !iPad() { - nameOnCard = app.otherElements.textFields.element(boundBy: 1) - cardNr = app.otherElements.textFields.element(boundBy: 2) - expiration = app.otherElements.textFields.element(boundBy: 3) - } + nameOnCard = app.buttons["name"] + cardNr = app.buttons["number"] + expiration = app.buttons["expiration"] } // https://mozilla.testrail.io/index.php?/cases/view/2306967 @@ -48,10 +43,10 @@ class CreditCardsTests: BaseTestCase { addCreditCard(name: "Test", cardNumber: cards[0], expirationDate: "0540") mozWaitForElementToExist(app.staticTexts[creditCardsStaticTexts.AutoFillCreditCard.savedCards]) mozWaitForElementToExist(app.staticTexts.containingText("New").element) - mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).staticTexts.elementContainingText("1252")) + mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).buttons.elementContainingText("1252")) let cardDetails = ["Test", "Expires", "5/40"] for i in cardDetails { - mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).staticTexts[i]) + mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).buttons[i]) } } @@ -126,7 +121,7 @@ class CreditCardsTests: BaseTestCase { // https://mozilla.testrail.io/index.php?/cases/view/2306969 // Smoketest - func testAutofillCreditCardsToggleOnOoff() { + func testAutofillCreditCardsToggleOnOff() { navigator.nowAt(NewTabScreen) waitForTabsButton() navigator.goto(CreditCardsSettings) @@ -689,11 +684,11 @@ class CreditCardsTests: BaseTestCase { app.tables.cells.element(boundBy: 1).tap() // The "View card" page is displayed with all the details of the card mozWaitForElementToExist(app.navigationBars[creditCardsStaticTexts.ViewCreditCard.viewCard]) - mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).staticTexts.elementContainingText("1252")) + mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).buttons.elementContainingText("1252")) let cardDetails = ["Test", "05 / 40"] for i in cardDetails { if #available(iOS 16, *) { - XCTAssertTrue(app.textFields[i].exists, "\(i) does not exists") + XCTAssertTrue(app.buttons[i].exists, "\(i) does not exists") } else { mozWaitForElementToExist(app.staticTexts[i]) } From f8f49740b71aa5402238321a7c4df2ce7ed5717b Mon Sep 17 00:00:00 2001 From: Isabella Date: Mon, 26 Aug 2024 14:16:32 -0600 Subject: [PATCH 110/128] Bugfix FXIOS-9039 Hide incorrect downloaded bytes when downloading encoded (e.g. gzip) files (#21004) * Hide download size / progress details for encoded data in the DownloadToast. * Cleanup and documentation update. * Hide progress view when download percent estimate is 0. --- .../Frontend/Browser/DownloadQueue.swift | 13 ++++++++ .../Frontend/Browser/DownloadToast.swift | 30 +++++++++++++++++-- .../Browser/OpenInHelper/DownloadHelper.swift | 2 ++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/firefox-ios/Client/Frontend/Browser/DownloadQueue.swift b/firefox-ios/Client/Frontend/Browser/DownloadQueue.swift index 89149ef956fd..915b4c99c9d2 100644 --- a/firefox-ios/Client/Frontend/Browser/DownloadQueue.swift +++ b/firefox-ios/Client/Frontend/Browser/DownloadQueue.swift @@ -24,6 +24,8 @@ class Download: NSObject { fileprivate(set) var totalBytesExpected: Int64? fileprivate(set) var bytesDownloaded: Int64 + // Whether the server has indicated it will send encoded data (via response `Content-Encoding` header) (FXIOS-9039) + fileprivate(set) var hasContentEncoding: Bool? init(originWindow: WindowUUID) { self.filename = "unknown" @@ -117,6 +119,17 @@ class HTTPDownload: Download { } self.totalBytesExpected = preflightResponse.expectedContentLength > 0 ? preflightResponse.expectedContentLength : nil + if let contentEncodingHeader = (preflightResponse as? HTTPURLResponse)? + .allHeaderFields["Content-Encoding"] as? String, + !contentEncodingHeader.isEmpty { + // If this header is present, some encoding has been applied to the payload (likely gzip compression), so the + // above `preflightResponse.expectedContentLength` reflects the size of the encoded content, not the actual file + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding + // FXIOS-9039 + self.hasContentEncoding = true + } else { + self.hasContentEncoding = false + } self.session = URLSession(configuration: .ephemeral, delegate: self, delegateQueue: .main) self.task = session?.downloadTask(with: self.request) diff --git a/firefox-ios/Client/Frontend/Browser/DownloadToast.swift b/firefox-ios/Client/Frontend/Browser/DownloadToast.swift index 0e841d5ec494..f037f9cd026b 100644 --- a/firefox-ios/Client/Frontend/Browser/DownloadToast.swift +++ b/firefox-ios/Client/Frontend/Browser/DownloadToast.swift @@ -49,11 +49,26 @@ class DownloadToast: Toast { var downloads: [Download] = [] - var percent: CGFloat = 0.0 { + // Returns true if one or more downloads have encoded data (indicated via response `Content-Encoding` header). + // If at least one download has encoded data, we cannot get a correct total estimate for all the downloads. + // In that case, we do not show descriptive text. This will be improved in a later rework of the download manager. + // FXIOS-9039 + var hasContentEncoding: Bool { + return downloads.contains(where: { $0.hasContentEncoding ?? false }) + } + + var percent: CGFloat? = 0.0 { didSet { UIView.animate(withDuration: 0.05) { self.descriptionLabel.text = self.descriptionText - self.progressWidthConstraint?.constant = self.toastView.frame.width * self.percent + + if let percent = self.percent { + self.progressView.isHidden = false + self.progressWidthConstraint?.constant = self.toastView.frame.width * percent + } else { + self.progressView.isHidden = true + } + self.layoutIfNeeded() } } @@ -72,6 +87,11 @@ class DownloadToast: Toast { } var descriptionText: String { + guard !hasContentEncoding else { + // We cannot get a correct estimate of encoded downloaded bytes (FXIOS-9039) + return String() + } + let downloadedSize = ByteCountFormatter.string( fromByteCount: combinedBytesDownloaded, countStyle: .file @@ -144,6 +164,12 @@ class DownloadToast: Toast { func updatePercent() { DispatchQueue.main.async { + guard !self.hasContentEncoding else { + // We cannot get a correct estimate of encoded downloaded bytes (FXIOS-9039) + self.percent = nil + return + } + guard let combinedTotalBytesExpected = self.combinedTotalBytesExpected else { self.percent = 0.0 return diff --git a/firefox-ios/Client/Frontend/Browser/OpenInHelper/DownloadHelper.swift b/firefox-ios/Client/Frontend/Browser/OpenInHelper/DownloadHelper.swift index b2424f6f7402..df13e3d8ac60 100644 --- a/firefox-ios/Client/Frontend/Browser/OpenInHelper/DownloadHelper.swift +++ b/firefox-ios/Client/Frontend/Browser/OpenInHelper/DownloadHelper.swift @@ -119,6 +119,8 @@ class DownloadHelper: NSObject { var filenameItem: SingleActionViewModel var modelText = host + // This size reflects the (possibly compressed) download size of the file, not necessarily its true size. + // e.g. In the case of gzip content (FXIOS-9039) if let expectedSize = expectedSize { modelText = "\(expectedSize) — \(host)" } From 1a53ed9dd0cc3a41cc63786bbc6ee6f3667dfa48 Mon Sep 17 00:00:00 2001 From: OrlaM Date: Mon, 26 Aug 2024 16:39:21 -0400 Subject: [PATCH 111/128] Bugfix FXIOS-9815 cookie issue (#21624) * Delay webview config setup to the point it is needed * Fix tests * Remove commented code * Fix tests * Re-add create webview call --- .../xcshareddata/swiftpm/Package.resolved | 8 ++--- .../Frontend/Reader/ReadabilityService.swift | 6 ++-- .../Legacy/LegacyTabManager.swift | 15 +++------ firefox-ios/Client/TabManagement/Tab.swift | 11 +++---- .../Client/TabManagement/TabManager.swift | 3 -- .../TabManagerImplementation.swift | 5 ++- .../Autofill/FormAutofillHelperTests.swift | 6 ++-- .../BrowserCoordinatorTests.swift | 4 +-- .../Browser/TabScrollControllerTests.swift | 4 +-- .../JumpBackInDataAdaptorTests.swift | 3 +- .../JumpBackIn/JumpBackInViewModelTests.swift | 3 +- .../Helpers/AccountSyncHandlerTests.swift | 3 +- .../Mocks/MockBrowserViewController.swift | 2 +- .../ClientTests/Mocks/MockTabManager.swift | 8 ++--- .../Legacy/TabEventHandlerTests.swift | 1 - .../TabManagement/TabManagerTests.swift | 3 +- .../Tests/ClientTests/TabTests.swift | 4 +-- .../TabTray/InactiveTabsManagerTests.swift | 6 ++-- .../Tests/ClientTests/TabWebViewTests.swift | 33 +++++++++---------- .../SponsoredContentFilterUtilityTests.swift | 6 ++-- 20 files changed, 57 insertions(+), 77 deletions(-) diff --git a/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index a825940aa98b..832902767ed7 100644 --- a/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/firefox-ios/Client.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -122,8 +122,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-asn1.git", "state" : { - "revision" : "c7e239b5c1492ffc3ebd7fbcc7a92548ce4e78f0", - "version" : "1.1.0" + "revision" : "df5d2fcd22e3f480e3ef85bf23e277a4a0ef524d", + "version" : "1.2.0" } }, { @@ -140,8 +140,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/apple/swift-crypto.git", "state" : { - "revision" : "f0525da24dc3c6cbb2b6b338b65042bc91cbc4bb", - "version" : "3.3.0" + "revision" : "a53a7e8f858902659d4784322bede34f4e49097e", + "version" : "3.6.1" } }, { diff --git a/firefox-ios/Client/Frontend/Reader/ReadabilityService.swift b/firefox-ios/Client/Frontend/Reader/ReadabilityService.swift index 7fca23dae9a3..6270ea50d73d 100644 --- a/firefox-ios/Client/Frontend/Reader/ReadabilityService.swift +++ b/firefox-ios/Client/Frontend/Reader/ReadabilityService.swift @@ -46,13 +46,11 @@ class ReadabilityOperation: Operation { DispatchQueue.main.async(execute: { () in let configuration = WKWebViewConfiguration() - // TODO: To resolve profile from DI container - let windowManager: WindowManager = AppContainer.shared.resolve() let defaultUUID = windowManager.windows.first?.key ?? .unavailable - let tab = Tab(profile: self.profile, configuration: configuration, windowUUID: defaultUUID) + let tab = Tab(profile: self.profile, windowUUID: defaultUUID) self.tab = tab - tab.createWebview() + tab.createWebview(configuration: configuration) tab.navigationDelegate = self let readerMode = ReaderMode(tab: tab) diff --git a/firefox-ios/Client/TabManagement/Legacy/LegacyTabManager.swift b/firefox-ios/Client/TabManagement/Legacy/LegacyTabManager.swift index da4982b03056..f3f14e6866ea 100644 --- a/firefox-ios/Client/TabManagement/Legacy/LegacyTabManager.swift +++ b/firefox-ios/Client/TabManagement/Legacy/LegacyTabManager.swift @@ -206,7 +206,7 @@ class LegacyTabManager: NSObject, FeatureFlaggable, TabManager, TabEventHandler // MARK: - Webview configuration // A WKWebViewConfiguration used for normal tabs - private lazy var configuration: WKWebViewConfiguration = { + lazy var configuration: WKWebViewConfiguration = { return LegacyTabManager.makeWebViewConfig(isPrivate: false, prefs: profile.prefs) }() @@ -344,7 +344,6 @@ class LegacyTabManager: NSObject, FeatureFlaggable, TabManager, TabEventHandler // MARK: - Add tabs func addTab(_ request: URLRequest?, afterTab: Tab?, isPrivate: Bool) -> Tab { return addTab(request, - configuration: nil, afterTab: afterTab, flushToDisk: true, zombie: false, @@ -353,13 +352,11 @@ class LegacyTabManager: NSObject, FeatureFlaggable, TabManager, TabEventHandler @discardableResult func addTab(_ request: URLRequest! = nil, - configuration: WKWebViewConfiguration! = nil, afterTab: Tab? = nil, zombie: Bool = false, isPrivate: Bool = false ) -> Tab { return addTab(request, - configuration: configuration, afterTab: afterTab, flushToDisk: true, zombie: zombie, @@ -389,23 +386,18 @@ class LegacyTabManager: NSObject, FeatureFlaggable, TabManager, TabEventHandler } func addTab(_ request: URLRequest? = nil, - configuration: WKWebViewConfiguration? = nil, afterTab: Tab? = nil, flushToDisk: Bool, zombie: Bool, isPrivate: Bool = false ) -> Tab { - // Take the given configuration. Or if it was nil, take our default configuration for the current browsing mode. - let configuration: WKWebViewConfiguration = configuration ?? (isPrivate ? privateConfiguration : self.configuration) - - let tab = Tab(profile: profile, configuration: configuration, isPrivate: isPrivate, windowUUID: windowUUID) + let tab = Tab(profile: profile, isPrivate: isPrivate, windowUUID: windowUUID) configureTab(tab, request: request, afterTab: afterTab, flushToDisk: flushToDisk, zombie: zombie) return tab } func addPopupForParentTab(profile: Profile, parentTab: Tab, configuration: WKWebViewConfiguration) -> Tab { let popup = Tab(profile: profile, - configuration: configuration, isPrivate: parentTab.isPrivate, windowUUID: windowUUID) configureTab(popup, request: nil, afterTab: parentTab, flushToDisk: true, zombie: false, isPopup: true) @@ -455,7 +447,8 @@ class LegacyTabManager: NSObject, FeatureFlaggable, TabManager, TabEventHandler } if !zombie { - tab.createWebview() + let configuration = tab.isPrivate ? self.privateConfiguration : self.configuration + tab.createWebview(configuration: configuration) } tab.navigationDelegate = self.navDelegate diff --git a/firefox-ios/Client/TabManagement/Tab.swift b/firefox-ios/Client/TabManagement/Tab.swift index e93de32f1b9f..445cbe75e2aa 100644 --- a/firefox-ios/Client/TabManagement/Tab.swift +++ b/firefox-ios/Client/TabManagement/Tab.swift @@ -391,23 +391,21 @@ class Tab: NSObject, ThemeApplicable { // If this tab has been opened from another, its parent will point to the tab from which it was opened weak var parent: Tab? - fileprivate var contentScriptManager = TabContentScriptManager() + private var contentScriptManager = TabContentScriptManager() - fileprivate let configuration: WKWebViewConfiguration + private var configuration: WKWebViewConfiguration? /// Any time a tab tries to make requests to display a Javascript Alert and we are not the active /// tab instance, queue it for later until we become foregrounded. - fileprivate var alertQueue = [JSAlertInfo]() + private var alertQueue = [JSAlertInfo]() var profile: Profile init(profile: Profile, - configuration: WKWebViewConfiguration, isPrivate: Bool = false, windowUUID: WindowUUID, faviconHelper: SiteImageHandler = DefaultSiteImageHandler.factory(), logger: Logger = DefaultLogger.shared) { - self.configuration = configuration self.nightMode = false self.windowUUID = windowUUID self.noImageMode = false @@ -460,7 +458,8 @@ class Tab: NSObject, ThemeApplicable { } } - func createWebview(with restoreSessionData: Data? = nil) { + func createWebview(with restoreSessionData: Data? = nil, configuration: WKWebViewConfiguration) { + self.configuration = configuration if webView == nil { configuration.userContentController = WKUserContentController() configuration.allowsInlineMediaPlayback = true diff --git a/firefox-ios/Client/TabManagement/TabManager.swift b/firefox-ios/Client/TabManagement/TabManager.swift index 2db98c9be2ec..c5dcef4f3335 100644 --- a/firefox-ios/Client/TabManagement/TabManager.swift +++ b/firefox-ios/Client/TabManagement/TabManager.swift @@ -62,7 +62,6 @@ protocol TabManager: AnyObject { @discardableResult func addTab(_ request: URLRequest!, - configuration: WKWebViewConfiguration!, afterTab: Tab?, zombie: Bool, isPrivate: Bool) -> Tab @@ -131,13 +130,11 @@ extension TabManager { @discardableResult func addTab(_ request: URLRequest! = nil, - configuration: WKWebViewConfiguration! = nil, afterTab: Tab? = nil, zombie: Bool = false, isPrivate: Bool = false ) -> Tab { addTab(request, - configuration: configuration, afterTab: afterTab, zombie: zombie, isPrivate: isPrivate) diff --git a/firefox-ios/Client/TabManagement/TabManagerImplementation.swift b/firefox-ios/Client/TabManagement/TabManagerImplementation.swift index 506884993486..3254f4b8bf64 100644 --- a/firefox-ios/Client/TabManagement/TabManagerImplementation.swift +++ b/firefox-ios/Client/TabManagement/TabManagerImplementation.swift @@ -7,6 +7,7 @@ import TabDataStore import Storage import Common import Shared +import WebKit // This class subclasses the legacy tab manager temporarily so we can // gradually migrate to the new system @@ -432,7 +433,9 @@ class TabManagerImplementation: LegacyTabManager, Notifiable, WindowSimpleTabsPr private func selectTabWithSession(tab: Tab, previous: Tab?, sessionData: Data?) { assert(Thread.isMainThread, "Currently expected to be called only on main thread.") - selectedTab?.createWebview(with: sessionData) + let configuration: WKWebViewConfiguration = tab.isPrivate ? self.privateConfiguration : self.configuration + + selectedTab?.createWebview(with: sessionData, configuration: configuration) selectedTab?.lastExecutedTime = Date.now() } diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Autofill/FormAutofillHelperTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Autofill/FormAutofillHelperTests.swift index 79329d836039..0f65ebe38163 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Autofill/FormAutofillHelperTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Autofill/FormAutofillHelperTests.swift @@ -51,7 +51,7 @@ class FormAutofillHelperTests: XCTestCase { profile = MockProfile() DependencyHelperMock().bootstrapDependencies() LegacyFeatureFlagsManager.shared.initializeDeveloperFeatures(with: profile) - tab = Tab(profile: profile, configuration: WKWebViewConfiguration(), windowUUID: windowUUID) + tab = Tab(profile: profile, windowUUID: windowUUID) formAutofillHelper = FormAutofillHelper(tab: tab) secureWebviewMock = WKWebViewMock(URL(string: "https://foo.com")!) secureFrameMock = WKFrameInfoMock(webView: secureWebviewMock, frameURL: URL(string: "https://foo.com")!) @@ -281,10 +281,10 @@ class FormAutofillHelperTests: XCTestCase { } func test_formAutofillHelper_foundFieldValuesClosure_doesntLeak() { - let tab = Tab(profile: profile, configuration: WKWebViewConfiguration(), windowUUID: windowUUID) + let tab = Tab(profile: profile, windowUUID: windowUUID) let subject = FormAutofillHelper(tab: tab) trackForMemoryLeaks(subject) - tab.createWebview() + tab.createWebview(configuration: .init()) tab.addContentScript(subject, name: FormAutofillHelper.name()) subject.foundFieldValues = { fieldValues, type, frame in diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Coordinators/BrowserCoordinatorTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Coordinators/BrowserCoordinatorTests.swift index fcc02a3d046f..89fb38c9310d 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Coordinators/BrowserCoordinatorTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Coordinators/BrowserCoordinatorTests.swift @@ -286,9 +286,9 @@ final class BrowserCoordinatorTests: XCTestCase, FeatureFlaggable { } func testShowBackForwardList_presentsBackForwardListViewController() { - let mockTab = Tab(profile: profile, configuration: .init(), windowUUID: windowUUID) + let mockTab = Tab(profile: profile, windowUUID: windowUUID) mockTab.url = URL(string: "https://www.google.com") - mockTab.createWebview() + mockTab.createWebview(configuration: .init()) tabManager.selectedTab = mockTab let subject = createSubject() diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Browser/TabScrollControllerTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Browser/TabScrollControllerTests.swift index 6faa5d0d43ad..ba3c292735e2 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Browser/TabScrollControllerTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Browser/TabScrollControllerTests.swift @@ -22,7 +22,7 @@ final class TabScrollControllerTests: XCTestCase { self.mockProfile = MockProfile() self.subject = TabScrollingController(windowUUID: windowUUID) - self.tab = Tab(profile: mockProfile, configuration: WKWebViewConfiguration(), windowUUID: windowUUID) + self.tab = Tab(profile: mockProfile, windowUUID: windowUUID) LegacyFeatureFlagsManager.shared.initializeDeveloperFeatures(with: mockProfile) mockGesture = UIPanGestureRecognizerMock() DependencyHelperMock().bootstrapDependencies() @@ -92,7 +92,7 @@ final class TabScrollControllerTests: XCTestCase { } private func setupTabScroll() { - tab.createWebview() + tab.createWebview(configuration: .init()) tab.webView?.scrollView.contentSize = CGSize(width: 200, height: 2000) tab.webView?.scrollView.delegate = subject subject.tab = tab diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Home/JumpBackIn/JumpBackInDataAdaptorTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Home/JumpBackIn/JumpBackInDataAdaptorTests.swift index dcd9d5a4f855..717d022fdef1 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Home/JumpBackIn/JumpBackInDataAdaptorTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Home/JumpBackIn/JumpBackInDataAdaptorTests.swift @@ -12,7 +12,6 @@ final class JumpBackInDataAdaptorTests: XCTestCase { var mockTabManager: MockTabManager! var mockProfile: MockProfile! let sleepTime: UInt64 = 100_000_000 - let webViewConfig = WKWebViewConfiguration() let windowUUID: WindowUUID = .XCTestDefaultUUID override func setUp() { @@ -149,7 +148,7 @@ extension JumpBackInDataAdaptorTests { func createTab(profile: MockProfile, urlString: String? = "www.website.com") -> Tab { - let tab = Tab(profile: profile, configuration: webViewConfig, windowUUID: windowUUID) + let tab = Tab(profile: profile, windowUUID: windowUUID) if let urlString = urlString { tab.url = URL(string: urlString)! diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Home/JumpBackIn/JumpBackInViewModelTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Home/JumpBackIn/JumpBackInViewModelTests.swift index baf8be59d403..f18208cf7264 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Home/JumpBackIn/JumpBackInViewModelTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Home/JumpBackIn/JumpBackInViewModelTests.swift @@ -586,9 +586,8 @@ extension JumpBackInViewModelTests { } func createTab(profile: MockProfile, - configuration: WKWebViewConfiguration = WKWebViewConfiguration(), urlString: String? = "www.website.com") -> Tab { - let tab = Tab(profile: profile, configuration: configuration, windowUUID: windowUUID) + let tab = Tab(profile: profile, windowUUID: windowUUID) if let urlString = urlString { tab.url = URL(string: urlString)! diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Helpers/AccountSyncHandlerTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Helpers/AccountSyncHandlerTests.swift index cf386c6d476f..7449e1743783 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Helpers/AccountSyncHandlerTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Helpers/AccountSyncHandlerTests.swift @@ -79,9 +79,8 @@ class AccountSyncHandlerTests: XCTestCase { // MARK: - Helper methods private extension AccountSyncHandlerTests { func createTab(profile: MockProfile, - configuration: WKWebViewConfiguration = WKWebViewConfiguration(), urlString: String? = "www.website.com") -> Tab { - let tab = Tab(profile: profile, configuration: configuration, windowUUID: windowUUID) + let tab = Tab(profile: profile, windowUUID: windowUUID) if let urlString = urlString { tab.url = URL(string: urlString)! diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockBrowserViewController.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockBrowserViewController.swift index ba53d970f70f..d3fa826d348a 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockBrowserViewController.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockBrowserViewController.swift @@ -95,7 +95,7 @@ class MockBrowserViewController: BrowserViewController { openURLInNewTabURL = url openURLInNewTabIsPrivate = isPrivate openURLInNewTabCount += 1 - return Tab(profile: MockProfile(), configuration: .init(), windowUUID: windowUUID) + return Tab(profile: MockProfile(), windowUUID: windowUUID) } override func handleQRCode() { diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockTabManager.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockTabManager.swift index 532224541b82..1c7dee21dc14 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockTabManager.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Mocks/MockTabManager.swift @@ -62,9 +62,8 @@ class MockTabManager: TabManager { } func addTab(_ request: URLRequest?, afterTab: Tab?, isPrivate: Bool) -> Tab { - let configuration = WKWebViewConfiguration() let profile = MockProfile() - let tab = Tab(profile: profile, configuration: configuration, isPrivate: isPrivate, windowUUID: windowUUID) + let tab = Tab(profile: profile, isPrivate: isPrivate, windowUUID: windowUUID) tabs.append(tab) return tab } @@ -137,7 +136,7 @@ class MockTabManager: TabManager { } func addPopupForParentTab(profile: Profile, parentTab: Tab, configuration: WKWebViewConfiguration) -> Tab { - return Tab(profile: MockProfile(), configuration: WKWebViewConfiguration(), windowUUID: windowUUID) + return Tab(profile: MockProfile(), windowUUID: windowUUID) } func makeToastFromRecentlyClosedUrls(_ recentlyClosedTabs: [Tab], @@ -148,12 +147,11 @@ class MockTabManager: TabManager { @discardableResult func addTab(_ request: URLRequest!, - configuration: WKWebViewConfiguration!, afterTab: Tab?, zombie: Bool, isPrivate: Bool ) -> Tab { - return Tab(profile: MockProfile(), configuration: WKWebViewConfiguration(), windowUUID: windowUUID) + return Tab(profile: MockProfile(), windowUUID: windowUUID) } func backgroundRemoveAllTabs(isPrivate: Bool, diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/TabManagement/Legacy/TabEventHandlerTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/TabManagement/Legacy/TabEventHandlerTests.swift index 5b604249fb3a..3c587b564528 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/TabManagement/Legacy/TabEventHandlerTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/TabManagement/Legacy/TabEventHandlerTests.swift @@ -14,7 +14,6 @@ class TabEventHandlerTests: XCTestCase { let windowUUID: WindowUUID = .XCTestDefaultUUID func testEventDelivery() { let tab = Tab(profile: MockProfile(), - configuration: WKWebViewConfiguration(), windowUUID: windowUUID) let handler = DummyHandler() diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/TabManagement/TabManagerTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/TabManagement/TabManagerTests.swift index bd952d909176..7b3b6e78bd95 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/TabManagement/TabManagerTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/TabManagement/TabManagerTests.swift @@ -16,7 +16,6 @@ class TabManagerTests: XCTestCase { var mockSessionStore: MockTabSessionStore! var mockProfile: MockProfile! var mockDiskImageStore: MockDiskImageStore! - let webViewConfig = WKWebViewConfiguration() let sleepTime: UInt64 = 1 * NSEC_PER_SEC let windowUUID: WindowUUID = .XCTestDefaultUUID @@ -219,7 +218,7 @@ class TabManagerTests: XCTestCase { private func addTabs(to subject: TabManagerImplementation, count: Int) { for _ in 0.. [Tab] { var tabs = [Tab]() for _ in 0.. TabWebView { - let subject = TabWebView(frame: .zero, configuration: configuration, windowUUID: windowUUID) + let subject = TabWebView(frame: .zero, configuration: .init(), windowUUID: windowUUID) try await Task.sleep(nanoseconds: sleepTime) subject.configure(delegate: tabWebViewDelegate, navigationDelegate: navigationDelegate) trackForMemoryLeaks(subject) diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Utils/SponsoredContentFilterUtilityTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Utils/SponsoredContentFilterUtilityTests.swift index 6844bdba1feb..59ec8b8735ad 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Utils/SponsoredContentFilterUtilityTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Utils/SponsoredContentFilterUtilityTests.swift @@ -150,18 +150,18 @@ extension SponsoredContentFilterUtilityTests { sponsoredTabsCount: Int) -> [Tab] { var tabs = [Tab]() (0.. Date: Tue, 27 Aug 2024 08:10:38 +0100 Subject: [PATCH 112/128] Bugfix FXIOS-9740 [Toolbar redesign] The hamburger menu is not displayed in landscape mode (#21621) * Display the correct address toolbar depending on the state * Fix wrong layout displayed in certain cases --- .../Toolbars/AddressToolbarContainer.swift | 24 +++++++++++-------- .../Models/AddressToolbarContainerModel.swift | 6 +++++ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/AddressToolbarContainer.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/AddressToolbarContainer.swift index 207a5820a837..dd329b07342d 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/AddressToolbarContainer.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/AddressToolbarContainer.swift @@ -43,8 +43,15 @@ final class AddressToolbarContainer: UIView, private(set) weak var delegate: AddressToolbarContainerDelegate? private var toolbar: BrowserAddressToolbar { - let isCompact = traitCollection.horizontalSizeClass == .compact - return isCompact ? compactToolbar : regularToolbar + return shouldDisplayCompact ? compactToolbar : regularToolbar + } + + private var shouldDisplayCompact: Bool { + guard let model else { + return traitCollection.horizontalSizeClass == .compact + } + + return model.shouldDisplayCompact } private var isTransitioning = false { @@ -73,7 +80,7 @@ final class AddressToolbarContainer: UIView, window: windowUUID) else { return nil } - let isCompact = traitCollection.horizontalSizeClass == .compact + let isCompact = shouldDisplayCompact let isHomepage = toolbarState.addressToolbar.url == nil let isEditing = toolbarState.addressToolbar.isEditing @@ -93,7 +100,7 @@ final class AddressToolbarContainer: UIView, window: windowUUID) else { return nil } - let isCompact = traitCollection.horizontalSizeClass == .compact + let isCompact = shouldDisplayCompact let isHomepage = toolbarState.addressToolbar.url == nil let isEditing = toolbarState.addressToolbar.isEditing @@ -149,12 +156,6 @@ final class AddressToolbarContainer: UIView, return toolbar.resignFirstResponder() } - // MARK: View Transitions - override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { - super.traitCollectionDidChange(previousTraitCollection) - adjustLayout() - } - // MARK: - Redux func subscribeToRedux() { @@ -213,6 +214,9 @@ final class AddressToolbarContainer: UIView, leadingSpace: leadingToolbarSpace, trailingSpace: trailingToolbarSpace) + // the layout (compact/regular) that should be displayed is driven by the state + adjustLayout() + // Dismiss overlay mode when not editing to fix overlay mode staying open // on iPad when switching tabs using top tabs if !toolbarState.addressToolbar.isEditing { diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift index a4aa0a1d9abb..3637e1c5b8c8 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift @@ -19,6 +19,7 @@ class AddressToolbarContainerModel: Equatable { let searchTerm: String? let isEditing: Bool let shouldSelectSearchTerm: Bool + let shouldDisplayCompact: Bool let windowUUID: UUID @@ -77,6 +78,7 @@ class AddressToolbarContainerModel: Equatable { self.searchTerm = state.addressToolbar.searchTerm self.isEditing = state.addressToolbar.isEditing self.shouldSelectSearchTerm = state.addressToolbar.shouldSelectSearchTerm + self.shouldDisplayCompact = state.isShowingNavigationToolbar } func searchTermFromURL(_ url: URL?, searchEngines: SearchEngines) -> String? { @@ -133,12 +135,16 @@ class AddressToolbarContainerModel: Equatable { lhs.navigationActions == rhs.navigationActions && lhs.pageActions == rhs.pageActions && lhs.browserActions == rhs.browserActions && + lhs.borderPosition == rhs.borderPosition && lhs.searchEngineImage == rhs.searchEngineImage && lhs.lockIconImageName == rhs.lockIconImageName && lhs.url == rhs.url && lhs.searchTerm == rhs.searchTerm && lhs.isEditing == rhs.isEditing && + lhs.shouldSelectSearchTerm == rhs.shouldSelectSearchTerm && + lhs.shouldDisplayCompact == rhs.shouldDisplayCompact && + lhs.windowUUID == rhs.windowUUID } } From 2c7bc6837f0f4ab07d493a905fa3e8add5824686 Mon Sep 17 00:00:00 2001 From: Winnie Teichmann <4530+thatswinnie@users.noreply.github.com> Date: Tue, 27 Aug 2024 13:33:32 +0100 Subject: [PATCH 113/128] Refactor FXIOS-9854 Replace DefaultChromeSmallSize & DefaultChromeSmallFontBold with FXFontStyles (#21634) * Replace DefaultChromeSmallSize & DefaultChromeSmallFontBold with FXFontStyles * Remove static fonts --- firefox-ios/Client/Frontend/UIConstants.swift | 4 ---- .../Widgets/PhotonActionSheet/PhotonActionSheetView.swift | 2 +- firefox-ios/Client/Frontend/Widgets/TabsButton.swift | 2 +- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/firefox-ios/Client/Frontend/UIConstants.swift b/firefox-ios/Client/Frontend/UIConstants.swift index 8715cffeae82..3f2998378686 100644 --- a/firefox-ios/Client/Frontend/UIConstants.swift +++ b/firefox-ios/Client/Frontend/UIConstants.swift @@ -14,10 +14,6 @@ public struct UIConstants { static var ToolbarPadding: CGFloat = 17 static let ZoomPageBarHeight: CGFloat = 54 - // Static fonts - static let DefaultChromeSmallSize: CGFloat = 11 - static let DefaultChromeSmallFontBold = UIFont.boldSystemFont(ofSize: DefaultChromeSmallSize) - /// JPEG compression quality for persisted screenshots. Must be between 0-1. static let ScreenshotQuality: Float = 1 static let ActiveScreenshotQuality: CGFloat = 0.5 diff --git a/firefox-ios/Client/Frontend/Widgets/PhotonActionSheet/PhotonActionSheetView.swift b/firefox-ios/Client/Frontend/Widgets/PhotonActionSheet/PhotonActionSheetView.swift index 938ad685010c..a305455fc8ee 100644 --- a/firefox-ios/Client/Frontend/Widgets/PhotonActionSheet/PhotonActionSheetView.swift +++ b/firefox-ios/Client/Frontend/Widgets/PhotonActionSheet/PhotonActionSheetView.swift @@ -110,7 +110,7 @@ class PhotonActionSheetView: UIView, UIGestureRecognizerDelegate, ThemeApplicabl } private lazy var tabsLabel: UILabel = .build { label in - label.font = UIFont.boldSystemFont(ofSize: UIConstants.DefaultChromeSmallSize) + label.font = FXFontStyles.Bold.caption2.systemFont() } lazy var bottomBorder: UIView = .build { _ in } diff --git a/firefox-ios/Client/Frontend/Widgets/TabsButton.swift b/firefox-ios/Client/Frontend/Widgets/TabsButton.swift index 4c9b38a2d84d..4be0e0063ef1 100644 --- a/firefox-ios/Client/Frontend/Widgets/TabsButton.swift +++ b/firefox-ios/Client/Frontend/Widgets/TabsButton.swift @@ -9,7 +9,7 @@ import Common class TabsButton: UIButton, ThemeApplicable { struct UX { static let cornerRadius: CGFloat = 2 - static let titleFont: UIFont = UIConstants.DefaultChromeSmallFontBold + static let titleFont: UIFont = FXFontStyles.Bold.caption2.systemFont() static let insideButtonSize: CGFloat = 24 // Animation constants From 900a8c94e22d4e8a5b7209a2b2aee87c17585594 Mon Sep 17 00:00:00 2001 From: "roux g. buciu" <11182210+adudenamedruby@users.noreply.github.com> Date: Tue, 27 Aug 2024 09:53:30 -0400 Subject: [PATCH 114/128] Add FXIOS-9121 [Menu] Create menu kit (#21626) * Add menu kit * Add to test plan * Add dummy test --- BrowserKit/Package.swift | 10 ++++++ BrowserKit/Sources/MenuKit/MenuElement.swift | 33 +++++++++++++++++++ .../Tests/MenuKitTests/MenuKitTests.swift | 31 +++++++++++++++++ .../Tests/UnitTest.xctestplan | 7 ++++ 4 files changed, 81 insertions(+) create mode 100644 BrowserKit/Sources/MenuKit/MenuElement.swift create mode 100644 BrowserKit/Tests/MenuKitTests/MenuKitTests.swift diff --git a/BrowserKit/Package.swift b/BrowserKit/Package.swift index e3e5ecf3ff75..717844cf1b8a 100644 --- a/BrowserKit/Package.swift +++ b/BrowserKit/Package.swift @@ -30,6 +30,9 @@ let package = Package( .library( name: "ToolbarKit", targets: ["ToolbarKit"]), + .library( + name: "MenuKit", + targets: ["MenuKit"]), .library( name: "ContentBlockingGenerator", targets: ["ContentBlockingGenerator"]), @@ -109,6 +112,13 @@ let package = Package( .testTarget( name: "ToolbarKitTests", dependencies: ["ToolbarKit"]), + .target( + name: "MenuKit", + dependencies: ["Common"], + swiftSettings: [.unsafeFlags(["-enable-testing"])]), + .testTarget( + name: "MenuKitTests", + dependencies: ["MenuKit"]), .target( name: "ContentBlockingGenerator", swiftSettings: [.unsafeFlags(["-enable-testing"])]), diff --git a/BrowserKit/Sources/MenuKit/MenuElement.swift b/BrowserKit/Sources/MenuKit/MenuElement.swift new file mode 100644 index 000000000000..cd0a62284134 --- /dev/null +++ b/BrowserKit/Sources/MenuKit/MenuElement.swift @@ -0,0 +1,33 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/ + +import UIKit + +public struct MenuElement: Equatable { + let iconName: String + let isEnabled: Bool + let isActive: Bool + let hasSubmenu: Bool + let a11yLabel: String + let a11yHint: String? + let a11yId: String + + // We need this init as by default the init generated by the compiler + // for the struct will be internal and can not be used outside of MenuKit + public init(iconName: String, + isEnabled: Bool, + isActive: Bool, + hasSubmenu: Bool, + a11yLabel: String, + a11yHint: String?, + a11yId: String) { + self.iconName = iconName + self.isEnabled = isEnabled + self.isActive = isActive + self.hasSubmenu = hasSubmenu + self.a11yLabel = a11yLabel + self.a11yHint = a11yHint + self.a11yId = a11yId + } +} diff --git a/BrowserKit/Tests/MenuKitTests/MenuKitTests.swift b/BrowserKit/Tests/MenuKitTests/MenuKitTests.swift new file mode 100644 index 000000000000..060b84dd9ea8 --- /dev/null +++ b/BrowserKit/Tests/MenuKitTests/MenuKitTests.swift @@ -0,0 +1,31 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/ + +import XCTest +@testable import MenuKit + +final class MenuKitTests: XCTestCase { + func testMenuElement_initializesCorrectly() { + let subject = MenuElement( + iconName: "test", + isEnabled: true, + isActive: true, + hasSubmenu: false, + a11yLabel: "test", + a11yHint: nil, + a11yId: "test" + ) + let expectedResult = MenuElement( + iconName: "test", + isEnabled: true, + isActive: true, + hasSubmenu: false, + a11yLabel: "test", + a11yHint: nil, + a11yId: "test" + ) + + XCTAssertEqual(subject, expectedResult) + } +} diff --git a/firefox-ios/firefox-ios-tests/Tests/UnitTest.xctestplan b/firefox-ios/firefox-ios-tests/Tests/UnitTest.xctestplan index 7e648b90ce68..27bc57e3417b 100644 --- a/firefox-ios/firefox-ios-tests/Tests/UnitTest.xctestplan +++ b/firefox-ios/firefox-ios-tests/Tests/UnitTest.xctestplan @@ -206,6 +206,13 @@ "identifier" : "ContentBlockingGeneratorTests", "name" : "ContentBlockingGeneratorTests" } + }, + { + "target" : { + "containerPath" : "container:..\/BrowserKit", + "identifier" : "MenuKitTests", + "name" : "MenuKitTests" + } } ], "version" : 1 From e7ecff12a35b3be8a33d7130b411282c686cdeef Mon Sep 17 00:00:00 2001 From: Winnie Teichmann <4530+thatswinnie@users.noreply.github.com> Date: Tue, 27 Aug 2024 16:36:50 +0100 Subject: [PATCH 115/128] Refactor FXIOS-9298 Apply private mode UI if necessary (#21635) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Apply private mode UI to new toolbar * Don’t apply private mode UI to address toolbar * Remove unused code * Add comment * Update comment to fix Swiftlint --- .../Views/BrowserViewController.swift | 12 ++++++++---- .../Browser/Toolbars/AddressToolbarContainer.swift | 12 +++++++++--- .../Models/AddressToolbarContainerModel.swift | 2 ++ 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift index 4704db60961b..853a5597844f 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift @@ -2861,8 +2861,8 @@ class BrowserViewController: UIViewController, $0.applyTheme(theme: currentTheme) } - let isPrivate = (currentTheme.type == .privateMode) if !isToolbarRefactorEnabled { + let isPrivate = (currentTheme.type == .privateMode) urlBar.applyUIMode(isPrivate: isPrivate, theme: currentTheme) } @@ -3531,10 +3531,14 @@ extension BrowserViewController: TabManagerDelegate { if previousTab == nil || selectedTab.isPrivate != previousTab?.isPrivate { applyTheme() - if !isToolbarRefactorEnabled { - let ui: [PrivateModeUI?] = [toolbar, topTabsViewController, urlBar] - ui.forEach { $0?.applyUIMode(isPrivate: selectedTab.isPrivate, theme: currentTheme()) } + // TODO: [FXIOS-8907] Ideally we shouldn't create tabs as a side-effect of UI theme updates. + var ui = [PrivateModeUI?]() + if isToolbarRefactorEnabled { + ui = [topTabsViewController] + } else { + ui = [toolbar, topTabsViewController, urlBar] } + ui.forEach { $0?.applyUIMode(isPrivate: selectedTab.isPrivate, theme: currentTheme()) } } else { // Theme is applied to the tab and webView in the else case // because in the if block is applied already to all the tabs and web views diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/AddressToolbarContainer.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/AddressToolbarContainer.swift index dd329b07342d..32609efa97c7 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/AddressToolbarContainer.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/AddressToolbarContainer.swift @@ -265,10 +265,16 @@ final class AddressToolbarContainer: UIView, func applyTheme(theme: Theme) { compactToolbar.applyTheme(theme: theme) regularToolbar.applyTheme(theme: theme) + + let isPrivateMode = model?.isPrivateMode ?? false + let gradientStartColor = isPrivateMode ? theme.colors.borderAccentPrivate : theme.colors.borderAccent + let gradientMiddleColor = isPrivateMode ? nil : theme.colors.iconAccentPink + let gradientEndColor = isPrivateMode ? theme.colors.borderAccentPrivate : theme.colors.iconAccentYellow + progressBar.setGradientColors( - startColor: theme.colors.borderAccent, - middleColor: theme.colors.iconAccentPink, - endColor: theme.colors.iconAccentYellow + startColor: gradientStartColor, + middleColor: gradientMiddleColor, + endColor: gradientEndColor ) } diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift index 3637e1c5b8c8..c5667422877e 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift @@ -18,6 +18,7 @@ class AddressToolbarContainerModel: Equatable { let url: URL? let searchTerm: String? let isEditing: Bool + let isPrivateMode: Bool let shouldSelectSearchTerm: Bool let shouldDisplayCompact: Bool @@ -77,6 +78,7 @@ class AddressToolbarContainerModel: Equatable { self.url = state.addressToolbar.url self.searchTerm = state.addressToolbar.searchTerm self.isEditing = state.addressToolbar.isEditing + self.isPrivateMode = state.isPrivateMode self.shouldSelectSearchTerm = state.addressToolbar.shouldSelectSearchTerm self.shouldDisplayCompact = state.isShowingNavigationToolbar } From 89cad7e4d913c2e12669316ee65a2f1be4a382fb Mon Sep 17 00:00:00 2001 From: Matt Lichtenstein Date: Tue, 27 Aug 2024 12:44:22 -0400 Subject: [PATCH 116/128] Add FXIOS-9713 Data clearance CFR for toolbar refactor (#21622) --- .../AddressToolbar/AddressToolbarDelegate.swift | 1 + .../AddressToolbar/BrowserAddressToolbar.swift | 6 +++++- .../BrowserNavigationToolbar.swift | 13 ++++++++++++- .../NavigationToolbar/NavigationToolbar.swift | 2 +- .../Sources/ToolbarKit/ToolbarElement.swift | 5 +++++ ...owserViewController+TabToolbarDelegate.swift | 9 ++++----- .../Views/BrowserViewController.swift | 17 ++++++++++++++++- .../Toolbars/AddressToolbarContainer.swift | 7 +++++++ .../Models/AddressToolbarContainerModel.swift | 1 + .../NavigationToolbarContainerModel.swift | 1 + .../Toolbars/NavigationToolbarContainer.swift | 13 ++++++++++++- .../Toolbars/Redux/ToolbarActionState.swift | 1 + .../Toolbars/Redux/ToolbarMiddleware.swift | 1 + .../Toolbar+URLBar/TabToolbarHelper.swift | 2 +- 14 files changed, 68 insertions(+), 11 deletions(-) diff --git a/BrowserKit/Sources/ToolbarKit/AddressToolbar/AddressToolbarDelegate.swift b/BrowserKit/Sources/ToolbarKit/AddressToolbar/AddressToolbarDelegate.swift index 962705a0421f..180ecc2bb4a0 100644 --- a/BrowserKit/Sources/ToolbarKit/AddressToolbar/AddressToolbarDelegate.swift +++ b/BrowserKit/Sources/ToolbarKit/AddressToolbar/AddressToolbarDelegate.swift @@ -10,4 +10,5 @@ public protocol AddressToolbarDelegate: AnyObject { func openBrowser(searchTerm: String) func openSuggestions(searchTerm: String) func addressToolbarAccessibilityActions() -> [UIAccessibilityCustomAction]? + func configureContextualHint(_ addressToolbar: BrowserAddressToolbar, for button: UIButton) } diff --git a/BrowserKit/Sources/ToolbarKit/AddressToolbar/BrowserAddressToolbar.swift b/BrowserKit/Sources/ToolbarKit/AddressToolbar/BrowserAddressToolbar.swift index a072e7dee72e..4b47d37bc953 100644 --- a/BrowserKit/Sources/ToolbarKit/AddressToolbar/BrowserAddressToolbar.swift +++ b/BrowserKit/Sources/ToolbarKit/AddressToolbar/BrowserAddressToolbar.swift @@ -64,8 +64,8 @@ public class BrowserAddressToolbar: UIView, AddressToolbar, ThemeApplicable, Loc toolbarDelegate: any AddressToolbarDelegate, leadingSpace: CGFloat?, trailingSpace: CGFloat?) { - configure(state: state) self.toolbarDelegate = toolbarDelegate + configure(state: state) updateSpacing(leading: leadingSpace, trailing: trailingSpace) } @@ -218,6 +218,10 @@ public class BrowserAddressToolbar: UIView, AddressToolbar, ThemeApplicable, Loc // As we recreate the buttons we need to apply the theme for them to be displayed correctly button.applyTheme(theme: theme) } + + if toolbarElement.hasContextualHint == true { + toolbarDelegate?.configureContextualHint(self, for: button) + } } } diff --git a/BrowserKit/Sources/ToolbarKit/NavigationToolbar/BrowserNavigationToolbar.swift b/BrowserKit/Sources/ToolbarKit/NavigationToolbar/BrowserNavigationToolbar.swift index 1b2ae0c90f16..aee530f2c1c7 100644 --- a/BrowserKit/Sources/ToolbarKit/NavigationToolbar/BrowserNavigationToolbar.swift +++ b/BrowserKit/Sources/ToolbarKit/NavigationToolbar/BrowserNavigationToolbar.swift @@ -5,6 +5,10 @@ import UIKit import Common +public protocol BrowserNavigationToolbarDelegate: AnyObject { + func configureContextualHint(for button: UIButton) +} + /// Navigation toolbar implementation. public class BrowserNavigationToolbar: UIView, NavigationToolbar, ThemeApplicable { private enum UX { @@ -13,6 +17,7 @@ public class BrowserNavigationToolbar: UIView, NavigationToolbar, ThemeApplicabl static let borderHeight: CGFloat = 1 } + private weak var toolbarDelegate: BrowserNavigationToolbarDelegate? private lazy var actionStack: UIStackView = .build { view in view.distribution = .equalSpacing } @@ -29,7 +34,9 @@ public class BrowserNavigationToolbar: UIView, NavigationToolbar, ThemeApplicabl fatalError("init(coder:) has not been implemented") } - public func configure(state: NavigationToolbarState) { + public func configure(state: NavigationToolbarState, toolbarDelegate: BrowserNavigationToolbarDelegate) { + self.toolbarDelegate = toolbarDelegate + updateActionStack(toolbarElements: state.actions) // Update border @@ -72,6 +79,10 @@ public class BrowserNavigationToolbar: UIView, NavigationToolbar, ThemeApplicabl // As we recreate the buttons we need to apply the theme for them to be displayed correctly button.applyTheme(theme: theme) } + + if toolbarElement.hasContextualHint == true { + toolbarDelegate?.configureContextualHint(for: button) + } } } diff --git a/BrowserKit/Sources/ToolbarKit/NavigationToolbar/NavigationToolbar.swift b/BrowserKit/Sources/ToolbarKit/NavigationToolbar/NavigationToolbar.swift index b99d6a9f2a21..bfbf8c51cb12 100644 --- a/BrowserKit/Sources/ToolbarKit/NavigationToolbar/NavigationToolbar.swift +++ b/BrowserKit/Sources/ToolbarKit/NavigationToolbar/NavigationToolbar.swift @@ -6,5 +6,5 @@ import Foundation /// Protocol representing an navigation toolbar. public protocol NavigationToolbar { - func configure(state: NavigationToolbarState) + func configure(state: NavigationToolbarState, toolbarDelegate: BrowserNavigationToolbarDelegate) } diff --git a/BrowserKit/Sources/ToolbarKit/ToolbarElement.swift b/BrowserKit/Sources/ToolbarKit/ToolbarElement.swift index bf1eaf625bcf..853d6eff69e3 100644 --- a/BrowserKit/Sources/ToolbarKit/ToolbarElement.swift +++ b/BrowserKit/Sources/ToolbarKit/ToolbarElement.swift @@ -26,6 +26,9 @@ public struct ToolbarElement: Equatable { /// Indicates if the element should be displayed as highlighted let shouldDisplayAsHighlighted: Bool + /// Indicates that there is an associated contextual hint + let hasContextualHint: Bool? + /// Accessibility label of the toolbar element let a11yLabel: String @@ -56,6 +59,7 @@ public struct ToolbarElement: Equatable { isEnabled: Bool, isFlippedForRTL: Bool = false, shouldDisplayAsHighlighted: Bool = false, + hasContextualHint: Bool = false, a11yLabel: String, a11yHint: String?, a11yId: String, @@ -70,6 +74,7 @@ public struct ToolbarElement: Equatable { self.isEnabled = isEnabled self.isFlippedForRTL = isFlippedForRTL self.shouldDisplayAsHighlighted = shouldDisplayAsHighlighted + self.hasContextualHint = hasContextualHint self.onSelected = onSelected self.onLongPress = onLongPress self.a11yLabel = a11yLabel diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+TabToolbarDelegate.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+TabToolbarDelegate.swift index a7082fc687db..17edbcc63167 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+TabToolbarDelegate.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+TabToolbarDelegate.swift @@ -15,17 +15,16 @@ extension BrowserViewController: TabToolbarDelegate, PhotonActionSheetProtocol { dataClearanceContextHintVC.stopTimer() } - func configureDataClearanceContextualHint() { - guard !isToolbarRefactorEnabled, - contentContainer.hasWebView, + func configureDataClearanceContextualHint(_ view: UIView) { + guard contentContainer.hasWebView, tabManager.selectedTab?.url?.displayURL?.isWebPage() == true else { resetDataClearanceCFRTimer() return } dataClearanceContextHintVC.configure( - anchor: navigationToolbar.multiStateButton, - withArrowDirection: topTabsVisible ? .up : .down, + anchor: view, + withArrowDirection: ToolbarHelper().shouldShowNavigationToolbar(for: traitCollection) ? .down : .up, andDelegate: self, presentedUsing: { [weak self] in self?.presentDataClearanceContextualHint() }, andActionForButton: { }, diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift index 853a5597844f..ba4593e04104 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift @@ -29,6 +29,7 @@ class BrowserViewController: UIViewController, QRCodeViewControllerDelegate, StoreSubscriber, BrowserFrameInfoProvider, + NavigationToolbarContainerDelegate, AddressToolbarContainerDelegate, FeatureFlaggable { private enum UX { @@ -692,6 +693,8 @@ class BrowserViewController: UIViewController, clipboardBarDisplayHandler = ClipboardBarDisplayHandler(prefs: profile.prefs, tabManager: tabManager) clipboardBarDisplayHandler?.delegate = self + navigationToolbarContainer.toolbarDelegate = self + scrollController.header = header scrollController.overKeyboardContainer = overKeyboardContainer scrollController.bottomContainer = bottomContainer @@ -1037,6 +1040,13 @@ class BrowserViewController: UIViewController, themeManager.applyThemeUpdatesToWindows() } setupMiddleButtonStatus(isLoading: false) + + // Everything works fine on iPad orientation switch (because CFR remains anchored to the same button), + // so only necessary to dismiss when vertical size class changes + if dataClearanceContextHintVC.isPresenting && + previousTraitCollection?.verticalSizeClass != traitCollection.verticalSizeClass { + dataClearanceContextHintVC.dismiss(animated: true) + } } // MARK: - Constraints @@ -1665,8 +1675,8 @@ class BrowserViewController: UIViewController, guard !showFireButton else { if !isToolbarRefactorEnabled { navigationToolbar.updateMiddleButtonState(.fire) + configureDataClearanceContextualHint(navigationToolbar.multiStateButton) } - configureDataClearanceContextualHint() return } resetDataClearanceCFRTimer() @@ -3021,6 +3031,11 @@ class BrowserViewController: UIViewController, searchController?.searchTelemetry?.determineInteractionType() } + // Also implements NavigationToolbarContainerDelegate::configureContextualHint(for button: UIButton) + func configureContextualHint(for button: UIButton) { + configureDataClearanceContextualHint(button) + } + func addressToolbarContainerAccessibilityActions() -> [UIAccessibilityCustomAction]? { locationActionsForURLBar().map { $0.accessibilityCustomAction } } diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/AddressToolbarContainer.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/AddressToolbarContainer.swift index 32609efa97c7..71db289bb6b5 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/AddressToolbarContainer.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/AddressToolbarContainer.swift @@ -11,6 +11,7 @@ protocol AddressToolbarContainerDelegate: AnyObject { func searchSuggestions(searchTerm: String) func openBrowser(searchTerm: String) func openSuggestions(searchTerm: String) + func configureContextualHint(for button: UIButton) func addressToolbarContainerAccessibilityActions() -> [UIAccessibilityCustomAction]? func addressToolbarDidEnterOverlayMode(_ view: UIView) func addressToolbar(_ view: UIView, didLeaveOverlayModeForReason: URLBarLeaveOverlayModeReason) @@ -301,6 +302,12 @@ final class AddressToolbarContainer: UIView, delegate?.addressToolbarContainerAccessibilityActions() } + func configureContextualHint(_ addressToolbar: BrowserAddressToolbar, for button: UIButton) { + if addressToolbar == toolbar { + delegate?.configureContextualHint(for: button) + } + } + // MARK: - MenuHelperURLBarInterface override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool { if action == MenuHelperURLBarModel.selectorPasteAndGo { diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift index c5667422877e..c0d3b7cf6071 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/AddressToolbarContainerModel.swift @@ -104,6 +104,7 @@ class AddressToolbarContainerModel: Equatable { isEnabled: action.isEnabled, isFlippedForRTL: action.isFlippedForRTL, shouldDisplayAsHighlighted: action.shouldDisplayAsHighlighted, + hasContextualHint: action.hasContextualHint, a11yLabel: action.a11yLabel, a11yHint: action.a11yHint, a11yId: action.a11yId, diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/NavigationToolbarContainerModel.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/NavigationToolbarContainerModel.swift index 5422c77e5d18..20660a6fc04e 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Models/NavigationToolbarContainerModel.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Models/NavigationToolbarContainerModel.swift @@ -25,6 +25,7 @@ struct NavigationToolbarContainerModel: Equatable { isEnabled: action.isEnabled, isFlippedForRTL: action.isFlippedForRTL, shouldDisplayAsHighlighted: action.shouldDisplayAsHighlighted, + hasContextualHint: action.hasContextualHint, a11yLabel: action.a11yLabel, a11yHint: action.a11yHint, a11yId: action.a11yId, diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/NavigationToolbarContainer.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/NavigationToolbarContainer.swift index 8320cb441693..9694f677fb00 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/NavigationToolbarContainer.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/NavigationToolbarContainer.swift @@ -7,6 +7,10 @@ import ToolbarKit import Redux import UIKit +protocol NavigationToolbarContainerDelegate: AnyObject { + func configureContextualHint(for: UIButton) +} + class NavigationToolbarContainer: UIView, ThemeApplicable, StoreSubscriber { typealias SubscriberStateType = ToolbarState @@ -19,6 +23,7 @@ class NavigationToolbarContainer: UIView, ThemeApplicable, StoreSubscriber { subscribeToRedux() } } + weak var toolbarDelegate: NavigationToolbarContainerDelegate? private var toolbarState: ToolbarState? private var model: NavigationToolbarContainerModel? @@ -69,7 +74,7 @@ class NavigationToolbarContainer: UIView, ThemeApplicable, StoreSubscriber { if self.model != model { self.model = model - toolbar.configure(state: model.navigationToolbarState) + toolbar.configure(state: model.navigationToolbarState, toolbarDelegate: self) } } @@ -93,3 +98,9 @@ class NavigationToolbarContainer: UIView, ThemeApplicable, StoreSubscriber { backgroundColor = theme.colors.layer1 } } + +extension NavigationToolbarContainer: BrowserNavigationToolbarDelegate { + func configureContextualHint(for button: UIButton) { + toolbarDelegate?.configureContextualHint(for: button) + } +} diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarActionState.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarActionState.swift index b1ce7f012fc8..de2a2c7c9c3b 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarActionState.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarActionState.swift @@ -33,6 +33,7 @@ struct ToolbarActionState: Equatable, FeatureFlaggable { var isShowingTopTabs: Bool? var isEnabled: Bool var shouldDisplayAsHighlighted = false + var hasContextualHint = false var a11yLabel: String var a11yHint: String? var a11yId: String diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift index 8c1218e0085c..b14ec5ca6833 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift @@ -98,6 +98,7 @@ final class ToolbarMiddleware: FeatureFlaggable { actionType: .dataClearance, iconName: StandardImageIdentifiers.Large.dataClearance, isEnabled: true, + hasContextualHint: true, a11yLabel: .TabToolbarDataClearanceAccessibilityLabel, a11yId: AccessibilityIdentifiers.Toolbar.fireButton) diff --git a/firefox-ios/Client/Frontend/Toolbar+URLBar/TabToolbarHelper.swift b/firefox-ios/Client/Frontend/Toolbar+URLBar/TabToolbarHelper.swift index d97023bc7f3d..8d74110451bc 100644 --- a/firefox-ios/Client/Frontend/Toolbar+URLBar/TabToolbarHelper.swift +++ b/firefox-ios/Client/Frontend/Toolbar+URLBar/TabToolbarHelper.swift @@ -29,7 +29,7 @@ protocol TabToolbarProtocol: AnyObject { } protocol TabToolbarDelegate: AnyObject { - func configureDataClearanceContextualHint() + func configureDataClearanceContextualHint(_ view: UIView) func tabToolbarDidPressBack(_ tabToolbar: TabToolbarProtocol, button: UIButton) func tabToolbarDidPressForward(_ tabToolbar: TabToolbarProtocol, button: UIButton) func tabToolbarDidLongPressBack(_ tabToolbar: TabToolbarProtocol, button: UIButton) From 3cdeff392f93205ed97560112711aba1cdfe2d87 Mon Sep 17 00:00:00 2001 From: "roux g. buciu" <11182210+adudenamedruby@users.noreply.github.com> Date: Tue, 27 Aug 2024 13:01:38 -0400 Subject: [PATCH 117/128] Add FXIOS-9132 [Strings] Menu strings (#21637) * Add strings * Changes for AppMenu * Swiftlints --- .../ShareExtensionCoordinator.swift | 4 +- ...serViewController+TabToolbarDelegate.swift | 2 +- .../Views/BrowserViewController.swift | 11 +- .../Browser/MainMenuActionHelper.swift | 71 ++--- .../Legacy/LegacyGridTabViewController.swift | 4 +- .../LegacyTabPeekPreviewActionBuilder.swift | 2 +- .../Legacy/LegacyTabPeekViewController.swift | 2 +- .../Legacy/LegacyTabTrayViewController.swift | 4 +- .../Browser/Tabs/State/TabTrayPanelType.swift | 2 +- .../Tabs/Views/TabTrayViewController.swift | 4 +- .../Client/Frontend/Browser/ToastType.swift | 4 +- .../Toolbars/Redux/ToolbarMiddleware.swift | 2 +- .../Client/Frontend/Browser/ZoomPageBar.swift | 8 +- .../Library/Bookmarks/BookmarksPanel.swift | 2 +- .../Library/HistoryPanel/HistoryPanel.swift | 2 +- .../Frontend/Library/LibraryPanelHelper.swift | 8 +- firefox-ios/Client/Frontend/Strings.swift | 275 +++++++++++++++++- .../Toolbar+URLBar/TabToolbarHelper.swift | 8 +- .../PhotonActionSheetProtocol.swift | 6 +- firefox-ios/Client/TabManagement/Tab.swift | 4 +- ...gacyTabPeekPreviewActionBuilderTests.swift | 2 +- .../Library/LibraryViewModelTests.swift | 8 +- .../Tests/ClientTests/TabTests.swift | 2 +- 23 files changed, 352 insertions(+), 85 deletions(-) diff --git a/firefox-ios/Client/Coordinators/ShareExtensionCoordinator.swift b/firefox-ios/Client/Coordinators/ShareExtensionCoordinator.swift index 208d2432d60e..9f75fbb439b1 100644 --- a/firefox-ios/Client/Coordinators/ShareExtensionCoordinator.swift +++ b/firefox-ios/Client/Coordinators/ShareExtensionCoordinator.swift @@ -78,7 +78,7 @@ class ShareExtensionCoordinator: BaseCoordinator, showSendToDevice(url: url) case CustomActivityAction.copyLink.actionType: SimpleToast().showAlertWithText( - .AppMenu.AppMenuCopyURLConfirmMessage, + .LegacyAppMenu.AppMenuCopyURLConfirmMessage, bottomContainer: alertContainer, theme: themeManager.getCurrentTheme(for: windowUUID)) dequeueNotShownJSAlert() @@ -163,7 +163,7 @@ class ShareExtensionCoordinator: BaseCoordinator, self.router.dismiss() self.parentCoordinator?.didFinish(from: self) DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { - SimpleToast().showAlertWithText(.AppMenu.AppMenuTabSentConfirmMessage, + SimpleToast().showAlertWithText(.LegacyAppMenu.AppMenuTabSentConfirmMessage, bottomContainer: self.alertContainer, theme: self.themeManager.getCurrentTheme(for: self.windowUUID)) } diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+TabToolbarDelegate.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+TabToolbarDelegate.swift index 17edbcc63167..464ef4ff8547 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+TabToolbarDelegate.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Extensions/BrowserViewController+TabToolbarDelegate.swift @@ -366,7 +366,7 @@ extension BrowserViewController: ToolBarActionMenuDelegate, UIDocumentPickerDele func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) { if !urls.isEmpty { - showToast(message: .AppMenu.AppMenuDownloadPDFConfirmMessage, toastAction: .downloadPDF) + showToast(message: .LegacyAppMenu.AppMenuDownloadPDFConfirmMessage, toastAction: .downloadPDF) } } diff --git a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift index ba4593e04104..97a48cf6d585 100644 --- a/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift +++ b/firefox-ios/Client/Frontend/Browser/BrowserViewController/Views/BrowserViewController.swift @@ -1570,9 +1570,14 @@ class BrowserViewController: UIViewController, private func showBookmarkToast(bookmarkURL: URL? = nil, title: String? = nil, action: BookmarkAction) { switch action { case .add: - self.showToast(message: .AppMenu.AddBookmarkConfirmMessage, toastAction: .bookmarkPage) + self.showToast(message: .LegacyAppMenu.AddBookmarkConfirmMessage, toastAction: .bookmarkPage) case .remove: - self.showToast(bookmarkURL, title, message: .AppMenu.RemoveBookmarkConfirmMessage, toastAction: .removeBookmark) + self.showToast( + bookmarkURL, + title, + message: .LegacyAppMenu.RemoveBookmarkConfirmMessage, + toastAction: .removeBookmark + ) } } @@ -3970,7 +3975,7 @@ extension BrowserViewController: DevicePickerViewControllerDelegate, Instruction profile.sendItem(shareItem, toDevices: devices).uponQueue(.main) { _ in self.popToBVC() DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { - SimpleToast().showAlertWithText(.AppMenu.AppMenuTabSentConfirmMessage, + SimpleToast().showAlertWithText(.LegacyAppMenu.AppMenuTabSentConfirmMessage, bottomContainer: self.contentContainer, theme: self.currentTheme()) } diff --git a/firefox-ios/Client/Frontend/Browser/MainMenuActionHelper.swift b/firefox-ios/Client/Frontend/Browser/MainMenuActionHelper.swift index 88f7eaa7b65a..6e61d004ccae 100644 --- a/firefox-ios/Client/Frontend/Browser/MainMenuActionHelper.swift +++ b/firefox-ios/Client/Frontend/Browser/MainMenuActionHelper.swift @@ -309,7 +309,7 @@ class MainMenuActionHelper: PhotonActionSheetProtocol, private func getNewTabAction() -> PhotonRowActions? { guard let tab = selectedTab else { return nil } - return SingleActionViewModel(title: tab.isPrivate ? .AppMenu.NewPrivateTab : .AppMenu.NewTab, + return SingleActionViewModel(title: tab.isPrivate ? .LegacyAppMenu.NewPrivateTab : .LegacyAppMenu.NewTab, iconString: StandardImageIdentifiers.Large.plus) { _ in let shouldFocusLocationField = NewTabAccessors.getNewTabPage(self.profile.prefs) != .homePage self.delegate?.openNewTabFromMenu(focusLocationField: shouldFocusLocationField, isPrivate: tab.isPrivate) @@ -318,7 +318,7 @@ class MainMenuActionHelper: PhotonActionSheetProtocol, } private func getHistoryLibraryAction() -> PhotonRowActions { - return SingleActionViewModel(title: .AppMenu.AppMenuHistory, + return SingleActionViewModel(title: .LegacyAppMenu.AppMenuHistory, iconString: StandardImageIdentifiers.Large.history) { _ in self.delegate?.showLibrary(panel: .history) TelemetryWrapper.recordEvent(category: .action, method: .tap, object: .viewHistoryPanel) @@ -326,7 +326,7 @@ class MainMenuActionHelper: PhotonActionSheetProtocol, } private func getDownloadsLibraryAction() -> PhotonRowActions { - return SingleActionViewModel(title: .AppMenu.AppMenuDownloads, + return SingleActionViewModel(title: .LegacyAppMenu.AppMenuDownloads, iconString: StandardImageIdentifiers.Large.download) { _ in self.delegate?.showLibrary(panel: .downloads) TelemetryWrapper.recordEvent(category: .action, method: .tap, object: .viewDownloadsPanel) @@ -338,7 +338,7 @@ class MainMenuActionHelper: PhotonActionSheetProtocol, private func getZoomAction() -> PhotonRowActions? { guard let tab = selectedTab else { return nil } let zoomLevel = NumberFormatter.localizedString(from: NSNumber(value: tab.pageZoom), number: .percent) - let title = String(format: .AppMenu.ZoomPageTitle, zoomLevel) + let title = String(format: .LegacyAppMenu.ZoomPageTitle, zoomLevel) let zoomAction = SingleActionViewModel(title: title, iconString: StandardImageIdentifiers.Large.pageZoom) { _ in self.delegate?.showZoomPage(tab: tab) @@ -347,7 +347,7 @@ class MainMenuActionHelper: PhotonActionSheetProtocol, } private func getFindInPageAction() -> PhotonRowActions { - return SingleActionViewModel(title: .AppMenu.AppMenuFindInPageTitleString, + return SingleActionViewModel(title: .LegacyAppMenu.AppMenuFindInPageTitleString, iconString: StandardImageIdentifiers.Large.search) { _ in TelemetryWrapper.recordEvent(category: .action, method: .tap, object: .findInPage) self.delegate?.showFindInPage() @@ -363,11 +363,11 @@ class MainMenuActionHelper: PhotonActionSheetProtocol, let siteTypeTelemetryObject: TelemetryWrapper.EventObject // swiftlint:disable line_length if defaultUAisDesktop { - toggleActionTitle = tab.changedUserAgent ? .AppMenu.AppMenuViewDesktopSiteTitleString : .AppMenu.AppMenuViewMobileSiteTitleString + toggleActionTitle = tab.changedUserAgent ? .LegacyAppMenu.AppMenuViewDesktopSiteTitleString : .LegacyAppMenu.AppMenuViewMobileSiteTitleString toggleActionIcon = tab.changedUserAgent ? StandardImageIdentifiers.Large.deviceDesktop : StandardImageIdentifiers.Large.deviceMobile siteTypeTelemetryObject = .requestDesktopSite } else { - toggleActionTitle = tab.changedUserAgent ? .AppMenu.AppMenuViewMobileSiteTitleString : .AppMenu.AppMenuViewDesktopSiteTitleString + toggleActionTitle = tab.changedUserAgent ? .LegacyAppMenu.AppMenuViewMobileSiteTitleString : .LegacyAppMenu.AppMenuViewDesktopSiteTitleString toggleActionIcon = tab.changedUserAgent ? StandardImageIdentifiers.Large.deviceMobile : StandardImageIdentifiers.Large.deviceDesktop siteTypeTelemetryObject = .requestMobileSite } @@ -388,19 +388,19 @@ class MainMenuActionHelper: PhotonActionSheetProtocol, } private func getCopyAction() -> PhotonRowActions? { - return SingleActionViewModel(title: .AppMenu.AppMenuCopyLinkTitleString, + return SingleActionViewModel(title: .LegacyAppMenu.AppMenuCopyLinkTitleString, iconString: StandardImageIdentifiers.Large.link) { _ in TelemetryWrapper.recordEvent(category: .action, method: .tap, object: .copyAddress) if let url = self.selectedTab?.canonicalURL?.displayURL { UIPasteboard.general.url = url - self.delegate?.showToast(message: .AppMenu.AppMenuCopyURLConfirmMessage, toastAction: .copyUrl) + self.delegate?.showToast(message: .LegacyAppMenu.AppMenuCopyURLConfirmMessage, toastAction: .copyUrl) } }.items } private func getSendToDevice() -> PhotonRowActions { let uuid = windowUUID - return SingleActionViewModel(title: .AppMenu.TouchActions.SendLinkToDeviceTitle, + return SingleActionViewModel(title: .LegacyAppMenu.TouchActions.SendLinkToDeviceTitle, iconString: StandardImageIdentifiers.Large.deviceDesktopSend) { _ in guard let delegate = self.sendToDeviceDelegate, let selectedTab = self.selectedTab, @@ -427,7 +427,7 @@ class MainMenuActionHelper: PhotonActionSheetProtocol, private func getReportSiteIssueAction() -> PhotonRowActions? { guard featureFlags.isFeatureEnabled(.reportSiteIssue, checking: .buildOnly) else { return nil } - return SingleActionViewModel(title: .AppMenu.AppMenuReportSiteIssueTitleString, + return SingleActionViewModel(title: .LegacyAppMenu.AppMenuReportSiteIssueTitleString, iconString: StandardImageIdentifiers.Large.lightbulb) { _ in guard let tabURL = self.selectedTab?.url?.absoluteString else { return } self.delegate?.openURLInNewTab(SupportUtils.URLForReportSiteIssue(tabURL), isPrivate: false) @@ -436,7 +436,7 @@ class MainMenuActionHelper: PhotonActionSheetProtocol, } private func getHelpAction() -> PhotonRowActions { - return SingleActionViewModel(title: .AppMenu.Help, + return SingleActionViewModel(title: .LegacyAppMenu.Help, iconString: StandardImageIdentifiers.Large.helpCircle) { _ in if let url = URL(string: "https://support.mozilla.org/products/ios") { self.delegate?.openURLInNewTab(url, isPrivate: self.tabManager.selectedTab?.isPrivate ?? false) @@ -446,7 +446,7 @@ class MainMenuActionHelper: PhotonActionSheetProtocol, } private func getCustomizeHomePageAction() -> PhotonRowActions? { - return SingleActionViewModel(title: .AppMenu.CustomizeHomePage, + return SingleActionViewModel(title: .LegacyAppMenu.CustomizeHomePage, iconString: StandardImageIdentifiers.Large.edit) { _ in self.delegate?.showCustomizeHomePage() TelemetryWrapper.recordEvent(category: .action, method: .tap, object: .customizeHomePage) @@ -454,7 +454,7 @@ class MainMenuActionHelper: PhotonActionSheetProtocol, } private func getSettingsAction() -> PhotonRowActions { - let openSettings = SingleActionViewModel(title: .AppMenu.AppMenuSettingsTitleString, + let openSettings = SingleActionViewModel(title: .LegacyAppMenu.AppMenuSettingsTitleString, iconString: StandardImageIdentifiers.Large.settings) { _ in TelemetryWrapper.recordEvent(category: .action, method: .open, object: .settings) @@ -470,7 +470,12 @@ class MainMenuActionHelper: PhotonActionSheetProtocol, var items: [PhotonRowActions] = [] let nightModeEnabled = NightModeHelper.isActivated() - let nightModeTitle: String = nightModeEnabled ? .AppMenu.AppMenuTurnOffNightMode : .AppMenu.AppMenuTurnOnNightMode + let nightModeTitle: String = if nightModeEnabled { + .LegacyAppMenu.AppMenuTurnOffNightMode + } else { + .LegacyAppMenu.AppMenuTurnOnNightMode + } + let nightMode = SingleActionViewModel( title: nightModeTitle, iconString: StandardImageIdentifiers.Large.nightMode, @@ -505,7 +510,7 @@ class MainMenuActionHelper: PhotonActionSheetProtocol, let needsReAuth = rustAccount.accountNeedsReauth() guard let userProfile = rustAccount.userProfile else { - return SingleActionViewModel(title: .AppMenu.SyncAndSaveData, + return SingleActionViewModel(title: .LegacyAppMenu.SyncAndSaveData, iconString: StandardImageIdentifiers.Large.sync, tapHandler: action).items } @@ -549,7 +554,7 @@ class MainMenuActionHelper: PhotonActionSheetProtocol, delegate?.updateToolbarState() } - whatsNewAction = SingleActionViewModel(title: .AppMenu.WhatsNewString, + whatsNewAction = SingleActionViewModel(title: .LegacyAppMenu.WhatsNewString, iconString: StandardImageIdentifiers.Large.whatsNew, isEnabled: showBadgeForWhatsNew) { _ in if let whatsNewURL = SupportUtils.URLForWhatsNew { @@ -567,7 +572,7 @@ class MainMenuActionHelper: PhotonActionSheetProtocol, // MARK: Share private func getShareFileAction() -> PhotonRowActions { - return SingleActionViewModel(title: .AppMenu.AppMenuSharePageTitleString, + return SingleActionViewModel(title: .LegacyAppMenu.AppMenuSharePageTitleString, iconString: StandardImageIdentifiers.Large.share) { _ in guard let tab = self.selectedTab, let url = tab.url @@ -578,7 +583,7 @@ class MainMenuActionHelper: PhotonActionSheetProtocol, } private func getShareAction() -> PhotonRowActions { - return SingleActionViewModel(title: .AppMenu.Share, + return SingleActionViewModel(title: .LegacyAppMenu.Share, iconString: StandardImageIdentifiers.Large.share) { _ in guard let tab = self.selectedTab, let url = tab.canonicalURL?.displayURL else { return } @@ -613,7 +618,7 @@ class MainMenuActionHelper: PhotonActionSheetProtocol, } private func getDownloadPDFAction() -> PhotonRowActions { - return SingleActionViewModel(title: .AppMenu.AppMenuDownloadPDF, + return SingleActionViewModel(title: .LegacyAppMenu.AppMenuDownloadPDF, iconString: StandardImageIdentifiers.Large.folder) { _ in guard let tab = self.selectedTab, let temporaryDocument = tab.temporaryDocument else { return } temporaryDocument.getURL { fileURL in @@ -652,7 +657,7 @@ class MainMenuActionHelper: PhotonActionSheetProtocol, } private func getReadingListLibraryAction() -> SingleActionViewModel { - return SingleActionViewModel(title: .AppMenu.ReadingList, + return SingleActionViewModel(title: .LegacyAppMenu.ReadingList, iconString: StandardImageIdentifiers.Large.readingList) { _ in self.delegate?.showLibrary(panel: .readingList) } @@ -663,7 +668,7 @@ class MainMenuActionHelper: PhotonActionSheetProtocol, } private func getAddReadingListAction() -> SingleActionViewModel { - return SingleActionViewModel(title: .AppMenu.AddReadingList, + return SingleActionViewModel(title: .LegacyAppMenu.AddReadingList, iconString: StandardImageIdentifiers.Large.readingListAdd) { _ in guard let tab = self.selectedTab, let url = self.tabUrl?.displayURL @@ -680,19 +685,19 @@ class MainMenuActionHelper: PhotonActionSheetProtocol, object: .readingListItem, value: .pageActionMenu ) - self.delegate?.showToast(message: .AppMenu.AddToReadingListConfirmMessage, toastAction: .addToReadingList) + self.delegate?.showToast(message: .LegacyAppMenu.AddToReadingListConfirmMessage, toastAction: .addToReadingList) } } private func getRemoveReadingListAction() -> SingleActionViewModel { - return SingleActionViewModel(title: .AppMenu.RemoveReadingList, + return SingleActionViewModel(title: .LegacyAppMenu.RemoveReadingList, iconString: StandardImageIdentifiers.Large.delete) { _ in guard let url = self.tabUrl?.displayURL?.absoluteString, let record = self.profile.readingList.getRecordWithURL(url).value.successValue else { return } self.profile.readingList.deleteRecord(record, completion: nil) - self.delegate?.showToast(message: .AppMenu.RemoveFromReadingListConfirmMessage, + self.delegate?.showToast(message: .LegacyAppMenu.RemoveFromReadingListConfirmMessage, toastAction: .removeFromReadingList) TelemetryWrapper.recordEvent(category: .action, method: .delete, @@ -716,7 +721,7 @@ class MainMenuActionHelper: PhotonActionSheetProtocol, } private func getBookmarkLibraryAction() -> SingleActionViewModel { - return SingleActionViewModel(title: .AppMenu.Bookmarks, + return SingleActionViewModel(title: .LegacyAppMenu.Bookmarks, iconString: StandardImageIdentifiers.Large.bookmarkTrayFill) { _ in self.delegate?.showLibrary(panel: .bookmarks) } @@ -727,7 +732,7 @@ class MainMenuActionHelper: PhotonActionSheetProtocol, } private func getAddBookmarkAction() -> SingleActionViewModel { - return SingleActionViewModel(title: .AppMenu.AddBookmark, + return SingleActionViewModel(title: .LegacyAppMenu.AddBookmark, iconString: StandardImageIdentifiers.Large.bookmark) { _ in guard let tab = self.selectedTab, let url = tab.canonicalURL?.displayURL @@ -745,14 +750,14 @@ class MainMenuActionHelper: PhotonActionSheetProtocol, } private func getRemoveBookmarkAction() -> SingleActionViewModel { - return SingleActionViewModel(title: .AppMenu.RemoveBookmark, + return SingleActionViewModel(title: .LegacyAppMenu.RemoveBookmark, iconString: StandardImageIdentifiers.Large.bookmarkSlash) { _ in guard let url = self.tabUrl?.displayURL else { return } self.profile.places.deleteBookmarksWithURL(url: url.absoluteString).uponQueue(.main) { result in guard result.isSuccess else { return } self.delegate?.showToast( - message: .AppMenu.RemoveBookmarkConfirmMessage, + message: .LegacyAppMenu.RemoveBookmarkConfirmMessage, toastAction: .removeBookmark ) self.removeBookmarkShortcut() @@ -781,7 +786,7 @@ class MainMenuActionHelper: PhotonActionSheetProtocol, let site = Site(url: url.absoluteString, title: title) self.profile.pinnedSites.addPinnedTopSite(site).uponQueue(.main) { result in guard result.isSuccess else { return } - self.delegate?.showToast(message: .AppMenu.AddPinToShortcutsConfirmMessage, toastAction: .pinPage) + self.delegate?.showToast(message: .LegacyAppMenu.AddPinToShortcutsConfirmMessage, toastAction: .pinPage) } TelemetryWrapper.recordEvent(category: .action, method: .tap, object: .pinToTopSites) @@ -789,7 +794,7 @@ class MainMenuActionHelper: PhotonActionSheetProtocol, } private func getRemoveShortcutAction() -> SingleActionViewModel { - return SingleActionViewModel(title: .AppMenu.RemoveFromShortcuts, + return SingleActionViewModel(title: .LegacyAppMenu.RemoveFromShortcuts, iconString: StandardImageIdentifiers.Large.pinSlash) { _ in guard let url = self.selectedTab?.url?.displayURL, let title = self.selectedTab?.displayTitle else { return } @@ -797,7 +802,7 @@ class MainMenuActionHelper: PhotonActionSheetProtocol, self.profile.pinnedSites.removeFromPinnedTopSites(site).uponQueue(.main) { result in if result.isSuccess { self.delegate?.showToast( - message: .AppMenu.RemovePinFromShortcutsConfirmMessage, + message: .LegacyAppMenu.RemovePinFromShortcutsConfirmMessage, toastAction: .removePinPage ) } @@ -811,7 +816,7 @@ class MainMenuActionHelper: PhotonActionSheetProtocol, private func getPasswordAction(navigationController: UINavigationController?) -> PhotonRowActions? { guard PasswordManagerListViewController.shouldShowAppMenuShortcut(forPrefs: profile.prefs) else { return nil } TelemetryWrapper.recordEvent(category: .action, method: .open, object: .logins) - return SingleActionViewModel(title: .AppMenu.AppMenuPasswords, + return SingleActionViewModel(title: .LegacyAppMenu.AppMenuPasswords, iconString: StandardImageIdentifiers.Large.login, iconType: .Image, iconAlignment: .left) { _ in diff --git a/firefox-ios/Client/Frontend/Browser/Tabs/Legacy/LegacyGridTabViewController.swift b/firefox-ios/Client/Frontend/Browser/Tabs/Legacy/LegacyGridTabViewController.swift index cd90cd05d691..7e468b921092 100644 --- a/firefox-ios/Client/Frontend/Browser/Tabs/Legacy/LegacyGridTabViewController.swift +++ b/firefox-ios/Client/Frontend/Browser/Tabs/Legacy/LegacyGridTabViewController.swift @@ -628,7 +628,7 @@ extension LegacyGridTabViewController: LegacyTabPeekDelegate { } func tabPeekDidCopyUrl() { - SimpleToast().showAlertWithText(.AppMenu.AppMenuCopyURLConfirmMessage, + SimpleToast().showAlertWithText(.LegacyAppMenu.AppMenuCopyURLConfirmMessage, bottomContainer: view, theme: currentTheme(), bottomConstraintPadding: -toolbarHeight) @@ -701,7 +701,7 @@ extension LegacyGridTabViewController { guard !tabDisplayManager.isDragging else { return } let controller = AlertController(title: nil, message: nil, preferredStyle: .actionSheet) - controller.addAction(UIAlertAction(title: .AppMenu.AppMenuCloseAllTabsTitleString, + controller.addAction(UIAlertAction(title: .LegacyAppMenu.AppMenuCloseAllTabsTitleString, style: .default, handler: { _ in self.closeTabsTrayBackground() }), accessibilityIdentifier: AccessibilityIdentifiers.TabTray.deleteCloseAllButton) diff --git a/firefox-ios/Client/Frontend/Browser/Tabs/Legacy/LegacyTabPeekPreviewActionBuilder.swift b/firefox-ios/Client/Frontend/Browser/Tabs/Legacy/LegacyTabPeekPreviewActionBuilder.swift index 18f4b4f54695..2cd2e8735e1d 100644 --- a/firefox-ios/Client/Frontend/Browser/Tabs/Legacy/LegacyTabPeekPreviewActionBuilder.swift +++ b/firefox-ios/Client/Frontend/Browser/Tabs/Legacy/LegacyTabPeekPreviewActionBuilder.swift @@ -19,7 +19,7 @@ class LegacyTabPeekPreviewActionBuilder { func addSendToDeviceTitle(handler: @escaping (UIPreviewAction, UIViewController) -> Void) { actions.append(UIPreviewAction( - title: .AppMenu.TouchActions.SendToDeviceTitle, + title: .LegacyAppMenu.TouchActions.SendToDeviceTitle, style: .default, handler: handler )) diff --git a/firefox-ios/Client/Frontend/Browser/Tabs/Legacy/LegacyTabPeekViewController.swift b/firefox-ios/Client/Frontend/Browser/Tabs/Legacy/LegacyTabPeekViewController.swift index 151723c3e616..2d2ce61fc886 100644 --- a/firefox-ios/Client/Frontend/Browser/Tabs/Legacy/LegacyTabPeekViewController.swift +++ b/firefox-ios/Client/Frontend/Browser/Tabs/Legacy/LegacyTabPeekViewController.swift @@ -87,7 +87,7 @@ class LegacyTabPeekViewController: UIViewController, WKNavigationDelegate { } if self.hasRemoteClients { actions.append(UIAction( - title: .AppMenu.TouchActions.SendToDeviceTitle, + title: .LegacyAppMenu.TouchActions.SendToDeviceTitle, image: UIImage.templateImageNamed(StandardImageIdentifiers.Large.share), identifier: nil ) { [weak self] _ in diff --git a/firefox-ios/Client/Frontend/Browser/Tabs/Legacy/LegacyTabTrayViewController.swift b/firefox-ios/Client/Frontend/Browser/Tabs/Legacy/LegacyTabTrayViewController.swift index f94d61352d5c..a158c8b39b2d 100644 --- a/firefox-ios/Client/Frontend/Browser/Tabs/Legacy/LegacyTabTrayViewController.swift +++ b/firefox-ios/Client/Frontend/Browser/Tabs/Legacy/LegacyTabTrayViewController.swift @@ -53,7 +53,7 @@ class LegacyTabTrayViewController: UIViewController, Themeable, TabTrayControlle return createButtonItem(imageName: StandardImageIdentifiers.Large.delete, action: #selector(didTapDeleteTabs(_:)), a11yId: AccessibilityIdentifiers.TabTray.closeAllTabsButton, - a11yLabel: .AppMenu.Toolbar.TabTrayDeleteMenuButtonAccessibilityLabel) + a11yLabel: .LegacyAppMenu.Toolbar.TabTrayDeleteMenuButtonAccessibilityLabel) }() private lazy var newTabButtonIpad: UIBarButtonItem = { @@ -67,7 +67,7 @@ class LegacyTabTrayViewController: UIViewController, Themeable, TabTrayControlle return createButtonItem(imageName: StandardImageIdentifiers.Large.delete, action: #selector(didTapDeleteTabs(_:)), a11yId: AccessibilityIdentifiers.TabTray.closeAllTabsButton, - a11yLabel: .AppMenu.Toolbar.TabTrayDeleteMenuButtonAccessibilityLabel) + a11yLabel: .LegacyAppMenu.Toolbar.TabTrayDeleteMenuButtonAccessibilityLabel) }() private lazy var newTabButtonIphone: UIBarButtonItem = { diff --git a/firefox-ios/Client/Frontend/Browser/Tabs/State/TabTrayPanelType.swift b/firefox-ios/Client/Frontend/Browser/Tabs/State/TabTrayPanelType.swift index baa0dd1c92eb..cf9063d20d64 100644 --- a/firefox-ios/Client/Frontend/Browser/Tabs/State/TabTrayPanelType.swift +++ b/firefox-ios/Client/Frontend/Browser/Tabs/State/TabTrayPanelType.swift @@ -17,7 +17,7 @@ enum TabTrayPanelType: Int, CaseIterable { case .privateTabs: return .TabTrayPrivateBrowsingTitle case .syncedTabs: - return .AppMenu.AppMenuSyncedTabsTitleString + return .LegacyAppMenu.AppMenuSyncedTabsTitleString } } diff --git a/firefox-ios/Client/Frontend/Browser/Tabs/Views/TabTrayViewController.swift b/firefox-ios/Client/Frontend/Browser/Tabs/Views/TabTrayViewController.swift index 9c55d8d04511..9720eb712e6a 100644 --- a/firefox-ios/Client/Frontend/Browser/Tabs/Views/TabTrayViewController.swift +++ b/firefox-ios/Client/Frontend/Browser/Tabs/Views/TabTrayViewController.swift @@ -108,7 +108,7 @@ class TabTrayViewController: UIViewController, return createButtonItem(imageName: StandardImageIdentifiers.Large.delete, action: #selector(deleteTabsButtonTapped), a11yId: AccessibilityIdentifiers.TabTray.closeAllTabsButton, - a11yLabel: .AppMenu.Toolbar.TabTrayDeleteMenuButtonAccessibilityLabel) + a11yLabel: .LegacyAppMenu.Toolbar.TabTrayDeleteMenuButtonAccessibilityLabel) }() private lazy var newTabButton: UIBarButtonItem = { @@ -481,7 +481,7 @@ class TabTrayViewController: UIViewController, private func showCloseAllConfirmation() { let controller = AlertController(title: nil, message: nil, preferredStyle: .actionSheet) - controller.addAction(UIAlertAction(title: .AppMenu.AppMenuCloseAllTabsTitleString, + controller.addAction(UIAlertAction(title: .LegacyAppMenu.AppMenuCloseAllTabsTitleString, style: .default, handler: { _ in self.confirmCloseAll() }), accessibilityIdentifier: AccessibilityIdentifiers.TabTray.deleteCloseAllButton) diff --git a/firefox-ios/Client/Frontend/Browser/ToastType.swift b/firefox-ios/Client/Frontend/Browser/ToastType.swift index 5dec291b0531..a00861939aff 100644 --- a/firefox-ios/Client/Frontend/Browser/ToastType.swift +++ b/firefox-ios/Client/Frontend/Browser/ToastType.swift @@ -23,9 +23,9 @@ enum ToastType: Equatable { .TabsTray.CloseTabsToast.Title, tabsCount) case .copyURL: - return .AppMenu.AppMenuCopyURLConfirmMessage + return .LegacyAppMenu.AppMenuCopyURLConfirmMessage case .addBookmark: - return .AppMenu.AddBookmarkConfirmMessage + return .LegacyAppMenu.AddBookmarkConfirmMessage } } diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift index b14ec5ca6833..1209bea91eef 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift @@ -745,7 +745,7 @@ final class ToolbarMiddleware: FeatureFlaggable { badgeImageName: badgeImageName, maskImageName: maskImageName, isEnabled: true, - a11yLabel: .AppMenu.Toolbar.MenuButtonAccessibilityLabel, + a11yLabel: .LegacyAppMenu.Toolbar.MenuButtonAccessibilityLabel, a11yId: AccessibilityIdentifiers.Toolbar.settingsMenuButton) } diff --git a/firefox-ios/Client/Frontend/Browser/ZoomPageBar.swift b/firefox-ios/Client/Frontend/Browser/ZoomPageBar.swift index 416535b8483f..bdd4fe9ddee5 100644 --- a/firefox-ios/Client/Frontend/Browser/ZoomPageBar.swift +++ b/firefox-ios/Client/Frontend/Browser/ZoomPageBar.swift @@ -65,7 +65,7 @@ final class ZoomPageBar: UIView, ThemeApplicable, AlphaDimmable { private lazy var zoomOutButton: UIButton = .build { button in self.configureButton(button, image: UIImage.templateImageNamed(StandardImageIdentifiers.Large.subtract), - accessibilityLabel: .AppMenu.ZoomPageDecreaseZoomAccessibilityLabel, + accessibilityLabel: .LegacyAppMenu.ZoomPageDecreaseZoomAccessibilityLabel, accessibilityIdentifier: AccessibilityIdentifiers.ZoomPageBar.zoomPageZoomOutButton) button.setContentHuggingPriority(.required, for: .horizontal) button.configuration = .plain() @@ -83,7 +83,7 @@ final class ZoomPageBar: UIView, ThemeApplicable, AlphaDimmable { private lazy var zoomInButton: UIButton = .build { button in self.configureButton(button, image: UIImage.templateImageNamed(StandardImageIdentifiers.Large.plus), - accessibilityLabel: .AppMenu.ZoomPageIncreaseZoomAccessibilityLabel, + accessibilityLabel: .LegacyAppMenu.ZoomPageIncreaseZoomAccessibilityLabel, accessibilityIdentifier: AccessibilityIdentifiers.ZoomPageBar.zoomPageZoomInButton) button.setContentHuggingPriority(.required, for: .horizontal) button.configuration = .plain() @@ -93,7 +93,7 @@ final class ZoomPageBar: UIView, ThemeApplicable, AlphaDimmable { private lazy var closeButton: UIButton = .build { button in self.configureButton(button, image: UIImage.templateImageNamed(StandardImageIdentifiers.Large.cross), - accessibilityLabel: .AppMenu.ZoomPageCloseAccessibilityLabel, + accessibilityLabel: .LegacyAppMenu.ZoomPageCloseAccessibilityLabel, accessibilityIdentifier: AccessibilityIdentifiers.FindInPage.findInPageCloseButton) } @@ -219,7 +219,7 @@ final class ZoomPageBar: UIView, ThemeApplicable, AlphaDimmable { zoomLevel.text = NumberFormatter.localizedString(from: NSNumber(value: tab.pageZoom), number: .percent) zoomLevel.isEnabled = tab.pageZoom == 1.0 ? false : true gestureRecognizer.isEnabled = !(tab.pageZoom == 1.0) - zoomLevel.accessibilityLabel = String(format: .AppMenu.ZoomPageCurrentZoomLevelAccessibilityLabel, + zoomLevel.accessibilityLabel = String(format: .LegacyAppMenu.ZoomPageCurrentZoomLevelAccessibilityLabel, zoomLevel.text ?? "") } diff --git a/firefox-ios/Client/Frontend/Library/Bookmarks/BookmarksPanel.swift b/firefox-ios/Client/Frontend/Library/Bookmarks/BookmarksPanel.swift index ef7ed70c60ea..19dc9807ebd8 100644 --- a/firefox-ios/Client/Frontend/Library/Bookmarks/BookmarksPanel.swift +++ b/firefox-ios/Client/Frontend/Library/Bookmarks/BookmarksPanel.swift @@ -526,7 +526,7 @@ extension BookmarksPanel: LibraryPanelContextMenu { tapHandler: { _ in self.profile.pinnedSites.addPinnedTopSite(site).uponQueue(.main) { result in if result.isSuccess { - SimpleToast().showAlertWithText(.AppMenu.AddPinToShortcutsConfirmMessage, + SimpleToast().showAlertWithText(.LegacyAppMenu.AddPinToShortcutsConfirmMessage, bottomContainer: self.view, theme: self.currentTheme()) } else { diff --git a/firefox-ios/Client/Frontend/Library/HistoryPanel/HistoryPanel.swift b/firefox-ios/Client/Frontend/Library/HistoryPanel/HistoryPanel.swift index 225fc360c533..3e7513f33f7d 100644 --- a/firefox-ios/Client/Frontend/Library/HistoryPanel/HistoryPanel.swift +++ b/firefox-ios/Client/Frontend/Library/HistoryPanel/HistoryPanel.swift @@ -884,7 +884,7 @@ extension HistoryPanel { func pinToTopSites(_ site: Site) { profile.pinnedSites.addPinnedTopSite(site).uponQueue(.main) { result in if result.isSuccess { - SimpleToast().showAlertWithText(.AppMenu.AddPinToShortcutsConfirmMessage, + SimpleToast().showAlertWithText(.LegacyAppMenu.AddPinToShortcutsConfirmMessage, bottomContainer: self.view, theme: self.currentTheme()) } diff --git a/firefox-ios/Client/Frontend/Library/LibraryPanelHelper.swift b/firefox-ios/Client/Frontend/Library/LibraryPanelHelper.swift index 2f268926ab5a..f1c4f120b15a 100644 --- a/firefox-ios/Client/Frontend/Library/LibraryPanelHelper.swift +++ b/firefox-ios/Client/Frontend/Library/LibraryPanelHelper.swift @@ -56,13 +56,13 @@ enum LibraryPanelType: Int, CaseIterable { var title: String { switch self { case .bookmarks: - return .AppMenu.AppMenuBookmarksTitleString + return .LegacyAppMenu.AppMenuBookmarksTitleString case .history: - return .AppMenu.AppMenuHistoryTitleString + return .LegacyAppMenu.AppMenuHistoryTitleString case .downloads: - return .AppMenu.AppMenuDownloadsTitleString + return .LegacyAppMenu.AppMenuDownloadsTitleString case .readingList: - return .AppMenu.AppMenuReadingListTitleString + return .LegacyAppMenu.AppMenuReadingListTitleString } } diff --git a/firefox-ios/Client/Frontend/Strings.swift b/firefox-ios/Client/Frontend/Strings.swift index 2378560cace0..7025020f71f6 100644 --- a/firefox-ios/Client/Frontend/Strings.swift +++ b/firefox-ios/Client/Frontend/Strings.swift @@ -3847,10 +3847,266 @@ extension String { } } -// MARK: - App menu +// MARK: - Main Menu extension String { - /// Identifiers of all new strings should begin with `Menu.` - public struct AppMenu { + public struct MainMenu { + public struct Account { + public static let SignedOutTitle = MZLocalizedString( + key: "MainMenu.Account.SignedOut.Title.v131", + tableName: "MainMenu", + value: "Sign In", + comment: "On the main menu, at the top, when the user is signed out. The title for the sign in action") + public static let SignedOutDescription = MZLocalizedString( + key: "MainMenu.Account.SignedOut.Description.v131", + tableName: "MainMenu", + value: "Sync passwords, tabs, and more", + comment: "On the main menu, at the top, when the user is signed out. The description for the sign in action") + public static let SyncErrorTitle = MZLocalizedString( + key: "MainMenu.Account.SyncError.Title.v131", + tableName: "MainMenu", + value: "Sign back in to sync", + comment: "On the main menu, at the top, when the user is signed in but there was an error syncing. The title for this state.") + public static let SyncErrorDescription = MZLocalizedString( + key: "MainMenu.Account.SyncError.Description.v131", + tableName: "MainMenu", + value: "Syncing paused", + comment: "On the main menu, at the top, when the user is signed in but there was an error syncing. The description subtitle for the sync error state.") + } + + public struct TabsSection { + public static let NewTab = MZLocalizedString( + key: "MainMenu.TabsSection.NewTab.Title.v131", + tableName: "MainMenu", + value: "New Tab", + comment: "On the main menu, the title for the action that will create a new, non-private, tab.") + public static let NewPrivateTab = MZLocalizedString( + key: "MainMenu.TabsSection.NewPrivateTab.Title.v131", + tableName: "MainMenu", + value: "New Private Tab", + comment: "On the main menu, the title for the action that will create a new private tab.") + } + + public struct ToolsSection { + public static let SwitchToDesktopSite = MZLocalizedString( + key: "MainMenu.ToolsSection.SwitchToDesktopSite.Title.v131", + tableName: "MainMenu", + value: "Switch to Desktop Site", + comment: "On the main menu, the title for the action that will switch a site from mobile version to the desktop version, if available.") + public static let SwitchToMobileSite = MZLocalizedString( + key: "MainMenu.ToolsSection.SwitchToMobileSite.Title.v131", + tableName: "MainMenu", + value: "Switch to Mobile Site", + comment: "On the main menu, the title for the action that will switch a site from the desktop version to the mobile version.") + public static let FindInPage = MZLocalizedString( + key: "MainMenu.ToolsSection.FindInPage.Title.v131", + tableName: "MainMenu", + value: "Find in Page...", + comment: "On the main menu, the title for the action that will bring up the Search menu, so the user can search for a word or a pharse on the current page.") + public static let Tools = MZLocalizedString( + key: "MainMenu.ToolsSection.ToolsSubmenu.Title.v131", + tableName: "MainMenu", + value: "Tools", + comment: "On the main menu, the title for the action that will take the user to the Tools submenu in the menu.") + public static let Save = MZLocalizedString( + key: "MainMenu.ToolsSection.SaveSubmenu.Title.v131", + tableName: "MainMenu", + value: "Save", + comment: "On the main menu, the title for the action that will take the user to the Save submenu in the menu.") + } + + public struct PanelLinkSection { + public static let Bookmarks = MZLocalizedString( + key: "MainMenu.PanelLinkSection.Bookmarks.Title.v131", + tableName: "MainMenu", + value: "Bookmarks", + comment: "On the main menu, the title for the action that will take the user to the Bookmarks panel. Please keep as short as possible, <15 chars of space available.") + public static let History = MZLocalizedString( + key: "MainMenu.PanelLinkSection.History.Title.v131", + tableName: "MainMenu", + value: "History", + comment: "On the main menu, the title for the action that will take the user to the History panel. Please keep as short as possible, <15 chars of space available.") + public static let Downloads = MZLocalizedString( + key: "MainMenu.PanelLinkSection.Downloads.Title.v131", + tableName: "MainMenu", + value: "Downloads", + comment: "On the main menu, the title for the action that will take the user to the Downloads panel. Please keep as short as possible, <15 chars of space available.") + public static let Passwords = MZLocalizedString( + key: "MainMenu.PanelLinkSection.Passwords.Title.v131", + tableName: "MainMenu", + value: "Passwords", + comment: "On the main menu, the title for the action that will take the user to the Passwords panel in the settings screen. Please keep as short as possible, <15 chars of space available.") + } + + public struct SettingsSection { + public static let CustomizeHomepage = MZLocalizedString( + key: "MainMenu.SettingsSection.CustomizeHomepage.Title.v131", + tableName: "MainMenu", + value: "Customize Homepage", + comment: "On the main menu, the title for the action that will take the user to the Customize Hopegape section in the settings screen.") + public static let WhatsNew = MZLocalizedString( + key: "MainMenu.SettingsSection.WhatsNew.Title.v131", + tableName: "MainMenu", + value: "New in %@", + comment: "On the main menu, the title for the action that will take the user to a What's New in Firefox popup. Placeholder is for the app name.") + public static let Settings = MZLocalizedString( + key: "MainMenu.SettingsSection.Settings.Title.v131", + tableName: "MainMenu", + value: "Settings", + comment: "On the main menu, the title for the action that will take the user to the Settings menu.") + public static let GetHelp = MZLocalizedString( + key: "MainMenu.SettingsSection.GetHelp.Title.v131", + tableName: "MainMenu", + value: "Get Help", + comment: "On the main menu, the title for the action that will take the user to a website to get help from Mozilla.") + } + + public struct Submenus { + public struct Tools { + public static let Zoom = MZLocalizedString( + key: "MainMenu.Submenus.Tools.Zoom.Title.v131", + tableName: "MainMenu", + value: "Zoom (%@)", + comment: "On the main menu, in the tools submenu, the title for the menu component that indicates the current zoom level. Placeholder is for the current zoom level percentage. ") + public static let ZoomSubtitle = MZLocalizedString( + key: "MainMenu.Submenus.Tools.Zoom.Subtitle.v131", + tableName: "MainMenu", + value: "Zoom", + comment: "On the main menu, a string below the Tool submenu title, indicating what kind of tools are available in that menu. This string is for the Zoom tool.") + public static let ReaderViewOn = MZLocalizedString( + key: "MainMenu.Submenus.Tools.ReaderView.On.Title.v131", + tableName: "MainMenu", + value: "Turn on Reader View", + comment: "On the main menu, the title for the action that will turn the reader view on for the current website.") + public static let ReaderViewOff = MZLocalizedString( + key: "MainMenu.Submenus.Tools.ReaderView.Off.Title.v131", + tableName: "MainMenu", + value: "Turn off Reader View", + comment: "On the main menu, the title for the action that will turn the reader view on for the current website.") + public static let ReaderViewSubtitle = MZLocalizedString( + key: "MainMenu.Submenus.Tools.ReaderView.Subtitle.v131", + tableName: "MainMenu", + value: "Reader View", + comment: "On the main menu, a string below the Tool submenu tiitle, indicating what kind of tools are available in that menu. This string is for the Reader View tool.") + public static let NightModeOn = MZLocalizedString( + key: "MainMenu.Submenus.Tools.NightMode.On.Title.v131", + tableName: "MainMenu", + value: "Turn on Night Mode", + comment: "On the main menu, the title for the action that will turn Night Mode on in the application.") + public static let NightModeOff = MZLocalizedString( + key: "MainMenu.Submenus.Tools.NightMode.Off.Title.v131", + tableName: "MainMenu", + value: "Turn off Night Mode", + comment: "On the main menu, the title for the action that will turn Night Mode off in the application.") + public static let NightModeSubtitle = MZLocalizedString( + key: "MainMenu.Submenus.Tools.NightMode.Subtitle.v131", + tableName: "MainMenu", + value: "Night Mode", + comment: "On the main menu, a string below the Tool submenu tiitle, indicating what kind of tools are available in that menu. This string is for the Night Mode tool.") + public static let Print = MZLocalizedString( + key: "MainMenu.Submenus.Tools.Print.Title.v131", + tableName: "MainMenu", + value: "Print", + comment: "On the main menu, the title for the action that will take the user to the Print module in the application.") + public static let PrintSubtitle = MZLocalizedString( + key: "MainMenu.Submenus.Tools.Print.Subtitle.v131", + tableName: "MainMenu", + value: "Print", + comment: "On the main menu, a string below the Tool submenu tiitle, indicating what kind of tools are available in that menu. This string is for the Report Print tool.") + public static let Share = MZLocalizedString( + key: "MainMenu.Submenus.Tools.Share.Title.v131", + tableName: "MainMenu", + value: "Share", + comment: "On the main menu, the title for the action that will take the user to the Share module in the application.") + public static let ShareSubtitle = MZLocalizedString( + key: "MainMenu.Submenus.Tools.Share.Subtitle.v131", + tableName: "MainMenu", + value: "Share", + comment: "On the main menu, a string below the Tool submenu tiitle, indicating what kind of tools are available in that menu. This string is for the Report Share tool.") + public static let ReportBrokenSite = MZLocalizedString( + key: "MainMenu.Submenus.Tools.ReportBrokenSite.Title.v131", + tableName: "MainMenu", + value: "Report Broken Site", + comment: "On the main menu, the title for the action that will take the user to the site where they can report a broken website to our web compatibility team.") + public static let ReportBrokenSiteSubtitle = MZLocalizedString( + key: "MainMenu.Submenus.Tools.ReportBrokenSite.Subtitle.v131", + tableName: "MainMenu", + value: "Report", + comment: "On the main menu, a string below the Tool submenu tiitle, indicating what kind of tools are available in that menu. This string is for the Report Broken Site tool.") + } + + public struct Save { + public static let BookmarkThisPage = MZLocalizedString( + key: "MainMenu.Submenus.Save.BookmarkThisPage.Title.v131", + tableName: "MainMenu", + value: "Bookmark This Page", + comment: "On the main menu, in the tools submenu, the title for the menu component that indicates the current zoom level. Placeholder is for the current zoom level percentage. ") + public static let BookmarkThisPageSubtitle = MZLocalizedString( + key: "MainMenu.Submenus.Save.BookmarkThisPage.Subtitle.v131", + tableName: "MainMenu", + value: "Add Bookmark", + comment: "On the main menu, a string below the Save submenu title, indicating what kind of tools are available in that menu. This string is for the Bookmarks tool.") + public static let EditBookmark = MZLocalizedString( + key: "MainMenu.Submenus.Save.EditBookmark.Title.v131", + tableName: "MainMenu", + value: "Edit Bookmark", + comment: "On the main menu, in the Save submenu, the title for the menu component that allows a user to edit the bookmark for this particular page.") + public static let AddToShortcuts = MZLocalizedString( + key: "MainMenu.Submenus.Save.AddToShortcuts.Title.v131", + tableName: "MainMenu", + value: "Add to Shortcuts", + comment: "On the main menu, in the Save submenu, the title for the menu component that allows a user to add the current website to the shortcuts on the homepage.") + public static let RemoveFromShortcuts = MZLocalizedString( + key: "MainMenu.Submenus.Save.RemoveFromShortcuts.Title.v131", + tableName: "MainMenu", + value: "Remove from Shortcuts", + comment: "On the main menu, in the Save submenu, the title for the menu component that allows a user to remove the current website from the shortcuts on the homepage.") + public static let AddToShortcutsSubtitle = MZLocalizedString( + key: "MainMenu.Submenus.Save.AddToShortcuts.Subtitle.v131", + tableName: "MainMenu", + value: "Shortcut", + comment: "On the main menu, a string below the Save submenu title, indicating what kind of tools are available in that menu. This string is for the Shortcuts tool.") + public static let AddToHomeScreen = MZLocalizedString( + key: "MainMenu.Submenus.Save.AddToHomeScreen.Title.v131", + tableName: "MainMenu", + value: "Add to Home Screen", + comment: "On the main menu, in the Save submenu, the title for the menu component that allows a user to add a website to the home screen.") + public static let AddToHomeScreenSubtitle = MZLocalizedString( + key: "MainMenu.Submenus.Save.AddToHomeScreen.Subtitle.v131", + tableName: "MainMenu", + value: "Home", + comment: "On the main menu, a string below the Save submenu title, indicating what kind of tools are available in that menu. This string is for the Add to Homescreen tool.") + public static let SaveToReadingList = MZLocalizedString( + key: "MainMenu.Submenus.Save.SaveToReadingList.Title.v131", + tableName: "MainMenu", + value: "Save to Reading List", + comment: "On the main menu, in the Save submenu, the title for the menu component that allows the user to add this site to the reading list.") + public static let RemoveFromReadingList = MZLocalizedString( + key: "MainMenu.Submenus.Save.RemoveFromReadingList.Title.v131", + tableName: "MainMenu", + value: "Remove from Reading List", + comment: "On the main menu, in the Save submenu, the title for the menu component that allows the user to remove this site from the reading list.") + public static let SaveToReadingListSubtitle = MZLocalizedString( + key: "MainMenu.Submenus.Save.SaveToReadingList.Subtitle.v131", + tableName: "MainMenu", + value: "Reading List", + comment: "On the main menu, a string below the Save submenu title, indicating what kind of tools are available in that menu. This string is for the Reading List tool.") + public static let SaveAsPDF = MZLocalizedString( + key: "MainMenu.Submenus.Save.SaveAsPDF.Title.v131", + tableName: "MainMenu", + value: "Save as PDF", + comment: "On the main menu, in the Save submenu, the title for the menu component that allows the user to use the Save to PDF tool.") + public static let SaveAsPDFSubtitle = MZLocalizedString( + key: "MainMenu.Submenus.Save.SaveAsPDF.Subtitle.v131", + tableName: "MainMenu", + value: "PDF", + comment: "On the main menu, a string below the Save submenu title, indicating what kind of tools are available in that menu. This string is for the Save as PDF tool.") + } + } + } + + // MARK: - LegacyAppMenu + // These strings may still be in use, thus have not been moved to the `OldStrings` struct + public struct LegacyAppMenu { public static let AppMenuReportSiteIssueTitleString = MZLocalizedString( key: "Menu.ReportSiteIssueAction.Title", tableName: "Menu", @@ -3881,16 +4137,17 @@ extension String { tableName: "Menu", value: "Request Mobile Site", comment: "Label for the button, displayed in the menu, used to request the mobile version of the current website.") - public static let AppMenuSettingsTitleString = MZLocalizedString( - key: "Menu.OpenSettingsAction.Title", - tableName: "Menu", - value: "Settings", - comment: "Label for the button, displayed in the menu, used to open the Settings menu.") public static let AppMenuCloseAllTabsTitleString = MZLocalizedString( key: "Menu.CloseAllTabsAction.Title", tableName: "Menu", value: "Close All Tabs", comment: "Label for the button, displayed in the menu, used to close all tabs currently open.") + + public static let AppMenuSettingsTitleString = MZLocalizedString( + key: "Menu.OpenSettingsAction.Title", + tableName: "Menu", + value: "Settings", + comment: "Label for the button, displayed in the menu, used to open the Settings menu.") public static let AppMenuOpenHomePageTitleString = MZLocalizedString( key: "SettingsMenu.OpenHomePageAction.Title", tableName: "Menu", @@ -4665,7 +4922,7 @@ extension String { tableName: nil, value: "Available devices:", comment: "Header for the list of devices table") - public static let ShareSendToDevice = String.AppMenu.TouchActions.SendToDeviceTitle + public static let ShareSendToDevice = String.LegacyAppMenu.TouchActions.SendToDeviceTitle // The above items are re-used strings from the old extension. New strings below. diff --git a/firefox-ios/Client/Frontend/Toolbar+URLBar/TabToolbarHelper.swift b/firefox-ios/Client/Frontend/Toolbar+URLBar/TabToolbarHelper.swift index 8d74110451bc..9924796fd05d 100644 --- a/firefox-ios/Client/Frontend/Toolbar+URLBar/TabToolbarHelper.swift +++ b/firefox-ios/Client/Frontend/Toolbar+URLBar/TabToolbarHelper.swift @@ -153,19 +153,19 @@ open class TabToolbarHelper: NSObject { let appMenuImage = UIImage.templateImageNamed(StandardImageIdentifiers.Large.appMenu) toolbar.appMenuButton.contentMode = .center toolbar.appMenuButton.showsLargeContentViewer = true - toolbar.appMenuButton.largeContentTitle = .AppMenu.Toolbar.MenuButtonAccessibilityLabel + toolbar.appMenuButton.largeContentTitle = .LegacyAppMenu.Toolbar.MenuButtonAccessibilityLabel toolbar.appMenuButton.largeContentImage = appMenuImage toolbar.appMenuButton.setImage(appMenuImage, for: .normal) - toolbar.appMenuButton.accessibilityLabel = .AppMenu.Toolbar.MenuButtonAccessibilityLabel + toolbar.appMenuButton.accessibilityLabel = .LegacyAppMenu.Toolbar.MenuButtonAccessibilityLabel toolbar.appMenuButton.addTarget(self, action: #selector(didClickMenu), for: .touchUpInside) toolbar.appMenuButton.accessibilityIdentifier = AccessibilityIdentifiers.Toolbar.settingsMenuButton toolbar.bookmarksButton.contentMode = .center toolbar.bookmarksButton.showsLargeContentViewer = true toolbar.bookmarksButton.largeContentImage = ImageBookmark - toolbar.bookmarksButton.largeContentTitle = .AppMenu.Toolbar.BookmarksButtonAccessibilityLabel + toolbar.bookmarksButton.largeContentTitle = .LegacyAppMenu.Toolbar.BookmarksButtonAccessibilityLabel toolbar.bookmarksButton.setImage(ImageBookmark, for: .normal) - toolbar.bookmarksButton.accessibilityLabel = .AppMenu.Toolbar.BookmarksButtonAccessibilityLabel + toolbar.bookmarksButton.accessibilityLabel = .LegacyAppMenu.Toolbar.BookmarksButtonAccessibilityLabel toolbar.bookmarksButton.addTarget(self, action: #selector(didClickLibrary), for: .touchUpInside) toolbar.bookmarksButton.accessibilityIdentifier = AccessibilityIdentifiers.Toolbar.bookmarksButton diff --git a/firefox-ios/Client/Frontend/Widgets/PhotonActionSheet/PhotonActionSheetProtocol.swift b/firefox-ios/Client/Frontend/Widgets/PhotonActionSheet/PhotonActionSheetProtocol.swift index 0a0dbace0814..77321068211f 100644 --- a/firefox-ios/Client/Frontend/Widgets/PhotonActionSheet/PhotonActionSheetProtocol.swift +++ b/firefox-ios/Client/Frontend/Widgets/PhotonActionSheet/PhotonActionSheetProtocol.swift @@ -76,7 +76,7 @@ extension PhotonActionSheetProtocol { let currentURL = tabManager.selectedTab?.currentURL() if let url = tabManager.selectedTab?.canonicalURL?.displayURL ?? currentURL { UIPasteboard.general.url = url - SimpleToast().showAlertWithText(.AppMenu.AppMenuCopyURLConfirmMessage, + SimpleToast().showAlertWithText(.LegacyAppMenu.AppMenuCopyURLConfirmMessage, bottomContainer: alertContainer, theme: themeManager.getCurrentTheme(for: tabManager.windowUUID)) } @@ -98,9 +98,9 @@ extension PhotonActionSheetProtocol { let toggleActionTitle: String // swiftlint:disable line_length if defaultUAisDesktop { - toggleActionTitle = tab.changedUserAgent ? .AppMenu.AppMenuViewDesktopSiteTitleString : .AppMenu.AppMenuViewMobileSiteTitleString + toggleActionTitle = tab.changedUserAgent ? .LegacyAppMenu.AppMenuViewDesktopSiteTitleString : .LegacyAppMenu.AppMenuViewMobileSiteTitleString } else { - toggleActionTitle = tab.changedUserAgent ? .AppMenu.AppMenuViewMobileSiteTitleString : .AppMenu.AppMenuViewDesktopSiteTitleString + toggleActionTitle = tab.changedUserAgent ? .LegacyAppMenu.AppMenuViewMobileSiteTitleString : .LegacyAppMenu.AppMenuViewDesktopSiteTitleString } // swiftlint:enable line_length let toggleDesktopSite = SingleActionViewModel(title: toggleActionTitle, diff --git a/firefox-ios/Client/TabManagement/Tab.swift b/firefox-ios/Client/TabManagement/Tab.swift index 445cbe75e2aa..b88eb258b107 100644 --- a/firefox-ios/Client/TabManagement/Tab.swift +++ b/firefox-ios/Client/TabManagement/Tab.swift @@ -195,7 +195,7 @@ class Tab: NSObject, ThemeApplicable { /// or not, it will resort to other displayable titles. var displayTitle: String { if self.isFxHomeTab { - return .AppMenu.AppMenuOpenHomePageTitleString + return .LegacyAppMenu.AppMenuOpenHomePageTitleString } if let lastTitle = lastTitle, !lastTitle.isEmpty { @@ -227,7 +227,7 @@ class Tab: NSObject, ThemeApplicable { var backUpName: String = "" // In case display title is empty if let baseDomain = baseDomain { - backUpName = baseDomain.contains("local") ? .AppMenu.AppMenuOpenHomePageTitleString : baseDomain + backUpName = baseDomain.contains("local") ? .LegacyAppMenu.AppMenuOpenHomePageTitleString : baseDomain } else if let url = url, let about = InternalURL(url)?.aboutComponent { backUpName = about } diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Browser/Tabs/Legacy/LegacyTabPeekPreviewActionBuilderTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Browser/Tabs/Legacy/LegacyTabPeekPreviewActionBuilderTests.swift index 9eb6498277ca..226c91e28c0a 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Browser/Tabs/Legacy/LegacyTabPeekPreviewActionBuilderTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Browser/Tabs/Legacy/LegacyTabPeekPreviewActionBuilderTests.swift @@ -35,7 +35,7 @@ final class LegacyTabPeekPreviewActionBuilderTests: XCTestCase { builder.addSendToDeviceTitle { _, __ in } let action = builder.build().first ?? UIPreviewAction() - XCTAssertEqual(action.title, String.AppMenu.TouchActions.SendToDeviceTitle) + XCTAssertEqual(action.title, String.LegacyAppMenu.TouchActions.SendToDeviceTitle) } func test_addCopyUrl_afterAdded_shouldContainsInActions() { diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Library/LibraryViewModelTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Library/LibraryViewModelTests.swift index 100a1eb0390f..2f4f3d49fc2a 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Library/LibraryViewModelTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Library/LibraryViewModelTests.swift @@ -40,13 +40,13 @@ class LibraryViewModelTests: XCTestCase { for panel in subject.panelDescriptors { switch panel.panelType { case .bookmarks: - XCTAssertEqual(panel.panelType.title, .AppMenu.AppMenuBookmarksTitleString) + XCTAssertEqual(panel.panelType.title, .LegacyAppMenu.AppMenuBookmarksTitleString) case .history: - XCTAssertEqual(panel.panelType.title, .AppMenu.AppMenuHistoryTitleString) + XCTAssertEqual(panel.panelType.title, .LegacyAppMenu.AppMenuHistoryTitleString) case .downloads: - XCTAssertEqual(panel.panelType.title, .AppMenu.AppMenuDownloadsTitleString) + XCTAssertEqual(panel.panelType.title, .LegacyAppMenu.AppMenuDownloadsTitleString) case .readingList: - XCTAssertEqual(panel.panelType.title, .AppMenu.AppMenuReadingListTitleString) + XCTAssertEqual(panel.panelType.title, .LegacyAppMenu.AppMenuReadingListTitleString) } } } diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/TabTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/TabTests.swift index 8886bddfa3a9..f1dbf879f450 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/TabTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/TabTests.swift @@ -36,7 +36,7 @@ class TabTests: XCTestCase { let url = URL(string: "internal://local/about/home")! let tab = Tab(profile: MockProfile(), windowUUID: windowUUID) tab.url = url - let expectedDisplayTitle = String.AppMenu.AppMenuOpenHomePageTitleString + let expectedDisplayTitle = String.LegacyAppMenu.AppMenuOpenHomePageTitleString XCTAssertEqual(tab.displayTitle, expectedDisplayTitle) } From a20fc2292367e5aed1233218b2a1c3e681681c24 Mon Sep 17 00:00:00 2001 From: mattreaganmozilla <145381717+mattreaganmozilla@users.noreply.github.com> Date: Tue, 27 Aug 2024 10:15:02 -0700 Subject: [PATCH 118/128] [9839] Allow session data to be restored for current tab even if the current page is home page (#21641) --- .../Client/TabManagement/TabManagerImplementation.swift | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/firefox-ios/Client/TabManagement/TabManagerImplementation.swift b/firefox-ios/Client/TabManagement/TabManagerImplementation.swift index 3254f4b8bf64..ae08c874e1f7 100644 --- a/firefox-ios/Client/TabManagement/TabManagerImplementation.swift +++ b/firefox-ios/Client/TabManagement/TabManagerImplementation.swift @@ -359,10 +359,7 @@ class TabManagerImplementation: LegacyTabManager, Notifiable, WindowSimpleTabsPr preserveTabs() - var sessionData: Data? - if !tab.isFxHomeTab { - sessionData = tabSessionStore.fetchTabSession(tabID: tabUUID) - } + let sessionData = tabSessionStore.fetchTabSession(tabID: tabUUID) selectTabWithSession(tab: tab, previous: previous, sessionData: sessionData) From 6eaddbafe7128248ddba2f5e16cf2c1ae892644e Mon Sep 17 00:00:00 2001 From: Isabella Date: Tue, 27 Aug 2024 13:19:42 -0600 Subject: [PATCH 119/128] Refactor FXIOS-9719 Update Twitter name String to X (#21630) * Update the "Twitter" title for the Default Suggested Tile to contain X (new name). * Fix UI test. * Update firefox-ios/Client/Frontend/Strings.swift Co-authored-by: roux g. buciu <11182210+adudenamedruby@users.noreply.github.com> * Test fix. --------- Co-authored-by: roux g. buciu <11182210+adudenamedruby@users.noreply.github.com> --- firefox-ios/Client/Frontend/Strings.swift | 5 +++++ firefox-ios/Storage/DefaultSuggestedSites.swift | 2 +- .../Tests/XCUITests/ActivityStreamTest.swift | 4 ++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/firefox-ios/Client/Frontend/Strings.swift b/firefox-ios/Client/Frontend/Strings.swift index 7025020f71f6..8044752a8d9a 100644 --- a/firefox-ios/Client/Frontend/Strings.swift +++ b/firefox-ios/Client/Frontend/Strings.swift @@ -6791,6 +6791,11 @@ extension String { tableName: nil, value: nil, comment: "Tile title for Twitter") + public static let DefaultSuggestedX = MZLocalizedString( + key: "SuggestedSites.X.Title.v131", + tableName: "SuggestedSites", + value: "X", + comment: "Title for X (formerly Twitter) tile in the suggested sites section of the homepage.") } // MARK: - Credential Provider diff --git a/firefox-ios/Storage/DefaultSuggestedSites.swift b/firefox-ios/Storage/DefaultSuggestedSites.swift index 4dcc769c583b..cec47fcb189e 100644 --- a/firefox-ios/Storage/DefaultSuggestedSites.swift +++ b/firefox-ios/Storage/DefaultSuggestedSites.swift @@ -73,7 +73,7 @@ open class DefaultSuggestedSites { imageUrl: "asset://suggestedsites_twitter", faviconUrl: "asset://defaultFavicon", trackingId: 628, - title: .DefaultSuggestedTwitter + title: .DefaultSuggestedX ) ], "zh_CN": [ diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/ActivityStreamTest.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/ActivityStreamTest.swift index e3f234fee875..1800d4e76614 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/ActivityStreamTest.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/ActivityStreamTest.swift @@ -10,7 +10,7 @@ let newTopSite = [ "topSiteLabel": "Mozilla", "bookmarkLabel": "Internet for people, not profit — Mozilla (US)" ] -let allDefaultTopSites = ["Facebook", "YouTube", "Amazon", "Wikipedia", "Twitter"] +let allDefaultTopSites = ["Facebook", "YouTube", "Amazon", "Wikipedia", "X"] class ActivityStreamTest: BaseTestCase { typealias TopSites = AccessibilityIdentifiers.FirefoxHomepage.TopSites @@ -53,7 +53,7 @@ class ActivityStreamTest: BaseTestCase { // There should be 5 top sites by default checkNumberOfExpectedTopSites(numberOfExpectedTopSites: 5) // Check their names so that test is added to Smoketest - mozWaitForElementToExist(app.collectionViews.cells.staticTexts["Twitter"]) + mozWaitForElementToExist(app.collectionViews.cells.staticTexts["X"]) mozWaitForElementToExist(app.collectionViews.cells.staticTexts["Amazon"]) mozWaitForElementToExist(app.collectionViews.cells.staticTexts["Wikipedia"]) mozWaitForElementToExist(app.collectionViews.cells.staticTexts["YouTube"]) From a7d6276e36d1675b6c46610a9627d5796fc5a8b5 Mon Sep 17 00:00:00 2001 From: Ione Souza Junior Date: Tue, 27 Aug 2024 17:52:38 -0300 Subject: [PATCH 120/128] Refactor FXIOS-7301 - Remove 1 closure_body_length violation from SearchLoader.swift (#21335) --- .../Frontend/Browser/SearchLoader.swift | 84 +++++++++++-------- 1 file changed, 47 insertions(+), 37 deletions(-) diff --git a/firefox-ios/Client/Frontend/Browser/SearchLoader.swift b/firefox-ios/Client/Frontend/Browser/SearchLoader.swift index cda2d17e2bad..bf5cd2c2d808 100644 --- a/firefox-ios/Client/Frontend/Browser/SearchLoader.swift +++ b/firefox-ios/Client/Frontend/Browser/SearchLoader.swift @@ -115,49 +115,59 @@ class SearchLoader: Loader, SearchViewModel>, FeatureFlaggable { } DispatchQueue.main.async { - let results = queries - defer { - GleanMetrics.Awesomebar.queryTime.stopAndAccumulate(timerid) - } + self.updateUIWithBookmarksAsSitesResults(queries: queries, + timerid: timerid, + historyHighlightsEnabled: historyHighlightsEnabled, + oldValue: oldValue) + } + } + } + } - let bookmarksSites = results[safe: 0] ?? [] - var combinedSites = bookmarksSites - if !historyHighlightsEnabled { - let historySites = results[safe: 1] ?? [] - combinedSites += historySites - } + private func updateUIWithBookmarksAsSitesResults(queries: [[Site]], + timerid: TimerId, + historyHighlightsEnabled: Bool, + oldValue: String) { + let results = queries + defer { + GleanMetrics.Awesomebar.queryTime.stopAndAccumulate(timerid) + } + + let bookmarksSites = results[safe: 0] ?? [] + var combinedSites = bookmarksSites + if !historyHighlightsEnabled { + let historySites = results[safe: 1] ?? [] + combinedSites += historySites + } - // Load the data in the table view. - self.load(ArrayCursor(data: combinedSites)) + // Load the data in the table view. + load(ArrayCursor(data: combinedSites)) - // If the new search string is not longer than the previous - // we don't need to find an autocomplete suggestion. - guard oldValue.count < self.query.count else { return } + // If the new search string is not longer than the previous + // we don't need to find an autocomplete suggestion. + guard oldValue.count < query.count else { return } - // If we should skip the next autocomplete, reset - // the flag and bail out here. - guard !self.skipNextAutocomplete else { - self.skipNextAutocomplete = false - return - } + // If we should skip the next autocomplete, reset + // the flag and bail out here. + guard !skipNextAutocomplete else { + skipNextAutocomplete = false + return + } - // First, see if the query matches any URLs from the user's search history. - for site in combinedSites { - if let completion = self.completionForURL(site.url) { - self.autocompleteView.setAutocompleteSuggestion(completion) - return - } - } + // First, see if the query matches any URLs from the user's search history. + for site in combinedSites { + if let completion = completionForURL(site.url) { + autocompleteView.setAutocompleteSuggestion(completion) + return + } + } - // If there are no search history matches, try matching one of the Alexa top domains. - if let topDomains = self.topDomains { - for domain in topDomains { - if let completion = self.completionForDomain(domain) { - self.autocompleteView.setAutocompleteSuggestion(completion) - return - } - } - } + // If there are no search history matches, try matching one of the Alexa top domains. + if let topDomains = topDomains { + for domain in topDomains { + if let completion = completionForDomain(domain) { + autocompleteView.setAutocompleteSuggestion(completion) + return } } } From 12492e41daea04712ad61c15c07afa762f3e0036 Mon Sep 17 00:00:00 2001 From: dragosb01 <134391433+dragosb01@users.noreply.github.com> Date: Wed, 28 Aug 2024 15:41:46 +0300 Subject: [PATCH 121/128] Fixess MTE-3339 - for credit card tests (#21659) --- .../Tests/XCUITests/CreditCardsTests.swift | 28 +++++++++---------- .../Tests/XCUITests/FxScreenGraph.swift | 2 +- .../XCUITests/TrackingProtectionTests.swift | 6 +--- 3 files changed, 16 insertions(+), 20 deletions(-) diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/CreditCardsTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/CreditCardsTests.swift index 70756e6ea97c..81d92f3797f9 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/CreditCardsTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/CreditCardsTests.swift @@ -206,7 +206,7 @@ class CreditCardsTests: BaseTestCase { typeCardName(name: updatedName) app.buttons["Save"].tap() // The name of the card is saved without issues - mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).staticTexts[updatedName]) + mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).buttons[updatedName]) // Go to an saved credit card and change the credit card number app.tables.cells.element(boundBy: 1).tap() app.buttons[creditCardsStaticTexts.ViewCreditCard.edit].tap() @@ -215,7 +215,7 @@ class CreditCardsTests: BaseTestCase { typeCardNr(cardNo: cards[1]) app.buttons["Save"].tap() // The credit card number is saved without issues - mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).staticTexts.elementContainingText("1111")) + mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).buttons.elementContainingText("1111")) // Reach autofill website // reachAutofillWebsite() does not work on iOS 15 if #available(iOS 16, *) { @@ -249,12 +249,12 @@ class CreditCardsTests: BaseTestCase { ["1111", "Test2", "6/40"], ["9631", "Test3", "7/40"]] for i in 1...3 { - mozWaitForElementToExist(app.tables.cells.element(boundBy: i).staticTexts.firstMatch) - XCTAssertTrue(app.tables.cells.element(boundBy: i).staticTexts.elementContainingText(cardsInfo[i-1][0]).exists, + mozWaitForElementToExist(app.tables.cells.element(boundBy: i).buttons.firstMatch) + XCTAssertTrue(app.tables.cells.element(boundBy: i).buttons.elementContainingText(cardsInfo[i-1][0]).exists, "\(cardsInfo[i-1][0]) info is not displayed") - XCTAssertTrue(app.tables.cells.element(boundBy: i).staticTexts[cardsInfo[i-1][1]].exists, + XCTAssertTrue(app.tables.cells.element(boundBy: i).buttons[cardsInfo[i-1][1]].exists, "\(cardsInfo[i-1][1]) info is not displayed") - XCTAssertTrue(app.tables.cells.element(boundBy: i).staticTexts[cardsInfo[i-1][2]].exists, + XCTAssertTrue(app.tables.cells.element(boundBy: i).buttons[cardsInfo[i-1][2]].exists, "\(cardsInfo[i-1][2]) info is not displayed") } // reachAutofillWebsite() not working on iOS 15 @@ -338,9 +338,9 @@ class CreditCardsTests: BaseTestCase { saveButton.tap() // The credit card is saved let cardsInfo = ["Test", "5/40"] - mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).staticTexts.elementContainingText("1252")) + mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).buttons.elementContainingText("1252")) for i in cardsInfo { - mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).staticTexts[i]) + mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).buttons[i]) } } @@ -398,10 +398,10 @@ class CreditCardsTests: BaseTestCase { unlockLoginsView() // The credit card is saved and displayed in the Credit cards section mozWaitForElementToExist(app.staticTexts[creditCardsStaticTexts.AutoFillCreditCard.savedCards]) - mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).staticTexts.elementContainingText("1111")) + mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).buttons.elementContainingText("1111")) let cardDetails = ["Test", "Expires", "5/40"] for i in cardDetails { - XCTAssertTrue(app.tables.cells.element(boundBy: 1).staticTexts[i].exists, "\(i) does not exists") + XCTAssertTrue(app.tables.cells.element(boundBy: 1).buttons[i].exists, "\(i) does not exists") } } @@ -479,10 +479,10 @@ class CreditCardsTests: BaseTestCase { navigator.goto(CreditCardsSettings) unlockLoginsView() // Credit cards details changed - mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).staticTexts.elementContainingText("1252")) + mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).buttons.elementContainingText("1252")) cardDetails = ["TestTest2", "Expires", "5/40"] for i in cardDetails { - mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).staticTexts[i]) + mozWaitForElementToExist(app.tables.cells.element(boundBy: 1).buttons[i]) } } @@ -505,9 +505,9 @@ class CreditCardsTests: BaseTestCase { } private func selectCreditCardOnFormWebsite() { - mozWaitForElementToExist(app.scrollViews.otherElements.tables.staticTexts["Test"]) + mozWaitForElementToExist(app.scrollViews.otherElements.tables.buttons["Test"]) var attempts = 4 - while app.scrollViews.otherElements.tables.staticTexts["Test"].isHittable && attempts > 0 { + while app.scrollViews.otherElements.tables.buttons["Test"].isHittable && attempts > 0 { app.scrollViews.otherElements.tables.cells.firstMatch.tapOnApp() attempts -= 1 } diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/FxScreenGraph.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/FxScreenGraph.swift index 02e60ee08d3c..66089f8341cd 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/FxScreenGraph.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/FxScreenGraph.swift @@ -369,7 +369,7 @@ func createScreenGraph(for test: XCTestCase, with app: XCUIApplication) -> MMScr // There is no Cancel option in iPad. app.otherElements["PopoverDismissRegion"].tap() } else { - app.buttons["PhotonMenu.close"].tap() + app.buttons["Close"].tap() } } } diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/TrackingProtectionTests.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/TrackingProtectionTests.swift index c7d3aeda3e00..bdfc1cdff251 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/TrackingProtectionTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/TrackingProtectionTests.swift @@ -192,11 +192,7 @@ class TrackingProtectionTests: BaseTestCase { navigator.nowAt(BrowserTab) navigator.goto(TrackingProtectionContextMenuDetails) mozWaitForElementToExist(app.staticTexts["Secure connection"]) - if iPad() { - app.popovers.scrollViews.buttons.element(boundBy: 2).tap() - } else { - app.buttons["Close"].tap() - } + navigator.performAction(Action.CloseTPContextMenu) mozWaitForElementToNotExist(app.staticTexts["Secure connection"]) } } From a050d09ecbc68ec601a06bb447be7234744c1bd9 Mon Sep 17 00:00:00 2001 From: Matt Lichtenstein Date: Wed, 28 Aug 2024 10:21:23 -0400 Subject: [PATCH 122/128] Add FXIOS-9841 Show search action in navigation toolbar on private homepage (#21656) --- .../Toolbars/Redux/ToolbarMiddleware.swift | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift index 1209bea91eef..1b34df07334c 100644 --- a/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift +++ b/firefox-ios/Client/Frontend/Browser/Toolbars/Redux/ToolbarMiddleware.swift @@ -549,7 +549,7 @@ final class ToolbarMiddleware: FeatureFlaggable { let isForwardButtonEnabled = canGoForward actions.append(backAction(enabled: isBackButtonEnabled)) actions.append(forwardAction(enabled: isForwardButtonEnabled)) - if shouldShowDataClearanceAction(isPrivate: toolbarState.isPrivateMode) { + if canShowDataClearanceAction(isPrivate: toolbarState.isPrivateMode) { actions.append(dataClearanceAction) } } @@ -688,15 +688,12 @@ final class ToolbarMiddleware: FeatureFlaggable { } private func getMiddleButtonAction(url: URL?, isPrivateMode: Bool) -> ToolbarActionState { - let shouldShowDataClearanceAction = shouldShowDataClearanceAction(isPrivate: isPrivateMode) - guard !shouldShowDataClearanceAction else { - return dataClearanceAction - } - + let canShowDataClearanceAction = canShowDataClearanceAction(isPrivate: isPrivateMode) let isNewTabEnabled = featureFlags.isFeatureEnabled(.toolbarOneTapNewTab, checking: .buildOnly) - let middleActionDefault = isNewTabEnabled ? newTabAction : homeAction - let middleActionHome = searchAction - let middleAction = url == nil ? middleActionHome : middleActionDefault + let middleActionForWebpage = canShowDataClearanceAction ? + dataClearanceAction : isNewTabEnabled ? newTabAction : homeAction + let middleActionForHomepage = searchAction + let middleAction = url == nil ? middleActionForHomepage : middleActionForWebpage return middleAction } @@ -759,7 +756,7 @@ final class ToolbarMiddleware: FeatureFlaggable { return manager.shouldDisplayNavigationBorder(toolbarPosition: toolbarPosition) } - private func shouldShowDataClearanceAction(isPrivate: Bool) -> Bool { + private func canShowDataClearanceAction(isPrivate: Bool) -> Bool { let isFeltPrivacyUIEnabled = featureFlags.isFeatureEnabled(.feltPrivacySimplifiedUI, checking: .buildOnly) let isFeltPrivacyDeletionEnabled = featureFlags.isFeatureEnabled(.feltPrivacyFeltDeletion, checking: .buildOnly) From a89b807a1b9eb1285cc41a3a29d7b9e0e097507e Mon Sep 17 00:00:00 2001 From: Daniel Dervishi <58835213+DanielDervishi@users.noreply.github.com> Date: Wed, 28 Aug 2024 14:14:42 -0400 Subject: [PATCH 123/128] Bugfix FXIOS-9783 - Add strings for Bookmarks MVP+1 (#21666) * Finished string changes * Added version numbers to string keys * Updated version number to release the strings are included in * Fixed swiftlint violations * Updated bookmarks string --------- Co-authored-by: Daniel Dervishi --- firefox-ios/Client/Frontend/Strings.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firefox-ios/Client/Frontend/Strings.swift b/firefox-ios/Client/Frontend/Strings.swift index 8044752a8d9a..43da339897c9 100644 --- a/firefox-ios/Client/Frontend/Strings.swift +++ b/firefox-ios/Client/Frontend/Strings.swift @@ -165,7 +165,7 @@ extension String { public static let DeletedBookmark = MZLocalizedString( key: "Bookmarks.Menu.DeletedBookmark.v131", tableName: "Bookmarks", - value: "Deleted \"%@\"", + value: "Deleted “%@”", comment: "Label of toast displayed after a bookmark is deleted in the Bookmarks menu. %@ is the name of the bookmark.") public static let BookmarksTopLevelTitle = MZLocalizedString( key: "Bookmarks.Menu.BookmarksTopLevelTitle.v131", From d81c422a95d18be6e3096879d455d64f2dff3ea7 Mon Sep 17 00:00:00 2001 From: dicarobinho <61138287+dicarobinho@users.noreply.github.com> Date: Thu, 29 Aug 2024 11:37:56 +0300 Subject: [PATCH 124/128] =?UTF-8?q?Add=20FXIOS-9201=20=E2=81=83=20Enhanced?= =?UTF-8?q?=20Tracking=20Protection=20certificates=20details=20screen=20(#?= =?UTF-8?q?21596)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * FXIOS-9201 #20369 ⁃ Enhanced Tracking Protection certificates details screen * Fixed pbxproj file * Fixed some PR requested changes after PR Wrote some tests for CertificatesViewModel class * Fixed SwiftLint warnings * Did some code changes after code review * Added two more tests for CertificatesViewModel class * Added two logs for CertificatesHandler --- firefox-ios/Client.xcodeproj/project.pbxproj | 16 + .../TrackingProtection/CertificatesCell.swift | 100 +++++++ .../CertificatesHandler.swift | 59 +++- .../CertificatesViewController.swift | 278 ++++++++++++++++++ .../CertificatesViewModel.swift | 65 ++++ .../TrackingProtectionModel.swift | 7 + .../TrackingProtectionViewController.swift | 5 + .../CertificatesViewModelTests.swift | 57 ++++ 8 files changed, 583 insertions(+), 4 deletions(-) create mode 100644 firefox-ios/Client/Frontend/TrackingProtection/CertificatesCell.swift create mode 100644 firefox-ios/Client/Frontend/TrackingProtection/CertificatesViewController.swift create mode 100644 firefox-ios/Client/Frontend/TrackingProtection/CertificatesViewModel.swift create mode 100644 firefox-ios/firefox-ios-tests/Tests/ClientTests/TrackingProtectionTests/CertificatesViewModelTests.swift diff --git a/firefox-ios/Client.xcodeproj/project.pbxproj b/firefox-ios/Client.xcodeproj/project.pbxproj index aaf24cb0f202..99861ec5c661 100644 --- a/firefox-ios/Client.xcodeproj/project.pbxproj +++ b/firefox-ios/Client.xcodeproj/project.pbxproj @@ -16,11 +16,15 @@ 047F9B3E24E1FF4000CD7DF7 /* SearchQuickLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 047F9B3A24E1FF4000CD7DF7 /* SearchQuickLinks.swift */; }; 047F9B4224E1FF4000CD7DF7 /* ImageButtonWithLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 047F9B3C24E1FF4000CD7DF7 /* ImageButtonWithLabel.swift */; }; 0A49784A2C53E63200B1E82A /* TrackingProtectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A4978492C53E63200B1E82A /* TrackingProtectionViewController.swift */; }; + 0A7693612C7DD19600103A6D /* CertificatesViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A7693602C7DD19500103A6D /* CertificatesViewModelTests.swift */; }; 0AC659272BF35854005C614A /* FxAWebViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AC659262BF35854005C614A /* FxAWebViewModelTests.swift */; }; 0AC659292BF493CE005C614A /* MockFxAWebViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AC659282BF493CE005C614A /* MockFxAWebViewModel.swift */; }; 0AD3EEAC2C2485A7001044E5 /* ThemedCenteredTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AD3EEAB2C2485A7001044E5 /* ThemedCenteredTableViewCell.swift */; }; 0AFF7F642C7784D600265214 /* MockDataCleaner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AFF7F632C7784D600265214 /* MockDataCleaner.swift */; }; 0AFF7F662C7784F100265214 /* TrackingProtectionModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AFF7F652C7784F000265214 /* TrackingProtectionModelTests.swift */; }; + 0AFF7F6C2C7C7BBA00265214 /* CertificatesCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AFF7F692C7C7BB800265214 /* CertificatesCell.swift */; }; + 0AFF7F6D2C7C7BBA00265214 /* CertificatesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AFF7F6A2C7C7BB900265214 /* CertificatesViewController.swift */; }; + 0AFF7F6E2C7C7BBA00265214 /* CertificatesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AFF7F6B2C7C7BB900265214 /* CertificatesViewModel.swift */; }; 0B305E1B1E3A98A900BE0767 /* BookmarksTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B305E1A1E3A98A900BE0767 /* BookmarksTests.swift */; }; 0B3D670E1E09B90B00C1EFC7 /* AuthenticationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B3D670D1E09B90B00C1EFC7 /* AuthenticationTest.swift */; }; 0B54BD191B698B7C004C822C /* SuggestedSites.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B54BD181B698B7C004C822C /* SuggestedSites.swift */; }; @@ -2159,6 +2163,7 @@ 0A574D09BF8D9E37D6C9C654 /* bn */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bn; path = bn.lproj/ClearHistoryConfirm.strings; sourceTree = ""; }; 0A5B4CE9B0996AE804491134 /* an */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = an; path = an.lproj/Shared.strings; sourceTree = ""; }; 0A734328A164466314ECE4BE /* ia */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ia; path = ia.lproj/Menu.strings; sourceTree = ""; }; + 0A7693602C7DD19500103A6D /* CertificatesViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CertificatesViewModelTests.swift; sourceTree = ""; }; 0A7D41DB98DDB127A2B8C544 /* ms */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ms; path = ms.lproj/Menu.strings; sourceTree = ""; }; 0AC659262BF35854005C614A /* FxAWebViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FxAWebViewModelTests.swift; sourceTree = ""; }; 0AC659282BF493CE005C614A /* MockFxAWebViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockFxAWebViewModel.swift; sourceTree = ""; }; @@ -2166,6 +2171,9 @@ 0AE9462E8A8E05CE07D4973D /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/InfoPlist.strings; sourceTree = ""; }; 0AFF7F632C7784D600265214 /* MockDataCleaner.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockDataCleaner.swift; sourceTree = ""; }; 0AFF7F652C7784F000265214 /* TrackingProtectionModelTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrackingProtectionModelTests.swift; sourceTree = ""; }; + 0AFF7F692C7C7BB800265214 /* CertificatesCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CertificatesCell.swift; sourceTree = ""; }; + 0AFF7F6A2C7C7BB900265214 /* CertificatesViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CertificatesViewController.swift; sourceTree = ""; }; + 0AFF7F6B2C7C7BB900265214 /* CertificatesViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CertificatesViewModel.swift; sourceTree = ""; }; 0B305E1A1E3A98A900BE0767 /* BookmarksTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BookmarksTests.swift; sourceTree = ""; }; 0B3D670D1E09B90B00C1EFC7 /* AuthenticationTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthenticationTest.swift; sourceTree = ""; }; 0B414433840C8AA60829B6FB /* ms */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ms; path = ms.lproj/Intro.strings; sourceTree = ""; }; @@ -11041,6 +11049,9 @@ AB2AC6642BD15E2C00022AAB /* TrackingProtection */ = { isa = PBXGroup; children = ( + 0AFF7F692C7C7BB800265214 /* CertificatesCell.swift */, + 0AFF7F6A2C7C7BB900265214 /* CertificatesViewController.swift */, + 0AFF7F6B2C7C7BB900265214 /* CertificatesViewModel.swift */, AB9CBBFE2C53B64B00102610 /* TrackingProtectionAction.swift */, AB9CBBFF2C53B64B00102610 /* TrackingProtectionMiddleware.swift */, AB9CBC002C53B64B00102610 /* TrackingProtectionModel.swift */, @@ -11057,6 +11068,7 @@ children = ( 0AFF7F652C7784F000265214 /* TrackingProtectionModelTests.swift */, AB9CBC062C53B76400102610 /* TrackingProtectionStateTests.swift */, + 0A7693602C7DD19500103A6D /* CertificatesViewModelTests.swift */, ); path = TrackingProtectionTests; sourceTree = ""; @@ -14734,6 +14746,7 @@ E1877A832875DEDE00F5BDF2 /* SyncedTabCell.swift in Sources */, 21E77E522AA8BE5C00FABA10 /* TabTrayFlagManager.swift in Sources */, CA8226F324C11DB7008A6F38 /* PasswordManagerTableViewCell.swift in Sources */, + 0AFF7F6E2C7C7BBA00265214 /* CertificatesViewModel.swift in Sources */, 8A0A1BA02B2200FD00E8706F /* PrivateHomepageViewController.swift in Sources */, E4A960061ABB9C450069AD6F /* ReaderModeUtils.swift in Sources */, 8AD40FCB27BADC4B00672675 /* StatefulButton.swift in Sources */, @@ -14866,6 +14879,7 @@ 967A028E28FA026F003C35E3 /* SceneDelegate.swift in Sources */, C8B07A4128199500000AFCE7 /* NimbusFlaggableFeature.swift in Sources */, 0B62EFD21AD63CD100ACB9CD /* Clearables.swift in Sources */, + 0AFF7F6C2C7C7BBA00265214 /* CertificatesCell.swift in Sources */, 8AAEBA062BF51141000C02B5 /* MicrosurveyMiddleware.swift in Sources */, 431C0CA925C890E500395CE4 /* DefaultBrowserOnboardingViewModel.swift in Sources */, DFACBF81277B916B003D5F41 /* ConfigurableGradientView.swift in Sources */, @@ -15362,6 +15376,7 @@ 3B39EDCB1E16E1AA00EF029F /* CustomSearchViewController.swift in Sources */, B2DFB7E12B619DF60004CEA5 /* AddressListView.swift in Sources */, C8B0F5F7283B7CCE007AE65D /* PocketFeedStory.swift in Sources */, + 0AFF7F6D2C7C7BBA00265214 /* CertificatesViewController.swift in Sources */, 96A562A027D6D0E80045144A /* ContileProvider.swift in Sources */, 8A5D1CAC2A30D70B005AD35C /* OpenWithSetting.swift in Sources */, 8AFA263227B6E9AB00D0C33B /* ToolbarBadge.swift in Sources */, @@ -15669,6 +15684,7 @@ C869915728917809007ACC5C /* NetworkingMock.swift in Sources */, 8A4190D22A6B0848001E8401 /* StatusBarOverlayTests.swift in Sources */, C8EDDBF029DD83FC003A4C07 /* RouteTests.swift in Sources */, + 0A7693612C7DD19600103A6D /* CertificatesViewModelTests.swift in Sources */, 8AED868328CA3B3400351A50 /* BookmarkPanelViewModelTests.swift in Sources */, 434CD57829F6FC4500A0D04B /* MockAppAuthenticator.swift in Sources */, DACDE996225E537900C8F37F /* VersionSettingTests.swift in Sources */, diff --git a/firefox-ios/Client/Frontend/TrackingProtection/CertificatesCell.swift b/firefox-ios/Client/Frontend/TrackingProtection/CertificatesCell.swift new file mode 100644 index 000000000000..d9b7b3c840b5 --- /dev/null +++ b/firefox-ios/Client/Frontend/TrackingProtection/CertificatesCell.swift @@ -0,0 +1,100 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/ + +import Foundation +import Common + +final class CertificatesCell: UITableViewCell, ReusableCell, ThemeApplicable { + struct UX { + static let sectionLabelWidth = 150.0 + static let sectionLabelMargin = 20.0 + static let sectionItemsSpacing = 40.0 + static let allSectionItemsSpacing = 10.0 + static let allSectionItemsTopMargin = 20.0 + } + + var sectionLabel: UILabel = .build { label in + label.font = FXFontStyles.Bold.headline.scaledFont() + label.textAlignment = .right + label.numberOfLines = 0 + label.lineBreakMode = .byWordWrapping + } + + var allSectionItemsStackView: UIStackView = .build { stack in + stack.axis = .vertical + stack.distribution = .equalSpacing + stack.spacing = UX.allSectionItemsSpacing + } + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + + contentView.addSubview(sectionLabel) + contentView.addSubview(allSectionItemsStackView) + + NSLayoutConstraint.activate([ + sectionLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, + constant: UX.sectionLabelMargin), + sectionLabel.topAnchor.constraint(equalTo: contentView.topAnchor, + constant: UX.sectionLabelMargin), + sectionLabel.widthAnchor.constraint(equalToConstant: UX.sectionLabelWidth), + + allSectionItemsStackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, + constant: UX.sectionLabelMargin), + allSectionItemsStackView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, + constant: -UX.sectionLabelMargin), + allSectionItemsStackView.topAnchor.constraint(equalTo: sectionLabel.bottomAnchor, + constant: UX.allSectionItemsTopMargin), + allSectionItemsStackView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, + constant: -UX.sectionLabelMargin) + ]) + } + + override func prepareForReuse() { + super.prepareForReuse() + allSectionItemsStackView.removeAllArrangedViews() + sectionLabel.text = nil + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func configure(theme: Theme, sectionTitle: String, items: CertificateItems) { + applyTheme(theme: theme) + sectionLabel.text = sectionTitle + for (key, value) in items { + let stackView = getSectionItemStackView() + let titleLabel = getItemLabel(theme: theme, with: key, isTitle: true) + titleLabel.widthAnchor.constraint(equalToConstant: UX.sectionLabelWidth).isActive = true + stackView.addArrangedSubview(titleLabel) + stackView.addArrangedSubview(getItemLabel(theme: theme, with: value, isTitle: false)) + allSectionItemsStackView.addArrangedSubview(stackView) + } + } + + func applyTheme(theme: Theme) { + sectionLabel.textColor = theme.colors.textPrimary + } + + private func getItemLabel(theme: Theme, with title: String, isTitle: Bool) -> UILabel { + let itemLabel: UILabel = .build { label in + label.font = FXFontStyles.Bold.headline.scaledFont() + label.textColor = isTitle ? theme.colors.textSecondary : theme.colors.textPrimary + label.text = title + label.textAlignment = isTitle ? .right : .left + label.numberOfLines = 0 + label.lineBreakMode = .byWordWrapping + } + return itemLabel + } + + private func getSectionItemStackView() -> UIStackView { + let sectionItemsStackView: UIStackView = .build { stack in + stack.axis = .horizontal + stack.spacing = UX.sectionItemsSpacing + } + return sectionItemsStackView + } +} diff --git a/firefox-ios/Client/Frontend/TrackingProtection/CertificatesHandler.swift b/firefox-ios/Client/Frontend/TrackingProtection/CertificatesHandler.swift index ab7fa050e61f..7e96e81330fd 100644 --- a/firefox-ios/Client/Frontend/TrackingProtection/CertificatesHandler.swift +++ b/firefox-ios/Client/Frontend/TrackingProtection/CertificatesHandler.swift @@ -7,10 +7,10 @@ import Security import CryptoKit import X509 import SwiftASN1 +import Common class CertificatesHandler { private let serverTrust: SecTrust - var certificates = [Certificate]() /// Initializes a new `CertificatesHandler` with the given server trust. /// - Parameters: @@ -20,17 +20,68 @@ class CertificatesHandler { } /// Extracts and handles the certificate chain. - func handleCertificates() { + /// - Parameters: + /// - completion: A completion block that provides the extracted certificates. + func handleCertificates() -> [Certificate] { + var certificates = [Certificate]() guard let certificateChain = SecTrustCopyCertificateChain(serverTrust) as? [SecCertificate] else { - return + return certificates } - for (_, certificate) in certificateChain.enumerated() { + for certificate in certificateChain { let certificateData = SecCertificateCopyData(certificate) as Data do { let certificate = try Certificate(derEncoded: Array(certificateData)) certificates.append(certificate) } catch { + DefaultLogger.shared.log("\(error)", + level: .warning, + category: .homepage) } } + return certificates + } +} + +// Define a function to get the certificates for a given URL +func getCertificates(for url: URL, completion: @escaping ([Certificate]?) -> Void) { + // Create a URL session with a custom delegate + let session = URLSession(configuration: .default, + delegate: CertificateDelegate(completion: completion), + delegateQueue: nil) + + // Start a data task to trigger the certificate retrieval + let task = session.dataTask(with: url) { _, _, error in + if let error = error { + DefaultLogger.shared.log("\(error)", + level: .warning, + category: .homepage) + completion(nil) + } + } + + task.resume() +} + +// Custom delegate to handle the authentication challenge +class CertificateDelegate: NSObject, URLSessionDelegate { + private let completion: ([Certificate]?) -> Void + + init(completion: @escaping ([Certificate]?) -> Void) { + self.completion = completion + } + + func urlSession(_ session: URLSession, didReceive + challenge: URLAuthenticationChallenge, + completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { + if let serverTrust = challenge.protectionSpace.serverTrust { + let certificatesHandler = CertificatesHandler(serverTrust: serverTrust) + self.completion(certificatesHandler.handleCertificates()) + // Use the server trust + completionHandler(.useCredential, URLCredential(trust: serverTrust)) + } else { + // Call the completion handler with nil if serverTrust is not available + self.completion(nil) + completionHandler(.cancelAuthenticationChallenge, nil) + } } } diff --git a/firefox-ios/Client/Frontend/TrackingProtection/CertificatesViewController.swift b/firefox-ios/Client/Frontend/TrackingProtection/CertificatesViewController.swift new file mode 100644 index 000000000000..2133efb857eb --- /dev/null +++ b/firefox-ios/Client/Frontend/TrackingProtection/CertificatesViewController.swift @@ -0,0 +1,278 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/ + +import Foundation +import Common +import Shared +import SiteImageView + +import Security +import CryptoKit +import X509 +import SwiftASN1 + +struct CertificateKeys { + static let commonName = "CN" + static let country = "C" + static let organization = "O" +} + +typealias CertificateItems = [(key: String, value: String)] + +class CertificatesViewController: UIViewController, Themeable, UITableViewDelegate, UITableViewDataSource { + private enum CertificatesItemType: Int { + case subjectName + case issuerName + case validity + case subjectAltName + } + + // MARK: - UI + struct UX { + static let headerStackViewSpacing = 16.0 + static let titleLabelMargin = 8.0 + static let titleLabelTopMargin = 20.0 + static let headerStackViewMargin = 8.0 + static let headerStackViewTopMargin = 20.0 + static let tableViewSpacerTopMargin = 20.0 + static let tableViewSpacerHeight = 1.0 + static let tableViewTopMargin = 20.0 + } + + private let titleLabel: UILabel = .build { label in + label.font = FXFontStyles.Bold.title1.scaledFont() + label.text = .Menu.EnhancedTrackingProtection.certificatesTitle + } + + private let headerStackView: UIStackView = .build { stack in + stack.axis = .horizontal + stack.distribution = .fillEqually + stack.spacing = UX.headerStackViewSpacing + } + + private let tableViewTopSpacer: UIView = .build() + + let certificatesTableView: UITableView = .build { tableView in + tableView.allowsSelection = false + tableView.register(CertificatesCell.self, forCellReuseIdentifier: CertificatesCell.cellIdentifier) + } + + // MARK: - Variables + private var constraints = [NSLayoutConstraint]() + var viewModel: CertificatesViewModel + var notificationCenter: NotificationProtocol + var themeManager: ThemeManager + var themeObserver: NSObjectProtocol? + let windowUUID: WindowUUID + var currentWindowUUID: UUID? { return windowUUID } + + // MARK: - View Lifecycle + + init(with viewModel: CertificatesViewModel, + windowUUID: WindowUUID, + and notificationCenter: NotificationProtocol = NotificationCenter.default, + themeManager: ThemeManager = AppContainer.shared.resolve()) { + self.viewModel = viewModel + self.windowUUID = windowUUID + self.notificationCenter = notificationCenter + self.themeManager = themeManager + super.init(nibName: nil, bundle: nil) + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + deinit { + notificationCenter.removeObserver(self) + } + + override func viewDidLoad() { + super.viewDidLoad() + setupView() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + updateViewDetails() + listenForThemeChange(view) + applyTheme() + } + + private func setupView() { + constraints.removeAll() + setupTitleConstraints() + setupCertificatesHeaderView() + setupCertificatesTableView() + setupAccessibilityIdentifiers() + NSLayoutConstraint.activate(constraints) + } + + private func setupTitleConstraints() { + view.addSubview(titleLabel) + NSLayoutConstraint.activate([ + titleLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: UX.titleLabelMargin), + titleLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -UX.titleLabelMargin), + titleLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: UX.titleLabelTopMargin) + ]) + } + + private func setupCertificatesHeaderView() { + // TODO: FXIOS-9834 Add tab indicator for table view tabs and hide/unhide it on selection + for (index, certificate) in viewModel.certificates.enumerated() { + let certificateValues = viewModel.getCertificateValues(from: "\(certificate.subject)") + if !certificateValues.isEmpty, let commonName = certificateValues[CertificateKeys.commonName] { + let button: UIButton = .build { [weak self] button in + button.setTitle(commonName, for: .normal) + button.setTitleColor(self?.currentTheme().colors.textPrimary, for: .normal) + button.configuration?.titleLineBreakMode = .byWordWrapping + button.titleLabel?.numberOfLines = 2 + button.titleLabel?.textAlignment = .center + button.tag = index + button.addTarget(self, action: #selector(self?.certificateButtonTapped(_:)), for: .touchUpInside) + } + headerStackView.addArrangedSubview(button) + } + } + + view.addSubview(headerStackView) + + NSLayoutConstraint.activate([ + headerStackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, + constant: UX.headerStackViewMargin), + headerStackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, + constant: -UX.headerStackViewMargin), + headerStackView.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, + constant: UX.headerStackViewTopMargin) + ]) + } + + private func setupCertificatesTableView() { + certificatesTableView.delegate = self + certificatesTableView.dataSource = self + view.addSubview(tableViewTopSpacer) + view.addSubview(certificatesTableView) + NSLayoutConstraint.activate([ + tableViewTopSpacer.topAnchor.constraint(equalTo: headerStackView.bottomAnchor, + constant: UX.tableViewSpacerTopMargin), + tableViewTopSpacer.leadingAnchor.constraint(equalTo: view.leadingAnchor), + tableViewTopSpacer.trailingAnchor.constraint(equalTo: view.trailingAnchor), + tableViewTopSpacer.heightAnchor.constraint(equalToConstant: UX.tableViewSpacerHeight), + + certificatesTableView.topAnchor.constraint(equalTo: tableViewTopSpacer.bottomAnchor, + constant: UX.tableViewTopMargin), + certificatesTableView.leadingAnchor.constraint(equalTo: view.leadingAnchor), + certificatesTableView.trailingAnchor.constraint(equalTo: view.trailingAnchor), + certificatesTableView.bottomAnchor.constraint(equalTo: view.bottomAnchor) + ]) + } + + @objc + private func certificateButtonTapped(_ sender: UIButton) { + viewModel.selectedCertificateIndex = sender.tag + certificatesTableView.reloadData() + } + + // MARK: - UITableViewDataSource + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + guard !viewModel.certificates.isEmpty else { return 0 } + return 4 + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + guard let cell = tableView.dequeueReusableCell(withIdentifier: CertificatesCell.cellIdentifier, for: indexPath) + as? CertificatesCell else { + return UITableViewCell() + } + + guard !viewModel.certificates.isEmpty else { + return cell + } + + let certificate = viewModel.certificates[viewModel.selectedCertificateIndex] + + switch CertificatesItemType(rawValue: indexPath.row) { + case .subjectName: + if let commonName = viewModel.getCertificateValues(from: "\(certificate.subject)")[CertificateKeys.commonName] { + cell.configure(theme: currentTheme(), + sectionTitle: .Menu.EnhancedTrackingProtection.certificateSubjectName, + items: [(.Menu.EnhancedTrackingProtection.certificateCommonName, commonName)]) + } + + case .issuerName: + let issuerData = viewModel.getCertificateValues(from: "\(certificate.issuer)") + if let country = issuerData[CertificateKeys.country], + let organization = issuerData[CertificateKeys.organization], + let commonName = issuerData[CertificateKeys.commonName] { + cell.configure(theme: currentTheme(), + sectionTitle: .Menu.EnhancedTrackingProtection.certificateIssuerName, + items: [(.Menu.EnhancedTrackingProtection.certificateIssuerCountry, country), + (.Menu.EnhancedTrackingProtection.certificateIssuerOrganization, organization), + (.Menu.EnhancedTrackingProtection.certificateCommonName, commonName)]) + } + + case .validity: + cell.configure(theme: currentTheme(), + sectionTitle: .Menu.EnhancedTrackingProtection.certificateValidity, + items: [ + (.Menu.EnhancedTrackingProtection.certificateValidityNotBefore, + certificate.notValidBefore.toRFC822String()), + (.Menu.EnhancedTrackingProtection.certificateValidityNotAfter, + certificate.notValidAfter.toRFC822String()) + ]) + + case .subjectAltName: + cell.configure(theme: currentTheme(), + sectionTitle: .Menu.EnhancedTrackingProtection.certificateSubjectAltNames, + items: viewModel.getDNSNames(for: certificate)) + case .none: break + } + return cell + } + + // MARK: Accessibility + private func setupAccessibilityIdentifiers() { + // TODO: FXIOS-9829 Enhanced Tracking Protection certificates details screen accessibility identifiers + } + + // MARK: View Transitions + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + adjustLayout() + } + + override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { + super.viewWillTransition(to: size, with: coordinator) + coordinator.animate(alongsideTransition: { _ in + self.adjustLayout() + }, completion: nil) + } + + private func adjustLayout() { + view.setNeedsLayout() + view.layoutIfNeeded() + } + + private func updateViewDetails() { + self.certificatesTableView.reloadData() + } + + // MARK: - Actions + private func currentTheme() -> Theme { + return themeManager.getCurrentTheme(for: windowUUID) + } +} + +// MARK: - Themable +extension CertificatesViewController { + func applyTheme() { + let theme = currentTheme() + overrideUserInterfaceStyle = theme.type.getInterfaceStyle() + view.backgroundColor = theme.colors.layer5 + titleLabel.textColor = theme.colors.textPrimary + tableViewTopSpacer.backgroundColor = theme.colors.layer1 + setNeedsStatusBarAppearanceUpdate() + } +} diff --git a/firefox-ios/Client/Frontend/TrackingProtection/CertificatesViewModel.swift b/firefox-ios/Client/Frontend/TrackingProtection/CertificatesViewModel.swift new file mode 100644 index 000000000000..e8c9fb56e3ef --- /dev/null +++ b/firefox-ios/Client/Frontend/TrackingProtection/CertificatesViewModel.swift @@ -0,0 +1,65 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/ + +import Foundation +import X509 + +// TODO FXIOS-9853 ⁃ Enhanced Tracking Protection Redux +final class CertificatesViewModel { + let topLevelDomain: String + let title: String + let URL: String + var certificates = [Certificate]() + var selectedCertificateIndex: Int = 0 + + init(topLevelDomain: String, title: String, URL: String, certificates: [Certificate]) { + self.topLevelDomain = topLevelDomain + self.title = title + self.URL = URL + self.certificates = certificates + } + + func getCertificateValues(from input: String) -> [String: String] { + var result = [String: String]() + let components = input.split(separator: ",") + for component in components { + let parts = component.split(separator: "=", maxSplits: 1, omittingEmptySubsequences: false) + if parts.count == 2 { + let key = parts[0].trimmingCharacters(in: .whitespacesAndNewlines) + let value = parts[1].trimmingCharacters(in: .whitespacesAndNewlines) + result[key] = value + } + } + return result + } + + func getDNSNamesList(from input: String) -> [String] { + let pattern = #"DNSName\("([^"]+)"\)"# + var dnsNames: [String] = [] + do { + let regex = try NSRegularExpression(pattern: pattern, options: []) + let matches = regex.matches(in: input, options: [], range: NSRange(location: 0, length: input.utf16.count)) + for match in matches { + if let range = Range(match.range(at: 1), in: input) { + let dnsNameString = String(input[range]) + dnsNames.append(dnsNameString) + } + } + return dnsNames + } catch { + return [] + } + } + + func getDNSNames(for certificate: Certificate) -> CertificateItems { + var dnsNames: CertificateItems = [] + if let certificateExtension = + certificate.extensions.first(where: { $0.description.contains("SubjectAlternativeNames") }) { + for dnsName in getDNSNamesList(from: certificateExtension.description) { + dnsNames.append((.Menu.EnhancedTrackingProtection.certificateSubjectAltNamesDNSName, dnsName)) + } + } + return dnsNames + } +} diff --git a/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionModel.swift b/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionModel.swift index 72e6331db89e..e52ba3abbe1c 100644 --- a/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionModel.swift +++ b/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionModel.swift @@ -136,6 +136,13 @@ class TrackingProtectionModel { } } + func getCertificatesViewModel() -> CertificatesViewModel { + return CertificatesViewModel(topLevelDomain: websiteTitle, + title: displayTitle, + URL: url.absoluteDisplayString, + certificates: certificates) + } + func toggleSiteSafelistStatus() { TelemetryWrapper.recordEvent(category: .action, method: .add, object: .trackingProtectionSafelist) ContentBlocker.shared.safelist(enable: contentBlockerStatus != .safelisted, url: url) { diff --git a/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionViewController.swift b/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionViewController.swift index 630a8cf1ba01..ac0fa9147973 100644 --- a/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionViewController.swift +++ b/firefox-ios/Client/Frontend/TrackingProtection/TrackingProtectionViewController.swift @@ -334,6 +334,11 @@ class TrackingProtectionViewController: UIViewController, Themeable, Notifiable, updateViewDetails() updateProtectionViewStatus() applyTheme() + getCertificates(for: viewModel.url) { [weak self] certificates in + if let certs = certificates { + self?.viewModel.certificates = certs + } + } } private func setupView() { diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/TrackingProtectionTests/CertificatesViewModelTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/TrackingProtectionTests/CertificatesViewModelTests.swift new file mode 100644 index 000000000000..c912cb5bc02f --- /dev/null +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/TrackingProtectionTests/CertificatesViewModelTests.swift @@ -0,0 +1,57 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/ + +import Foundation +import XCTest +import X509 +@testable import Client + +final class CertificatesViewModelTests: XCTestCase { + private var viewModel: CertificatesViewModel! + + override func setUp() { + super.setUp() + viewModel = CertificatesViewModel(topLevelDomain: "topLevelDomainTest.com", + title: "TitleTest", + URL: "https://google.com", + certificates: []) + } + + override func tearDown() { + super.tearDown() + viewModel = nil + } + + func testGetCertificateValues() { + let data = "CN=www.google.com, O=Google Trust Services, C=US" + let result = viewModel.getCertificateValues(from: data) + XCTAssertEqual(result["CN"], "www.google.com") + XCTAssertEqual(result["O"], "Google Trust Services") + XCTAssertEqual(result["C"], "US") + } + + func testGetCertificateFromInvalidData() { + let result = viewModel.getCertificateValues(from: "") + XCTAssertEqual(result, [:]) + } + + func testGetCertificateValuesWithMissingValue() { + let data = "CN=www.google.com, O=, C=US" + let result = viewModel.getCertificateValues(from: data) + XCTAssertEqual(result["CN"], "www.google.com") + XCTAssertEqual(result["O"], "") + XCTAssertEqual(result["C"], "US") + } + + func testGetDNSNamesList() { + let input = #"DNSName("www.google.com"), DNSName("*www.google.com")"# + let result = viewModel.getDNSNamesList(from: input) + XCTAssertEqual(result, ["www.google.com", "*www.google.com"]) + } + + func testGetDNSNamesFromInvalidInput() { + let result = viewModel.getDNSNamesList(from: "") + XCTAssertEqual(result, []) + } +} From f8ef5f01abcd4bc622797c6091f2146403a63b2c Mon Sep 17 00:00:00 2001 From: Clare So <1740517+clarmso@users.noreply.github.com> Date: Thu, 29 Aug 2024 08:45:24 -0400 Subject: [PATCH 125/128] Refactor MTE-3341 Support iOS 18 for Focus XCUITest (#21671) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Ensure tests are compatible on iOS 18 * 🈳 Empty commit --- .../XCUITest/BrowsingTest.swift | 10 +++-- .../XCUITest/SettingTest.swift | 44 ++++++++++--------- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/focus-ios/focus-ios-tests/XCUITest/BrowsingTest.swift b/focus-ios/focus-ios-tests/XCUITest/BrowsingTest.swift index 376054cc6f99..6b54862c7cd7 100644 --- a/focus-ios/focus-ios-tests/XCUITest/BrowsingTest.swift +++ b/focus-ios/focus-ios-tests/XCUITest/BrowsingTest.swift @@ -31,10 +31,14 @@ class BrowsingTest: BaseTestCase { // Launch external app let RemindersApp: XCUIElement - if iPad() { - RemindersApp = app.collectionViews.scrollViews.cells.element(boundBy: 0) + if #available(iOS 17, *) { + RemindersApp = app.collectionViews.scrollViews.cells["Reminders"] } else { - RemindersApp = app.collectionViews.scrollViews.cells.element(boundBy: 1) + if iPad() { + RemindersApp = app.collectionViews.scrollViews.cells.element(boundBy: 0) + } else { + RemindersApp = app.collectionViews.scrollViews.cells.element(boundBy: 1) + } } waitForExistence(RemindersApp) waitForHittable(RemindersApp) diff --git a/focus-ios/focus-ios-tests/XCUITest/SettingTest.swift b/focus-ios/focus-ios-tests/XCUITest/SettingTest.swift index c53b36a453a6..50da58958fb1 100644 --- a/focus-ios/focus-ios-tests/XCUITest/SettingTest.swift +++ b/focus-ios/focus-ios-tests/XCUITest/SettingTest.swift @@ -254,28 +254,30 @@ class SettingTest: BaseTestCase { XCTAssertEqual(app.switches["BlockerToggle.Safari"].value! as! String, "0") iOS_Settings.activate() - waitForExistence(iOS_Settings.cells["Safari"]) - iOS_Settings.cells["Safari"].tap() - iOS_Settings.cells["AutoFill"].swipeUp() - if #available(iOS 15.0, *) { - iOS_Settings.cells.staticTexts["Extensions"].tap() - } else { - iOS_Settings.cells.staticTexts["CONTENT_BLOCKERS"].tap() + if #unavailable(iOS 18) { + waitForExistence(iOS_Settings.cells["Safari"]) + iOS_Settings.cells["Safari"].tap() + iOS_Settings.cells["AutoFill"].swipeUp() + if #available(iOS 15.0, *) { + iOS_Settings.cells.staticTexts["Extensions"].tap() + } else { + iOS_Settings.cells.staticTexts["CONTENT_BLOCKERS"].tap() + } + iOS_Settings.tables.cells.staticTexts["Firefox Focus"].tap() + iOS_Settings.tables.cells.switches.element(boundBy: 0).tap() + iOS_Settings.terminate() + + XCUIDevice.shared.press(.home) + // Let's be sure the app is backgrounded + _ = app.wait(for: XCUIApplication.State.runningBackground, timeout: 45) + let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard") + waitForExistence(springboard.icons["XCUITest-Runner"], timeout: 15) + + // Go back to the app to verify that the toggle has changed its value + app.activate() + waitForExistence(app.navigationBars["Settings"], timeout: 15) + XCTAssertEqual(app.switches["BlockerToggle.Safari"].value! as! String, "1") } - iOS_Settings.tables.cells.staticTexts["Firefox Focus"].tap() - iOS_Settings.tables.cells.switches.element(boundBy: 0).tap() - iOS_Settings.terminate() - - XCUIDevice.shared.press(.home) - // Let's be sure the app is backgrounded - _ = app.wait(for: XCUIApplication.State.runningBackground, timeout: 45) - let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard") - waitForExistence(springboard.icons["XCUITest-Runner"], timeout: 15) - - // Go back to the app to verify that the toggle has changed its value - app.activate() - waitForExistence(app.navigationBars["Settings"], timeout: 15) - XCTAssertEqual(app.switches["BlockerToggle.Safari"].value! as! String, "1") } func setUrlAutoCompleteTo(desiredAutoCompleteState: String) { From 81965bc37533470530daec0b2eeabcf47060a56d Mon Sep 17 00:00:00 2001 From: Winnie Teichmann <4530+thatswinnie@users.noreply.github.com> Date: Thu, 29 Aug 2024 14:59:45 +0100 Subject: [PATCH 126/128] Bugfix FXIOS-9842 [Toolbar redesign] Tapping outside the URL bar is not completely closing the keyboard (#21639) * End edit mode when keyboard gets dismissed * Remove unused delegates * Cancel edit mode if user scrolls homepage --- .../AddressToolbar/BrowserAddressToolbar.swift | 2 -- .../LocationView/LocationTextField.swift | 1 - .../AddressToolbar/LocationView/LocationView.swift | 4 ---- .../LocationView/LocationViewDelegate.swift | 3 --- .../Frontend/Home/HomepageViewController.swift | 13 +++++++++++++ 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/BrowserKit/Sources/ToolbarKit/AddressToolbar/BrowserAddressToolbar.swift b/BrowserKit/Sources/ToolbarKit/AddressToolbar/BrowserAddressToolbar.swift index 4b47d37bc953..cf21eafb72bc 100644 --- a/BrowserKit/Sources/ToolbarKit/AddressToolbar/BrowserAddressToolbar.swift +++ b/BrowserKit/Sources/ToolbarKit/AddressToolbar/BrowserAddressToolbar.swift @@ -277,8 +277,6 @@ public class BrowserAddressToolbar: UIView, AddressToolbar, ThemeApplicable, Loc toolbarDelegate?.addressToolbarAccessibilityActions() } - func locationViewDidCancelEditing() {} - // MARK: - ThemeApplicable public func applyTheme(theme: Theme) { backgroundColor = theme.colors.layer1 diff --git a/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationTextField.swift b/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationTextField.swift index 2fae2d17af09..2ea00227b2b4 100644 --- a/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationTextField.swift +++ b/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationTextField.swift @@ -11,7 +11,6 @@ protocol LocationTextFieldDelegate: AnyObject { func locationTextField(_ textField: LocationTextField, didEnterText text: String) func locationTextFieldShouldReturn(_ textField: LocationTextField) -> Bool func locationTextFieldShouldClear(_ textField: LocationTextField) -> Bool - func locationTextFieldDidCancel(_ textField: LocationTextField) func locationPasteAndGo(_ textField: LocationTextField) func locationTextFieldDidBeginEditing(_ textField: UITextField) func locationTextFieldDidEndEditing(_ textField: UITextField) diff --git a/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationView.swift b/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationView.swift index 6a54a46c04de..bb71dcb4ab76 100644 --- a/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationView.swift +++ b/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationView.swift @@ -354,10 +354,6 @@ final class LocationView: UIView, LocationTextFieldDelegate, ThemeApplicable, Ac return true } - func locationTextFieldDidCancel(_ textField: LocationTextField) { - delegate?.locationViewDidCancelEditing() - } - func locationPasteAndGo(_ textField: LocationTextField) { if let pasteboardContents = UIPasteboard.general.string { delegate?.locationViewDidSubmitText(pasteboardContents) diff --git a/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationViewDelegate.swift b/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationViewDelegate.swift index e78e8cd8354a..bf2670dbb614 100644 --- a/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationViewDelegate.swift +++ b/BrowserKit/Sources/ToolbarKit/AddressToolbar/LocationView/LocationViewDelegate.swift @@ -28,7 +28,4 @@ protocol LocationViewDelegate: AnyObject { /// - Returns: An optional array of `UIAccessibilityCustomAction` objects. /// Return `nil` if no custom actions are provided. func locationViewAccessibilityActions() -> [UIAccessibilityCustomAction]? - - /// Called when the user cancels entering text into the location view. - func locationViewDidCancelEditing() } diff --git a/firefox-ios/Client/Frontend/Home/HomepageViewController.swift b/firefox-ios/Client/Frontend/Home/HomepageViewController.swift index b4645040d0ae..282fd9fb4e0f 100644 --- a/firefox-ios/Client/Frontend/Home/HomepageViewController.swift +++ b/firefox-ios/Client/Frontend/Home/HomepageViewController.swift @@ -365,6 +365,10 @@ class HomepageViewController: private func dismissKeyboard() { if currentTab?.lastKnownUrl?.absoluteString.hasPrefix("internal://") ?? false { overlayManager.cancelEditing(shouldCancelLoading: false) + + let action = ToolbarMiddlewareAction(windowUUID: windowUUID, + actionType: ToolbarMiddlewareActionType.cancelEdit) + store.dispatch(action) } } @@ -381,6 +385,15 @@ class HomepageViewController: theme: theme) } + // Only dispatch action when user is in edit mode to avoid having the toolbar re-displayed + if featureFlags.isFeatureEnabled(.toolbarRefactor, checking: .buildOnly), + let toolbarState = store.state.screenState(ToolbarState.self, for: .toolbar, window: windowUUID), + toolbarState.addressToolbar.isEditing { + let action = ToolbarMiddlewareAction(windowUUID: windowUUID, + actionType: ToolbarMiddlewareActionType.cancelEdit) + store.dispatch(action) + } + let scrolledToTop = lastContentOffsetY > 0 && scrollView.contentOffset.y <= 0 let scrolledDown = lastContentOffsetY == 0 && scrollView.contentOffset.y > 0 From c266fef9f8f9db4905a8f5d57679e4ba7a5250b0 Mon Sep 17 00:00:00 2001 From: "roux g. buciu" <11182210+adudenamedruby@users.noreply.github.com> Date: Thu, 29 Aug 2024 10:56:15 -0400 Subject: [PATCH 127/128] Fix comments (#21681) --- firefox-ios/Client/Frontend/Strings.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firefox-ios/Client/Frontend/Strings.swift b/firefox-ios/Client/Frontend/Strings.swift index 43da339897c9..7b684805d4dc 100644 --- a/firefox-ios/Client/Frontend/Strings.swift +++ b/firefox-ios/Client/Frontend/Strings.swift @@ -3900,7 +3900,7 @@ extension String { public static let FindInPage = MZLocalizedString( key: "MainMenu.ToolsSection.FindInPage.Title.v131", tableName: "MainMenu", - value: "Find in Page...", + value: "Find in Page…", comment: "On the main menu, the title for the action that will bring up the Search menu, so the user can search for a word or a pharse on the current page.") public static let Tools = MZLocalizedString( key: "MainMenu.ToolsSection.ToolsSubmenu.Title.v131", @@ -4039,7 +4039,7 @@ extension String { key: "MainMenu.Submenus.Save.BookmarkThisPage.Title.v131", tableName: "MainMenu", value: "Bookmark This Page", - comment: "On the main menu, in the tools submenu, the title for the menu component that indicates the current zoom level. Placeholder is for the current zoom level percentage. ") + comment: "On the main menu, in the Save submenu, the title for the menu component that allows a user to save a bookmark for this particular page..") public static let BookmarkThisPageSubtitle = MZLocalizedString( key: "MainMenu.Submenus.Save.BookmarkThisPage.Subtitle.v131", tableName: "MainMenu", From eb617dc64acd0c404705c54f58d9eeb7d82b139e Mon Sep 17 00:00:00 2001 From: Isabella Date: Thu, 29 Aug 2024 09:21:33 -0600 Subject: [PATCH 128/128] Bugfix FXIOS-9667 Reduce latency loading favicons (#21405) * Update suggested top sites model and hard code favicon URLs. * Remove code related to loading bundled favicons. * Delete TopSites bundled favicon assets (1.2 MB save). * Use the faviconURL for the pinned Google site and DefaultSuggestedSites so a heavy call to fetch the faviconURL is not necessary on first launch. * Make the Google pinned site have a hard coded favicon URL to reduce latency before URL cache is populated (first launch). * Don't cache empty favicon URLs. * Refactoring. * Documentation update. * Delete tests and mocks using the removed DefaultBundleImageFetcher. Update tests using new PinnedSite init. --- .../FaviconURLHandler.swift | 3 + .../BundleDataProvider.swift | 49 - .../BundleImageFetcher.swift | 137 -- .../ImageProcessing/ImageHandler.swift | 24 +- .../SiteImageView/SiteImageHandler.swift | 16 +- .../BundleImageFetcherTests.swift | 189 --- .../ImageProcessing/ImageHandlerTests.swift | 55 +- firefox-ios/Client.xcodeproj/project.pbxproj | 8 - firefox-ios/Client/Assets/TopSites/aa-com.png | Bin 3635 -> 0 bytes .../Client/Assets/TopSites/abcnews-go-com.png | Bin 12428 -> 0 bytes .../Client/Assets/TopSites/about-com.png | Bin 4055 -> 0 bytes .../Assets/TopSites/accuweather-com.png | Bin 3380 -> 0 bytes .../Client/Assets/TopSites/adobe-com.png | Bin 2184 -> 0 bytes .../Client/Assets/TopSites/adp-com.png | Bin 2513 -> 0 bytes .../Client/Assets/TopSites/airbnb-com.png | Bin 3757 -> 0 bytes .../Client/Assets/TopSites/allrecipes-com.png | Bin 5060 -> 0 bytes .../Client/Assets/TopSites/amazon-com.png | Bin 7169 -> 0 bytes .../Client/Assets/TopSites/amazonaws-com.png | Bin 3984 -> 0 bytes .../Assets/TopSites/americanexpress-com.png | Bin 4734 -> 0 bytes .../Client/Assets/TopSites/ancestry-com.png | Bin 3424 -> 0 bytes .../Client/Assets/TopSites/answers-com.png | Bin 3017 -> 0 bytes .../Client/Assets/TopSites/aol-com.png | Bin 9096 -> 0 bytes .../Client/Assets/TopSites/apple-com.png | Bin 2241 -> 0 bytes .../Client/Assets/TopSites/ask-com.png | Bin 5997 -> 0 bytes .../Client/Assets/TopSites/att-com.png | Bin 27266 -> 0 bytes .../Client/Assets/TopSites/baidu-com.png | Bin 3287 -> 0 bytes .../Assets/TopSites/bankofamerica-com.png | Bin 2781 -> 0 bytes .../Client/Assets/TopSites/bbc-com.png | Bin 1542 -> 0 bytes .../Client/Assets/TopSites/bestbuy-com.png | Bin 8167 -> 0 bytes .../Client/Assets/TopSites/bing-com.png | Bin 2307 -> 0 bytes .../Client/Assets/TopSites/blackboard-com.png | Bin 1248 -> 0 bytes .../Assets/TopSites/bleacherreport-com.png | Bin 2039 -> 0 bytes .../Client/Assets/TopSites/blogger-com.png | Bin 1943 -> 0 bytes .../Client/Assets/TopSites/box-com.png | Bin 2653 -> 0 bytes .../Assets/TopSites/businessinsider-com.png | Bin 3616 -> 0 bytes .../Client/Assets/TopSites/buzzfeed-com.png | Bin 2887 -> 0 bytes .../Client/Assets/TopSites/buzzlie-com.png | Bin 8033 -> 0 bytes firefox-ios/Client/Assets/TopSites/ca-gov.png | Bin 14382 -> 0 bytes .../Client/Assets/TopSites/capitalone-com.png | Bin 7900 -> 0 bytes .../Client/Assets/TopSites/cbsnews-com.png | Bin 4527 -> 0 bytes .../Client/Assets/TopSites/cbssports-com.png | Bin 5348 -> 0 bytes .../Client/Assets/TopSites/chase-com.png | Bin 2024 -> 0 bytes .../Client/Assets/TopSites/citi-com.png | Bin 7050 -> 0 bytes .../Client/Assets/TopSites/cnet-com.png | Bin 3449 -> 0 bytes .../Client/Assets/TopSites/cnn-com.png | Bin 3050 -> 0 bytes .../TopSites/conservativetribune-com.png | Bin 8064 -> 0 bytes .../Client/Assets/TopSites/costco-com.png | Bin 2810 -> 0 bytes .../Client/Assets/TopSites/craigslist-org.png | Bin 3639 -> 0 bytes .../Client/Assets/TopSites/dailybeast-com.png | Bin 3035 -> 0 bytes .../Assets/TopSites/dailymail-co-uk.png | Bin 704 -> 0 bytes .../Client/Assets/TopSites/delta-com.png | Bin 2147 -> 0 bytes .../Client/Assets/TopSites/deviantart-com.png | Bin 1048 -> 0 bytes .../Client/Assets/TopSites/digg-com.png | Bin 1407 -> 0 bytes .../Client/Assets/TopSites/diply-com.png | Bin 1841 -> 0 bytes .../Assets/TopSites/discovercard-com.png | Bin 6251 -> 0 bytes .../Client/Assets/TopSites/dropbox-com.png | Bin 3406 -> 0 bytes .../Assets/TopSites/drudgereport-com.png | Bin 5752 -> 0 bytes .../Client/Assets/TopSites/ebates-com.png | Bin 7035 -> 0 bytes .../Client/Assets/TopSites/ebay-com.png | Bin 929 -> 0 bytes .../Client/Assets/TopSites/espn-go-com.png | Bin 1521 -> 0 bytes .../Client/Assets/TopSites/etsy-com.png | Bin 1928 -> 0 bytes .../Client/Assets/TopSites/eventbrite-com.png | Bin 2281 -> 0 bytes .../Client/Assets/TopSites/facebook-com.png | Bin 2689 -> 0 bytes .../Client/Assets/TopSites/faithtap-com.png | Bin 3536 -> 0 bytes .../Client/Assets/TopSites/fedex-com.png | Bin 1830 -> 0 bytes .../Client/Assets/TopSites/feedly-com.png | Bin 1802 -> 0 bytes .../Client/Assets/TopSites/fitbit-com.png | Bin 2903 -> 0 bytes .../Client/Assets/TopSites/flickr-com.png | Bin 1832 -> 0 bytes .../Assets/TopSites/foodnetwork-com.png | Bin 3889 -> 0 bytes .../Client/Assets/TopSites/forbes-com.png | Bin 1850 -> 0 bytes .../Client/Assets/TopSites/foxnews-com.png | Bin 4308 -> 0 bytes .../Client/Assets/TopSites/gap-com.png | Bin 1780 -> 0 bytes .../Client/Assets/TopSites/gawker-com.png | Bin 2768 -> 0 bytes .../Client/Assets/TopSites/gfycat-com.png | Bin 2950 -> 0 bytes .../Client/Assets/TopSites/github-com.png | Bin 3917 -> 0 bytes .../Client/Assets/TopSites/gizmodo-com.png | Bin 3139 -> 0 bytes .../Client/Assets/TopSites/glassdoor-com.png | Bin 1722 -> 0 bytes firefox-ios/Client/Assets/TopSites/go-com.png | Bin 2989 -> 0 bytes .../Client/Assets/TopSites/goodreads-com.png | Bin 2735 -> 0 bytes .../Client/Assets/TopSites/google-admin.png | Bin 6411 -> 0 bytes .../Assets/TopSites/google-calendar.png | Bin 3822 -> 0 bytes .../Client/Assets/TopSites/google-com.png | Bin 6524 -> 0 bytes .../Assets/TopSites/google-contacts.png | Bin 4547 -> 0 bytes .../Client/Assets/TopSites/google-docs.png | Bin 2447 -> 0 bytes .../Client/Assets/TopSites/google-drive.png | Bin 5655 -> 0 bytes .../Client/Assets/TopSites/google-forms.png | Bin 2743 -> 0 bytes .../Client/Assets/TopSites/google-gmail.png | Bin 4795 -> 0 bytes .../Client/Assets/TopSites/google-groups.png | Bin 5025 -> 0 bytes .../Assets/TopSites/google-hangouts.png | Bin 5445 -> 0 bytes .../Client/Assets/TopSites/google-photos.png | Bin 7428 -> 0 bytes .../Client/Assets/TopSites/google-plus.png | Bin 8426 -> 0 bytes .../Client/Assets/TopSites/google-sheets.png | Bin 2636 -> 0 bytes .../Client/Assets/TopSites/google-sites.png | Bin 2865 -> 0 bytes .../Client/Assets/TopSites/google-slides.png | Bin 2471 -> 0 bytes .../Client/Assets/TopSites/groupon-com.png | Bin 2556 -> 0 bytes .../Client/Assets/TopSites/homedepot-com.png | Bin 7838 -> 0 bytes .../Client/Assets/TopSites/houzz-com.png | Bin 1510 -> 0 bytes .../Assets/TopSites/huffingtonpost-com.png | Bin 11004 -> 0 bytes .../Client/Assets/TopSites/hulu-com.png | Bin 798 -> 0 bytes .../Client/Assets/TopSites/ign-com.png | Bin 4330 -> 0 bytes .../Client/Assets/TopSites/ikea-com.png | Bin 1890 -> 0 bytes .../Assets/TopSites/images-google-com.png | Bin 1872 -> 0 bytes .../Client/Assets/TopSites/imdb-com.png | Bin 1714 -> 0 bytes .../Client/Assets/TopSites/imgur-com.png | Bin 2636 -> 0 bytes .../Client/Assets/TopSites/instagram-com.png | Bin 1874 -> 0 bytes .../Assets/TopSites/instructure-com.png | Bin 147 -> 0 bytes .../Client/Assets/TopSites/intuit-com.png | Bin 1194 -> 0 bytes .../Client/Assets/TopSites/invision-com.png | Bin 2241 -> 0 bytes .../Client/Assets/TopSites/irs-gov.png | Bin 5626 -> 0 bytes .../Client/Assets/TopSites/jcpenney-com.png | Bin 720 -> 0 bytes firefox-ios/Client/Assets/TopSites/jd-com.png | Bin 14747 -> 0 bytes .../Client/Assets/TopSites/kayak-com.png | Bin 8930 -> 0 bytes .../Client/Assets/TopSites/kohls-com.png | Bin 1541 -> 0 bytes .../Client/Assets/TopSites/latimes-com.png | Bin 2573 -> 0 bytes .../Client/Assets/TopSites/lifehacker-com.png | Bin 1447 -> 0 bytes .../Client/Assets/TopSites/linkedin-com.png | Bin 1377 -> 0 bytes .../Client/Assets/TopSites/live-com.png | Bin 2417 -> 0 bytes .../Client/Assets/TopSites/lowes-com.png | Bin 1551 -> 0 bytes .../Client/Assets/TopSites/macys-com.png | Bin 2087 -> 0 bytes .../Client/Assets/TopSites/mapquest-com.png | Bin 2036 -> 0 bytes .../Client/Assets/TopSites/mashable-com.png | Bin 1367 -> 0 bytes .../Client/Assets/TopSites/microsoft-com.png | Bin 198 -> 0 bytes .../Assets/TopSites/microsoftonline-com.png | Bin 1695 -> 0 bytes .../Client/Assets/TopSites/mlb-com.png | Bin 1967 -> 0 bytes .../Client/Assets/TopSites/mozilla-com.png | Bin 2393 -> 0 bytes .../Client/Assets/TopSites/msn-com.png | Bin 2663 -> 0 bytes .../Client/Assets/TopSites/nbcnews-com.png | Bin 5411 -> 0 bytes .../Client/Assets/TopSites/netflix-com.png | Bin 1270 -> 0 bytes .../Client/Assets/TopSites/newegg-com.png | Bin 9775 -> 0 bytes .../Assets/TopSites/news-ycombinator-com.png | Bin 3964 -> 0 bytes .../Client/Assets/TopSites/nih-gov.png | Bin 1853 -> 0 bytes .../Client/Assets/TopSites/nordstrom-com.png | Bin 2367 -> 0 bytes .../Client/Assets/TopSites/npr-org.png | Bin 1077 -> 0 bytes .../Client/Assets/TopSites/nypost-com.png | Bin 9952 -> 0 bytes .../Client/Assets/TopSites/nytimes-com.png | Bin 3084 -> 0 bytes .../Client/Assets/TopSites/office-com.png | Bin 1709 -> 0 bytes .../Client/Assets/TopSites/overstock-com.png | Bin 11228 -> 0 bytes .../Client/Assets/TopSites/pandora-com.png | Bin 1924 -> 0 bytes .../Client/Assets/TopSites/patch-com.png | Bin 3704 -> 0 bytes .../Client/Assets/TopSites/paypal-com.png | Bin 2512 -> 0 bytes .../Client/Assets/TopSites/people-com.png | Bin 2347 -> 0 bytes .../Client/Assets/TopSites/pinterest-com.png | Bin 2941 -> 0 bytes .../Client/Assets/TopSites/politico-com.png | Bin 1278 -> 0 bytes firefox-ios/Client/Assets/TopSites/qq-com.png | Bin 3259 -> 0 bytes .../Client/Assets/TopSites/quora-com.png | Bin 3062 -> 0 bytes .../Client/Assets/TopSites/realtor-com.png | Bin 8979 -> 0 bytes .../Client/Assets/TopSites/reddit-com.png | Bin 5328 -> 0 bytes .../Client/Assets/TopSites/salesforce-com.png | Bin 4191 -> 0 bytes .../Client/Assets/TopSites/sears-com.png | Bin 2833 -> 0 bytes .../Client/Assets/TopSites/sina-com.png | Bin 3207 -> 0 bytes .../Client/Assets/TopSites/slate-com.png | Bin 3120 -> 0 bytes .../Client/Assets/TopSites/slickdeals-net.png | Bin 3322 -> 0 bytes .../Client/Assets/TopSites/soundcloud-com.png | Bin 2836 -> 0 bytes .../Client/Assets/TopSites/southwest-com.png | Bin 5283 -> 0 bytes .../Client/Assets/TopSites/spotify-com.png | Bin 2856 -> 0 bytes .../Assets/TopSites/stackexchange-com.png | Bin 6432 -> 0 bytes .../Assets/TopSites/stackoverflow-com.png | Bin 2528 -> 0 bytes .../Client/Assets/TopSites/staples-com.png | Bin 21013 -> 0 bytes .../Client/Assets/TopSites/strava-com.png | Bin 2176 -> 0 bytes .../Assets/TopSites/surveymonkey-com.png | Bin 2327 -> 0 bytes .../Client/Assets/TopSites/swagbucks-com.png | Bin 2947 -> 0 bytes .../Client/Assets/TopSites/t-mobile-com.png | Bin 1756 -> 0 bytes .../Client/Assets/TopSites/taboola-com.png | Bin 2824 -> 0 bytes .../Assets/TopSites/talkingpointsmemo-com.png | Bin 3814 -> 0 bytes .../Client/Assets/TopSites/taobao-com.png | Bin 3268 -> 0 bytes .../Client/Assets/TopSites/target-com.png | Bin 2809 -> 0 bytes .../Assets/TopSites/thedailybeast-com.png | Bin 6786 -> 0 bytes .../Assets/TopSites/theguardian-com.png | Bin 2569 -> 0 bytes .../Client/Assets/TopSites/thesaurus-com.png | Bin 5746 -> 0 bytes .../Assets/TopSites/ticketmaster-com.png | Bin 7024 -> 0 bytes .../Assets/TopSites/tripadvisor-com.png | Bin 4938 -> 0 bytes .../Client/Assets/TopSites/trulia-com.png | Bin 2062 -> 0 bytes .../Client/Assets/TopSites/tumblr-com.png | Bin 1274 -> 0 bytes .../Client/Assets/TopSites/twitch-tv.png | Bin 975 -> 0 bytes .../Client/Assets/TopSites/twitter-com.png | Bin 6108 -> 0 bytes .../Client/Assets/TopSites/ups-com.png | Bin 3244 -> 0 bytes .../Client/Assets/TopSites/usaa-com.png | Bin 4880 -> 0 bytes .../Client/Assets/TopSites/usatoday-com.png | Bin 1415 -> 0 bytes .../Client/Assets/TopSites/usbank-com.png | Bin 2253 -> 0 bytes .../Client/Assets/TopSites/usps-com.png | Bin 2591 -> 0 bytes .../Client/Assets/TopSites/verizon-com.png | Bin 1887 -> 0 bytes .../Assets/TopSites/verizonwireless-com.png | Bin 1967 -> 0 bytes .../Client/Assets/TopSites/vice-com.png | Bin 2247 -> 0 bytes .../Client/Assets/TopSites/vimeo-com.png | Bin 2441 -> 0 bytes .../Client/Assets/TopSites/walmart-com.png | Bin 2267 -> 0 bytes .../Assets/TopSites/washingtonpost-com.png | Bin 3148 -> 0 bytes .../Client/Assets/TopSites/wayfair-com.png | Bin 17859 -> 0 bytes .../Client/Assets/TopSites/weather-com.png | Bin 3413 -> 0 bytes .../Client/Assets/TopSites/webmd-com.png | Bin 4884 -> 0 bytes .../Client/Assets/TopSites/wellsfargo-com.png | Bin 1932 -> 0 bytes .../Client/Assets/TopSites/wikia-com.png | Bin 2512 -> 0 bytes .../Client/Assets/TopSites/wikihow-com.png | Bin 3031 -> 0 bytes .../Client/Assets/TopSites/wikipedia-org.png | Bin 2597 -> 0 bytes .../Client/Assets/TopSites/wired-com.png | Bin 4603 -> 0 bytes .../Client/Assets/TopSites/wittyfeed-com.png | Bin 3402 -> 0 bytes .../Client/Assets/TopSites/wordpress-com.png | Bin 4149 -> 0 bytes .../Client/Assets/TopSites/wsj-com.png | Bin 3239 -> 0 bytes .../Assets/TopSites/wunderground-com.png | Bin 9949 -> 0 bytes .../Client/Assets/TopSites/xfinity-com.png | Bin 2336 -> 0 bytes .../Client/Assets/TopSites/yahoo-com.png | Bin 2266 -> 0 bytes .../Client/Assets/TopSites/yelp-com.png | Bin 2705 -> 0 bytes .../Client/Assets/TopSites/youtube-com.png | Bin 1470 -> 0 bytes .../Client/Assets/TopSites/zillow-com.png | Bin 2234 -> 0 bytes firefox-ios/Client/Assets/bundle_sites.json | 1387 ----------------- .../Home/TopSites/Cell/TopSiteItemCell.swift | 8 +- .../DataManagement/GoogleTopSiteManager.swift | 18 +- .../Frontend/Home/TopSites/PinnedSite.swift | 4 +- firefox-ios/Client/TabManagement/Tab.swift | 4 +- firefox-ios/Providers/TopSitesProvider.swift | 2 +- .../Storage/DefaultSuggestedSites.swift | 50 +- firefox-ios/Storage/SuggestedSites.swift | 5 +- .../Browser/TopSitesHelperTests.swift | 17 +- .../TopSites/TopSitesDataAdaptorTests.swift | 2 +- 213 files changed, 78 insertions(+), 1900 deletions(-) delete mode 100644 BrowserKit/Sources/SiteImageView/ImageProcessing/BundleImageFetcher/BundleDataProvider.swift delete mode 100644 BrowserKit/Sources/SiteImageView/ImageProcessing/BundleImageFetcher/BundleImageFetcher.swift delete mode 100644 BrowserKit/Tests/SiteImageViewTests/ImageProcessing/BundleImageFetcherTests.swift delete mode 100755 firefox-ios/Client/Assets/TopSites/aa-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/abcnews-go-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/about-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/accuweather-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/adobe-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/adp-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/airbnb-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/allrecipes-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/amazon-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/amazonaws-com.png delete mode 100644 firefox-ios/Client/Assets/TopSites/americanexpress-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/ancestry-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/answers-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/aol-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/apple-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/ask-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/att-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/baidu-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/bankofamerica-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/bbc-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/bestbuy-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/bing-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/blackboard-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/bleacherreport-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/blogger-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/box-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/businessinsider-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/buzzfeed-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/buzzlie-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/ca-gov.png delete mode 100755 firefox-ios/Client/Assets/TopSites/capitalone-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/cbsnews-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/cbssports-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/chase-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/citi-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/cnet-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/cnn-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/conservativetribune-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/costco-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/craigslist-org.png delete mode 100755 firefox-ios/Client/Assets/TopSites/dailybeast-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/dailymail-co-uk.png delete mode 100755 firefox-ios/Client/Assets/TopSites/delta-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/deviantart-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/digg-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/diply-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/discovercard-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/dropbox-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/drudgereport-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/ebates-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/ebay-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/espn-go-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/etsy-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/eventbrite-com.png delete mode 100644 firefox-ios/Client/Assets/TopSites/facebook-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/faithtap-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/fedex-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/feedly-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/fitbit-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/flickr-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/foodnetwork-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/forbes-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/foxnews-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/gap-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/gawker-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/gfycat-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/github-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/gizmodo-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/glassdoor-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/go-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/goodreads-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/google-admin.png delete mode 100755 firefox-ios/Client/Assets/TopSites/google-calendar.png delete mode 100755 firefox-ios/Client/Assets/TopSites/google-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/google-contacts.png delete mode 100755 firefox-ios/Client/Assets/TopSites/google-docs.png delete mode 100755 firefox-ios/Client/Assets/TopSites/google-drive.png delete mode 100755 firefox-ios/Client/Assets/TopSites/google-forms.png delete mode 100755 firefox-ios/Client/Assets/TopSites/google-gmail.png delete mode 100755 firefox-ios/Client/Assets/TopSites/google-groups.png delete mode 100755 firefox-ios/Client/Assets/TopSites/google-hangouts.png delete mode 100755 firefox-ios/Client/Assets/TopSites/google-photos.png delete mode 100755 firefox-ios/Client/Assets/TopSites/google-plus.png delete mode 100755 firefox-ios/Client/Assets/TopSites/google-sheets.png delete mode 100755 firefox-ios/Client/Assets/TopSites/google-sites.png delete mode 100755 firefox-ios/Client/Assets/TopSites/google-slides.png delete mode 100755 firefox-ios/Client/Assets/TopSites/groupon-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/homedepot-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/houzz-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/huffingtonpost-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/hulu-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/ign-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/ikea-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/images-google-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/imdb-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/imgur-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/instagram-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/instructure-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/intuit-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/invision-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/irs-gov.png delete mode 100755 firefox-ios/Client/Assets/TopSites/jcpenney-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/jd-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/kayak-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/kohls-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/latimes-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/lifehacker-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/linkedin-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/live-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/lowes-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/macys-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/mapquest-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/mashable-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/microsoft-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/microsoftonline-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/mlb-com.png delete mode 100644 firefox-ios/Client/Assets/TopSites/mozilla-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/msn-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/nbcnews-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/netflix-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/newegg-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/news-ycombinator-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/nih-gov.png delete mode 100755 firefox-ios/Client/Assets/TopSites/nordstrom-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/npr-org.png delete mode 100755 firefox-ios/Client/Assets/TopSites/nypost-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/nytimes-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/office-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/overstock-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/pandora-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/patch-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/paypal-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/people-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/pinterest-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/politico-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/qq-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/quora-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/realtor-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/reddit-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/salesforce-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/sears-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/sina-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/slate-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/slickdeals-net.png delete mode 100755 firefox-ios/Client/Assets/TopSites/soundcloud-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/southwest-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/spotify-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/stackexchange-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/stackoverflow-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/staples-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/strava-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/surveymonkey-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/swagbucks-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/t-mobile-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/taboola-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/talkingpointsmemo-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/taobao-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/target-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/thedailybeast-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/theguardian-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/thesaurus-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/ticketmaster-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/tripadvisor-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/trulia-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/tumblr-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/twitch-tv.png delete mode 100644 firefox-ios/Client/Assets/TopSites/twitter-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/ups-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/usaa-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/usatoday-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/usbank-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/usps-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/verizon-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/verizonwireless-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/vice-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/vimeo-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/walmart-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/washingtonpost-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/wayfair-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/weather-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/webmd-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/wellsfargo-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/wikia-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/wikihow-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/wikipedia-org.png delete mode 100755 firefox-ios/Client/Assets/TopSites/wired-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/wittyfeed-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/wordpress-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/wsj-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/wunderground-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/xfinity-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/yahoo-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/yelp-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/youtube-com.png delete mode 100755 firefox-ios/Client/Assets/TopSites/zillow-com.png delete mode 100755 firefox-ios/Client/Assets/bundle_sites.json diff --git a/BrowserKit/Sources/SiteImageView/FaviconURLProcessing/FaviconURLHandler.swift b/BrowserKit/Sources/SiteImageView/FaviconURLProcessing/FaviconURLHandler.swift index 25dced3f87c9..356f9d1193c3 100644 --- a/BrowserKit/Sources/SiteImageView/FaviconURLProcessing/FaviconURLHandler.swift +++ b/BrowserKit/Sources/SiteImageView/FaviconURLProcessing/FaviconURLHandler.swift @@ -20,6 +20,9 @@ struct DefaultFaviconURLHandler: FaviconURLHandler { self.urlCache = urlCache } + /// Attempts to get the favicon URL associated with this site. First checks the URL cache. If the URL can't be obtained + /// from the cache, then a network request is made to hopefully scrape the favicon URL from a webpage's metadata. + /// **Note**: This is a slow call when the URL is not cached. func getFaviconURL(site: SiteImageModel) async throws -> SiteImageModel { // Don't fetch favicon URL if we don't have a URL or domain for it guard let siteURL = site.siteURL else { diff --git a/BrowserKit/Sources/SiteImageView/ImageProcessing/BundleImageFetcher/BundleDataProvider.swift b/BrowserKit/Sources/SiteImageView/ImageProcessing/BundleImageFetcher/BundleDataProvider.swift deleted file mode 100644 index 2ccdfc571081..000000000000 --- a/BrowserKit/Sources/SiteImageView/ImageProcessing/BundleImageFetcher/BundleDataProvider.swift +++ /dev/null @@ -1,49 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/ - -import UIKit - -protocol BundleDataProvider { - func getBundleData() throws -> Data - - func getPath(from path: String) -> String? - - func getBundleImage(from path: String) -> UIImage? -} - -class DefaultBundleDataProvider: BundleDataProvider { - enum BundleDataError: Error { - case noPath - } - - func getBundleData() throws -> Data { - guard let path = bundle.path(forResource: "bundle_sites", ofType: "json") else { - throw BundleDataError.noPath - } - - return try Data(contentsOf: URL(fileURLWithPath: path)) - } - - func getPath(from path: String) -> String? { - return Bundle.main.path(forResource: "TopSites/" + path, ofType: "png") - } - - func getBundleImage(from path: String) -> UIImage? { - return UIImage(contentsOfFile: path) - } - - private var bundle: Bundle { - var bundle = Bundle.main - // Allows us to access bundle from extensions - // Taken from: https://stackoverflow.com/questions/26189060/get-the-main-app-bundle-from-within-extension - if bundle.bundleURL.pathExtension == "appex" { - // Peel off two directory levels - MY_APP.app/PlugIns/MY_APP_EXTENSION.appex - let url = bundle.bundleURL.deletingLastPathComponent().deletingLastPathComponent() - if let otherBundle = Bundle(url: url) { - bundle = otherBundle - } - } - return bundle - } -} diff --git a/BrowserKit/Sources/SiteImageView/ImageProcessing/BundleImageFetcher/BundleImageFetcher.swift b/BrowserKit/Sources/SiteImageView/ImageProcessing/BundleImageFetcher/BundleImageFetcher.swift deleted file mode 100644 index b52b854656f0..000000000000 --- a/BrowserKit/Sources/SiteImageView/ImageProcessing/BundleImageFetcher/BundleImageFetcher.swift +++ /dev/null @@ -1,137 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/ - -import UIKit -import Common - -protocol BundleImageFetcher { - /// Fetches from the bundle - /// - Parameter domain: The domain to fetch the image with from the bundle - /// - Returns: The image or throw an error if it fails - func getImageFromBundle(domain: ImageDomain?) throws -> UIImage -} - -class DefaultBundleImageFetcher: BundleImageFetcher { - private struct BundledImage: Codable { - var title: String - var url: String? - var image_url: String - var background_color: String - var domain: String - } - - private struct FormattedBundledImage { - var backgroundColor: UIColor - var filePath: String - var title: String - } - - private let bundleDataProvider: BundleDataProvider - private static var staticBundledImages = [String: FormattedBundledImage]() - private var bundledImages: [String: FormattedBundledImage] { - DefaultBundleImageFetcher.staticBundledImages - } - private var logger: Logger - - init(bundleDataProvider: BundleDataProvider = DefaultBundleDataProvider(), - logger: Logger = DefaultLogger.shared) { - self.bundleDataProvider = bundleDataProvider - self.logger = logger - // This is a heavy lift so we only want to fetch once, so we store in a static var - if bundledImages.isEmpty { - DefaultBundleImageFetcher.staticBundledImages = retrieveBundledImages() - } - } - - func getImageFromBundle(domain: ImageDomain?) throws -> UIImage { - guard let domain = domain, - let bundleDomain = getBundleDomain(domain: domain) - else { - throw SiteImageError.noImageInBundle - } - - guard let bundledImage = bundledImages[bundleDomain], - let image = bundleDataProvider.getBundleImage(from: bundledImage.filePath) - else { - throw SiteImageError.noImageInBundle - } - - let color = bundledImage.backgroundColor.cgColor.alpha < 0.01 ? UIColor.white : bundledImage.backgroundColor - return withBackgroundAndPadding(image: image, color: color) - } - - // MARK: - Private - - private func getBundleDomain(domain: ImageDomain) -> String? { - return domain.bundleDomains.first(where: { bundledImages[$0] != nil }) - } - - private func retrieveBundledImages() -> [String: FormattedBundledImage] { - do { - let data = try bundleDataProvider.getBundleData() - return decode(from: data) - } catch { - return [:] - } - } - - private func decode(from data: Data) -> [String: FormattedBundledImage] { - let decoder = JSONDecoder() - var icons = [String: FormattedBundledImage]() - - do { - let decodedImages = try decoder.decode([BundledImage].self, from: data) - for decodedImage in decodedImages { - guard let image = format(image: decodedImage) else { - continue - } - - icons[image.title] = image - } - - return icons - } catch { - return icons - } - } - - private func format(image: BundledImage) -> FormattedBundledImage? { - let path = image.image_url.replacingOccurrences(of: ".png", with: "") - let title = image.title - let color = image.background_color - let filePath = bundleDataProvider.getPath(from: path) - guard let filePath = filePath else { - return nil - } - - var backgroundColor: UIColor - if color == "#fff" || color == "#FFF" { - backgroundColor = UIColor.clear - } else { - backgroundColor = UIColor(colorString: color.replacingOccurrences(of: "#", with: "")) - } - - return FormattedBundledImage(backgroundColor: backgroundColor, - filePath: filePath, - title: title) - } - - private func withBackgroundAndPadding(image: UIImage, color: UIColor, opaque: Bool = true) -> UIImage { - UIGraphicsBeginImageContextWithOptions(image.size, opaque, image.scale) - - guard let ctx = UIGraphicsGetCurrentContext(), let cgImage = image.cgImage else { return image } - defer { UIGraphicsEndImageContext() } - - // Pad the image in a bit to make the favicons look better - let newSize = CGSize(width: image.size.width - 20, height: image.size.height - 20) - let rect = CGRect(origin: .zero, size: image.size) - let imageRect = CGRect(origin: CGPoint(x: 10, y: 10), size: newSize) - ctx.setFillColor(color.cgColor) - ctx.fill(rect) - ctx.concatenate(CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: image.size.height)) - ctx.draw(cgImage, in: imageRect) - - return UIGraphicsGetImageFromCurrentImageContext() ?? image - } -} diff --git a/BrowserKit/Sources/SiteImageView/ImageProcessing/ImageHandler.swift b/BrowserKit/Sources/SiteImageView/ImageProcessing/ImageHandler.swift index c198eb16c98d..c89498508284 100644 --- a/BrowserKit/Sources/SiteImageView/ImageProcessing/ImageHandler.swift +++ b/BrowserKit/Sources/SiteImageView/ImageProcessing/ImageHandler.swift @@ -6,11 +6,10 @@ import UIKit protocol ImageHandler { /// The ImageHandler will fetch the favicon with the following precedence: - /// 1. Tries to fetch from the bundle. - /// 2. Tries to fetch from the cache. - /// 3. Tries to fetch from the favicon fetcher (from the web) if there's a URL. + /// 1. Tries to fetch from the cache. + /// 2. Tries to fetch from the favicon fetcher (from the web) if there's a URL. /// If there's no URL it fallbacks to the letter favicon. - /// 4. When all fails it returns the letter favicon. + /// 3. When all fails it returns the letter favicon. /// /// Any time the favicon is fetched, it will be cache for future usage. /// @@ -37,18 +36,15 @@ protocol ImageHandler { } class DefaultImageHandler: ImageHandler { - private let bundleImageFetcher: BundleImageFetcher private let imageCache: SiteImageCache private let faviconFetcher: FaviconFetcher private let letterImageGenerator: LetterImageGenerator private let heroImageFetcher: HeroImageFetcher - init(bundleImageFetcher: BundleImageFetcher = DefaultBundleImageFetcher(), - imageCache: SiteImageCache = DefaultSiteImageCache(), + init(imageCache: SiteImageCache = DefaultSiteImageCache(), faviconFetcher: FaviconFetcher = DefaultFaviconFetcher(), letterImageGenerator: LetterImageGenerator = DefaultLetterImageGenerator(), heroImageFetcher: HeroImageFetcher = DefaultHeroImageFetcher()) { - self.bundleImageFetcher = bundleImageFetcher self.imageCache = imageCache self.faviconFetcher = faviconFetcher self.letterImageGenerator = letterImageGenerator @@ -57,9 +53,9 @@ class DefaultImageHandler: ImageHandler { func fetchFavicon(site: SiteImageModel) async -> UIImage { do { - return try bundleImageFetcher.getImageFromBundle(domain: site.domain) + return try await imageCache.getImageFromCache(cacheKey: site.cacheKey, type: site.expectedImageType) } catch { - return await fetchFaviconFromCache(site: site) + return await fetchFaviconFromFetcher(site: site) } } @@ -79,14 +75,6 @@ class DefaultImageHandler: ImageHandler { // MARK: Private - private func fetchFaviconFromCache(site: SiteImageModel) async -> UIImage { - do { - return try await imageCache.getImageFromCache(cacheKey: site.cacheKey, type: site.expectedImageType) - } catch { - return await fetchFaviconFromFetcher(site: site) - } - } - private func fetchFaviconFromFetcher(site: SiteImageModel) async -> UIImage { do { guard let url = site.faviconURL else { diff --git a/BrowserKit/Sources/SiteImageView/SiteImageHandler.swift b/BrowserKit/Sources/SiteImageView/SiteImageHandler.swift index ece4ca173a02..f0ae7e436300 100644 --- a/BrowserKit/Sources/SiteImageView/SiteImageHandler.swift +++ b/BrowserKit/Sources/SiteImageView/SiteImageHandler.swift @@ -46,15 +46,15 @@ public class DefaultSiteImageHandler: SiteImageHandler { faviconURL: imageModel.faviconURL, type: imageModel.expectedImageType) - do { - switch site.expectedImageType { - case .heroImage: + switch site.expectedImageType { + case .heroImage: + do { imageModel.heroImage = try await getHeroImage(imageModel: imageModel) - case .favicon: + } catch { + // If hero image fails, we return a favicon image imageModel.faviconImage = await getFaviconImage(imageModel: imageModel) } - } catch { - // If hero image fails, we return a favicon image + case .favicon: imageModel.faviconImage = await getFaviconImage(imageModel: imageModel) } @@ -118,10 +118,14 @@ public class DefaultSiteImageHandler: SiteImageHandler { currentInFlightRequest = imageModel.siteURLString var faviconURLImageModel = imageModel + + // Try to obtain the favicon URL if needed (ideally from cache, otherwise scrape the webpage) if faviconURLImageModel.faviconURL == nil { // Try to fetch the favicon URL faviconURLImageModel = try await urlHandler.getFaviconURL(site: imageModel) } + + // Try to load the favicon image from the cache, or make a request to the favicon URL if it's not in the cache let icon = await imageHandler.fetchFavicon(site: faviconURLImageModel) currentInFlightRequest = nil return icon diff --git a/BrowserKit/Tests/SiteImageViewTests/ImageProcessing/BundleImageFetcherTests.swift b/BrowserKit/Tests/SiteImageViewTests/ImageProcessing/BundleImageFetcherTests.swift deleted file mode 100644 index 52bbdb8fc964..000000000000 --- a/BrowserKit/Tests/SiteImageViewTests/ImageProcessing/BundleImageFetcherTests.swift +++ /dev/null @@ -1,189 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/ - -import XCTest -@testable import SiteImageView - -final class BundleImageFetcherTests: XCTestCase { - private var bundleDataProvider: MockBundleDataProvider! - - override func setUp() { - super.setUp() - self.bundleDataProvider = MockBundleDataProvider() - } - - override func tearDown() { - super.tearDown() - self.bundleDataProvider = nil - } - - func testEmptyDomain_throwsError() { - bundleDataProvider.error = SiteImageError.noImageInBundle - let subject = DefaultBundleImageFetcher(bundleDataProvider: bundleDataProvider) - let domain = ImageDomain(bundleDomains: []) - - do { - _ = try subject.getImageFromBundle(domain: domain) - XCTFail("Should fail") - } catch let error as SiteImageError { - XCTAssertEqual("No image in bundle was found", - error.description) - } catch { - XCTFail("Should have failed with BundleError type") - } - } - - func testInvalidData_throwsError() { - bundleDataProvider.data = generateHTMLData(string: MockBundleData.invalidData) - let subject = DefaultBundleImageFetcher(bundleDataProvider: bundleDataProvider) - let domain = ImageDomain(bundleDomains: ["mozilla"]) - - do { - _ = try subject.getImageFromBundle(domain: domain) - XCTFail("Should fail") - } catch let error as SiteImageError { - XCTAssertEqual("No image in bundle was found", - error.description) - } catch { - XCTFail("Should have failed with BundleError type") - } - } - - func testEmptyData_throwsError() { - bundleDataProvider.data = generateHTMLData(string: MockBundleData.emptyData) - let subject = DefaultBundleImageFetcher(bundleDataProvider: bundleDataProvider) - let domain = ImageDomain(bundleDomains: ["mozilla"]) - - do { - _ = try subject.getImageFromBundle(domain: domain) - XCTFail("Should fail") - } catch let error as SiteImageError { - XCTAssertEqual("No image in bundle was found", - error.description) - } catch { - XCTFail("Should have failed with BundleError type") - } - } - - func testValidData_withoutPath_throwsError() { - bundleDataProvider.data = generateHTMLData(string: MockBundleData.validData) - let subject = DefaultBundleImageFetcher(bundleDataProvider: bundleDataProvider) - let domain = ImageDomain(bundleDomains: ["mozilla"]) - - do { - _ = try subject.getImageFromBundle(domain: domain) - XCTFail("Should fail") - } catch let error as SiteImageError { - XCTAssertEqual("No image in bundle was found", - error.description) - } catch { - XCTFail("Should have failed with BundleError type") - } - } - - func testValidData_returnImage() { - let expectedImage = mockImage() - bundleDataProvider.imageToReturn = expectedImage - bundleDataProvider.pathToReturn = "a/path/to/image" - bundleDataProvider.data = generateHTMLData(string: MockBundleData.validData) - let subject = DefaultBundleImageFetcher(bundleDataProvider: bundleDataProvider) - let domain = ImageDomain(bundleDomains: ["mozilla"]) - - do { - let result = try subject.getImageFromBundle(domain: domain) - XCTAssertEqual(expectedImage.size, result.size) - } catch { - XCTFail("Should have succeeded") - } - } - - func testValidData_whenDomainNotPresent_throwsError() { - bundleDataProvider.imageToReturn = mockImage() - bundleDataProvider.pathToReturn = "a/path/to/image" - bundleDataProvider.data = generateHTMLData(string: MockBundleData.validData) - let subject = DefaultBundleImageFetcher(bundleDataProvider: bundleDataProvider) - let domain = ImageDomain(bundleDomains: ["fakedomain"]) - - do { - _ = try subject.getImageFromBundle(domain: domain) - XCTFail("Should fail") - } catch let error as SiteImageError { - XCTAssertEqual("No image in bundle was found", - error.description) - } catch { - XCTFail("Should have failed with BundleError type") - } - } - - func testPartlyValidData() { - bundleDataProvider.pathToReturn = "a/path/to/image" - bundleDataProvider.data = generateHTMLData(string: MockBundleData.partlyValidData) - - let subject = DefaultBundleImageFetcher(bundleDataProvider: bundleDataProvider) - let domain = ImageDomain(bundleDomains: ["google"]) - - do { - _ = try subject.getImageFromBundle(domain: domain) - XCTFail("Should fail") - } catch let error as SiteImageError { - XCTAssertEqual("No image in bundle was found", - error.description) - } catch { - XCTFail("Should have failed with BundleError type") - } - } - - func mockImage() -> UIImage { - let rect = CGRect(origin: CGPoint(x: 0, y: 0), size: CGSize(width: 100, height: 100)) - UIGraphicsBeginImageContextWithOptions(rect.size, false, 0) - UIRectFill(rect) - let image = UIGraphicsGetImageFromCurrentImageContext() - UIGraphicsEndImageContext() - return image ?? UIImage() - } -} - -private enum MockBundleData { - static let invalidData = "invalidData" - - static let emptyData = "[]" -// swiftlint:disable line_length - static let validData = """ -[{"title": "mozilla", "url": "https://www.mozilla.com.cn/", "image_url": "mozilla-com.png", "background_color": "#000", "domain": "mozilla.com.cn" },{"title": "google","url": "https://www.google.com/","image_url": "google-com.png","background_color": "#FFF","is_multi_region_domain": "true","domain": "google"}] -""" - - static let partlyValidData = """ -[{"title": "mozilla", "url": "https://www.mozilla.com.cn/", "image_url": "mozilla-com.png", "background_color": "#000", "domain": "mozilla.com.cn" },{"title": "google","url": "https://www.google.com/","image_url": "google-com.png","background_color": "#FFF","is_multi_region_domain": "true"}] -""" -// swiftlint:enable line_length -} - -private extension BundleImageFetcherTests { - func generateHTMLData(string: String) -> Data? { - return string.data(using: .utf8) - } -} - -// MARK: - MockBundleDataProvider -private class MockBundleDataProvider: BundleDataProvider { - var data: Data? - var error: SiteImageError? - func getBundleData() throws -> Data { - if let data = data { - return data - } else { - throw error ?? SiteImageError.noImageInBundle - } - } - - var pathToReturn: String? - func getPath(from path: String) -> String? { - return pathToReturn - } - - var imageToReturn: UIImage? - func getBundleImage(from path: String) -> UIImage? { - return imageToReturn - } -} diff --git a/BrowserKit/Tests/SiteImageViewTests/ImageProcessing/ImageHandlerTests.swift b/BrowserKit/Tests/SiteImageViewTests/ImageProcessing/ImageHandlerTests.swift index 83c0f0fe5b34..290428e2cc4b 100644 --- a/BrowserKit/Tests/SiteImageViewTests/ImageProcessing/ImageHandlerTests.swift +++ b/BrowserKit/Tests/SiteImageViewTests/ImageProcessing/ImageHandlerTests.swift @@ -7,7 +7,6 @@ import LinkPresentation @testable import SiteImageView final class ImageHandlerTests: XCTestCase { - private var bundleImageFetcher: MockBundleImageFetcher! private var heroImageFetcher: MockHeroImageFetcher! private var siteImageCache: MockSiteImageCache! private var faviconFetcher: MockFaviconFetcher! @@ -15,7 +14,6 @@ final class ImageHandlerTests: XCTestCase { override func setUp() { super.setUp() - self.bundleImageFetcher = MockBundleImageFetcher() self.heroImageFetcher = MockHeroImageFetcher() self.siteImageCache = MockSiteImageCache() self.faviconFetcher = MockFaviconFetcher() @@ -24,7 +22,6 @@ final class ImageHandlerTests: XCTestCase { override func tearDown() { super.tearDown() - self.bundleImageFetcher = nil self.heroImageFetcher = nil self.siteImageCache = nil self.faviconFetcher = nil @@ -46,26 +43,6 @@ final class ImageHandlerTests: XCTestCase { heroImage: nil) } - func testFavicon_whenImageInBundle_returnsBundleImage() async { - let expectedResult = UIImage() - bundleImageFetcher.image = expectedResult - let subject = createSubject() - let site = createSiteImageModel(cacheKey: "Mozilla", imageURL: URL(string: "www.mozilla.com")) - let result = await subject.fetchFavicon(site: site) - XCTAssertEqual(expectedResult, result) - XCTAssertEqual(bundleImageFetcher.getImageFromBundleSucceedCalled, 1) - XCTAssertEqual(bundleImageFetcher.getImageFromBundleFailedCalled, 0) - - XCTAssertEqual(siteImageCache.getImageFromCacheSucceedCalled, 0) - XCTAssertEqual(siteImageCache.getImageFromCacheFailedCalled, 0) - - XCTAssertEqual(faviconFetcher.fetchImageSucceedCalled, 0) - XCTAssertEqual(faviconFetcher.fetchImageFailedCalled, 0) - - XCTAssertEqual(siteImageCache.cacheImageCalled, 0) - XCTAssertEqual(letterImageGenerator.generateLetterImageCalled, 0) - } - func testFavicon_whenImageInCache_returnsCacheImage() async { let expectedResult = UIImage() siteImageCache.image = expectedResult @@ -73,8 +50,6 @@ final class ImageHandlerTests: XCTestCase { let site = createSiteImageModel(cacheKey: "Mozilla", imageURL: URL(string: "www.mozilla.com")) let result = await subject.fetchFavicon(site: site) XCTAssertEqual(expectedResult, result) - XCTAssertEqual(bundleImageFetcher.getImageFromBundleSucceedCalled, 0) - XCTAssertEqual(bundleImageFetcher.getImageFromBundleFailedCalled, 1) XCTAssertEqual(siteImageCache.getImageFromCacheSucceedCalled, 1) XCTAssertEqual(siteImageCache.getImageFromCacheFailedCalled, 0) @@ -93,8 +68,6 @@ final class ImageHandlerTests: XCTestCase { let result = await subject.fetchFavicon(site: site) XCTAssertEqual(letterImageGenerator.image, result) - XCTAssertEqual(bundleImageFetcher.getImageFromBundleSucceedCalled, 0) - XCTAssertEqual(bundleImageFetcher.getImageFromBundleFailedCalled, 1) XCTAssertEqual(siteImageCache.getImageFromCacheSucceedCalled, 0) XCTAssertEqual(siteImageCache.getImageFromCacheFailedCalled, 1) @@ -115,8 +88,6 @@ final class ImageHandlerTests: XCTestCase { let result = await subject.fetchFavicon(site: site) XCTAssertEqual(expectedResult, result) - XCTAssertEqual(bundleImageFetcher.getImageFromBundleSucceedCalled, 0) - XCTAssertEqual(bundleImageFetcher.getImageFromBundleFailedCalled, 1) XCTAssertEqual(siteImageCache.getImageFromCacheSucceedCalled, 0) XCTAssertEqual(siteImageCache.getImageFromCacheFailedCalled, 1) @@ -135,8 +106,6 @@ final class ImageHandlerTests: XCTestCase { let result = await subject.fetchFavicon(site: site) XCTAssertEqual(letterImageGenerator.image, result) - XCTAssertEqual(bundleImageFetcher.getImageFromBundleSucceedCalled, 0) - XCTAssertEqual(bundleImageFetcher.getImageFromBundleFailedCalled, 1) XCTAssertEqual(siteImageCache.getImageFromCacheSucceedCalled, 0) XCTAssertEqual(siteImageCache.getImageFromCacheFailedCalled, 1) @@ -231,8 +200,6 @@ final class ImageHandlerTests: XCTestCase { let result = await subject.fetchFavicon(site: site) XCTAssertEqual(letterImageGenerator.image, result) - XCTAssertEqual(bundleImageFetcher.getImageFromBundleSucceedCalled, 0) - XCTAssertEqual(bundleImageFetcher.getImageFromBundleFailedCalled, 1) XCTAssertEqual(siteImageCache.getImageFromCacheSucceedCalled, 1) XCTAssertEqual(siteImageCache.getImageFromCacheFailedCalled, 0) @@ -254,8 +221,6 @@ final class ImageHandlerTests: XCTestCase { let result = await subject.fetchFavicon(site: site) XCTAssertEqual(letterImageGenerator.image, result) - XCTAssertEqual(bundleImageFetcher.getImageFromBundleSucceedCalled, 0) - XCTAssertEqual(bundleImageFetcher.getImageFromBundleFailedCalled, 1) XCTAssertEqual(siteImageCache.getImageFromCacheSucceedCalled, 0) XCTAssertEqual(siteImageCache.getImageFromCacheFailedCalled, 1) @@ -280,31 +245,13 @@ final class ImageHandlerTests: XCTestCase { private extension ImageHandlerTests { func createSubject() -> ImageHandler { - return DefaultImageHandler(bundleImageFetcher: bundleImageFetcher, - imageCache: siteImageCache, + return DefaultImageHandler(imageCache: siteImageCache, faviconFetcher: faviconFetcher, letterImageGenerator: letterImageGenerator, heroImageFetcher: heroImageFetcher) } } -// MARK: - MockBundleImageFetcher -private class MockBundleImageFetcher: BundleImageFetcher { - var image: UIImage? - var getImageFromBundleSucceedCalled = 0 - var getImageFromBundleFailedCalled = 0 - - func getImageFromBundle(domain: ImageDomain?) throws -> UIImage { - if let image = image { - getImageFromBundleSucceedCalled += 1 - return image - } else { - getImageFromBundleFailedCalled += 1 - throw SiteImageError.noImageInBundle - } - } -} - // MARK: - MockHeroImageFetcher private class MockHeroImageFetcher: HeroImageFetcher { var image: UIImage? diff --git a/firefox-ios/Client.xcodeproj/project.pbxproj b/firefox-ios/Client.xcodeproj/project.pbxproj index 99861ec5c661..8000a4a5aba1 100644 --- a/firefox-ios/Client.xcodeproj/project.pbxproj +++ b/firefox-ios/Client.xcodeproj/project.pbxproj @@ -78,7 +78,6 @@ 1D7B789F2AE088930011E9F2 /* EventQueueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D7B789E2AE088930011E9F2 /* EventQueueTests.swift */; }; 1D8487B42AD0C6C100F7527C /* RemoteTabsPanelMiddleware.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D8487B32AD0C6C100F7527C /* RemoteTabsPanelMiddleware.swift */; }; 1D8487B62AD6038100F7527C /* RemoteTabPanelStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D8487B52AD6038100F7527C /* RemoteTabPanelStateTests.swift */; }; - 1D9E1FE524FEF56C006E561D /* TopSites in Resources */ = {isa = PBXBuildFile; fileRef = 3BC659481E5BA4AE006D560F /* TopSites */; }; 1DA3CE5D24EEE73100422BB2 /* OpenTabsWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DA3CE5C24EEE73100422BB2 /* OpenTabsWidget.swift */; }; 1DA3CE5F24EEE7C600422BB2 /* LegacyTabDataRetriever.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DA3CE5E24EEE7C600422BB2 /* LegacyTabDataRetriever.swift */; }; 1DA3CE6724EEE86C00422BB2 /* AppInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E65075641E37F7AB006961AC /* AppInfo.swift */; }; @@ -312,8 +311,6 @@ 3B6F40181DC7849C00656CC6 /* TopSitesViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B6F40171DC7849C00656CC6 /* TopSitesViewModelTests.swift */; }; 3BB50E111D6274CD004B33DF /* TopSiteItemCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BB50E101D6274CD004B33DF /* TopSiteItemCell.swift */; }; 3BB50E201D627539004B33DF /* HomepageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BB50E1F1D627539004B33DF /* HomepageViewController.swift */; }; - 3BC659491E5BA4AE006D560F /* TopSites in Resources */ = {isa = PBXBuildFile; fileRef = 3BC659481E5BA4AE006D560F /* TopSites */; }; - 3BC659591E5BA505006D560F /* bundle_sites.json in Resources */ = {isa = PBXBuildFile; fileRef = 3BC659581E5BA505006D560F /* bundle_sites.json */; }; 3BCE6D3C1CEB9E4D0080928C /* ThirdPartySearchAlerts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BCE6D3B1CEB9E4D0080928C /* ThirdPartySearchAlerts.swift */; }; 3BF4B8E91D38497A00493393 /* BaseTestCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BF4B8E81D38497A00493393 /* BaseTestCase.swift */; }; 3BF56D271CDBBE1F00AC4D75 /* SimpleToast.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BF56D261CDBBE1F00AC4D75 /* SimpleToast.swift */; }; @@ -2784,7 +2781,6 @@ 3BB50E101D6274CD004B33DF /* TopSiteItemCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopSiteItemCell.swift; sourceTree = ""; }; 3BB50E1F1D627539004B33DF /* HomepageViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HomepageViewController.swift; sourceTree = ""; }; 3BC659481E5BA4AE006D560F /* TopSites */ = {isa = PBXFileReference; lastKnownFileType = folder; path = TopSites; sourceTree = ""; }; - 3BC659581E5BA505006D560F /* bundle_sites.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = bundle_sites.json; sourceTree = ""; }; 3BCC4716A1AC7645F49D316A /* uz */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uz; path = uz.lproj/InfoPlist.strings; sourceTree = ""; }; 3BCE6D3B1CEB9E4D0080928C /* ThirdPartySearchAlerts.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThirdPartySearchAlerts.swift; sourceTree = ""; }; 3BF4B8E81D38497A00493393 /* BaseTestCase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseTestCase.swift; sourceTree = ""; }; @@ -12926,7 +12922,6 @@ D0FCF8031FE4772C004A7995 /* AllFramesAtDocumentEnd.js */, D03F8F22200EAC1E003C2224 /* AllFramesAtDocumentStart.js */, 43F92B3729E9F52B000C0F17 /* AutofillAllFramesAtDocumentStart.js */, - 3BC659581E5BA505006D560F /* bundle_sites.json */, BA8E197E2BF2FB1900590B5F /* AddressFormManager.js */, 43879AFB287BDFB100B15D10 /* CC_Script */, D308EE551CBF0BF5006843F2 /* CertError.css */, @@ -13838,7 +13833,6 @@ 047F9B2E24E1FE1F00CD7DF7 /* Assets.xcassets in Resources */, D58A202C25C9D96400105D25 /* Localizable.strings in Resources */, 8A1F6C332BC5A6D100DA6F86 /* PrivacyInfo.xcprivacy in Resources */, - 1D9E1FE524FEF56C006E561D /* TopSites in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -13992,13 +13986,11 @@ 8AEE62CB2756BA34003207D1 /* DownloadHelper.js in Resources */, 8AEE62CA2756BA34003207D1 /* TrackingProtectionStats.js in Resources */, 0BA1E0301B051A07007675AF /* NetError.css in Resources */, - 3BC659491E5BA4AE006D560F /* TopSites in Resources */, F84B220B1A0910F600AAB793 /* Images.xcassets in Resources */, 8A3345692BA499B7008C52AB /* disconnect-block-cookies-social.json in Resources */, 8A3345682BA499B7008C52AB /* disconnect-block-social.json in Resources */, 4336FAD2264B169000A6B076 /* WebcompatAllFramesAtDocumentStart.js in Resources */, 23BEA767251A99ED00A014BF /* NewYorkMedium-Bold.otf in Resources */, - 3BC659591E5BA505006D560F /* bundle_sites.json in Resources */, E4CD9F541A71506400318571 /* Reader.html in Resources */, E1BDAC832B9F65780063E6BF /* reportSiteIssueOff.json in Resources */, E1AF3563286DE5F800960045 /* FullFunctionalTestPlan.xctestplan in Resources */, diff --git a/firefox-ios/Client/Assets/TopSites/aa-com.png b/firefox-ios/Client/Assets/TopSites/aa-com.png deleted file mode 100755 index c96e95fd43f8f05f49ff593165661608d6118aea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3635 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 diff --git a/firefox-ios/Client/Assets/TopSites/abcnews-go-com.png b/firefox-ios/Client/Assets/TopSites/abcnews-go-com.png deleted file mode 100755 index 62b5b1b3d1b9bbd2ddff14ec0358f6fe8fec9d1e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12428 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 KMNUMnLSTZgP}q|I diff --git a/firefox-ios/Client/Assets/TopSites/about-com.png b/firefox-ios/Client/Assets/TopSites/about-com.png deleted file mode 100755 index d61a22fff583931a22563a1fbac444a00becaca7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4055 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 JPDHLkV1h6!mR0}& diff --git a/firefox-ios/Client/Assets/TopSites/accuweather-com.png b/firefox-ios/Client/Assets/TopSites/accuweather-com.png deleted file mode 100755 index 0f14e31a26d566b5f2957bbd653bcccde0f6e94d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3380 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 diff --git a/firefox-ios/Client/Assets/TopSites/adobe-com.png b/firefox-ios/Client/Assets/TopSites/adobe-com.png deleted file mode 100755 index ca8cde6ec99dd777df93f1464d88c3169e51eac1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2184 zcmeHH|3B0D1Ao2u#bynaiAo{O&G!uviRHU)Y1r*%qn4E@HJ5Kw%`HWjyUy{^S~uTH zaS2U0lf`=^cU>P;D&KEOQNny%gq+VG@%inZkH_=*d^~@BKAw-~C3=v*4sH_;0H6~X z;1jayqW=+#T-8}s_5uJ14xPsEU5zXM;@<}T4-E|0e%ie{uRjt(faAU`PcSev+PG=6@s_P7re@pBw-YT$mR8m_ws!Vpii6`0mz}O|yF5Ji`1uFy z{hGEfh#nluV1}_d;oL*K!$+cyM#mgG9(&>>KRz)jS#VaEDms^T{z7`j50^53x}24r zb47er@~gC>$I}2%{Fte>g=^f*rMr4FSXc`yFj6lZnYWLsXX9s<@P=lIQBGtB9 zc)FcP-DpTP42PWbc*yDd1E73cYL^^DpQa(z1#3jO%Non&--R$^3;2eO34eO5a8Ra8 zdWzhBpawtMzAgDAWGK6m@TTk=Dlfyi=!q4#A!#x9xPdy;L)6Yfg*!wSy4t^nm=d7n z5{8^_lYmk4#P*nW+nT$pDMQ^1A4~}A;2{e_V z4$PKQ!1vj&P>7KuGdV2aZXkWk3z~31%;oYcw5)y0qom znB1k`W*Q0t>1utH$}F+?aB$*AlmeFwRr+JPlvlg4CLr%z({<9zx(OReBMy{EHA*gH zNI16=iLiqa#lk9ZqFx41NJMCIlbfcjuTBQ9sRE4&^S85JrnY(S5#p)0dd`rYm}CDP zF$ea=!(AM#+CJPC>p5wtB`1xYR|+EdZyoTWc)dvQW%E}_evoRe((4gKT=8MOqY~gn z^32YoF7mx&S$HVn@Q;gJbw2jnS6&^9=^)8_;i|%WogjpB9R>T7(^FJ$wNSKB=u1FV zC#HULgr_x#+eY2kQ${}<&uj@viO>~2rDS8QH4k*Dlln_@V;4oI-q>C<$*beq)7YD| zqdOe56vYCZ>VCw17erk5*-)$Mw!?RL-=nydTn=q2zw?(1IZ^4z)O{Pky}rD(I{Gs> zr74w42^^B>$K^`uOtEq?31O3fa4WnJ)^rhw|J3+75=OQM!R311z_odxXOghH3J~AA zBl6b&e%BZmx8HqvE!iIz5c;v*x#d>n4G7kGZ>fEwHj@J`igP*3qFX~6OU{%s2^Dn( z4K-z_cbBr%>Gl^Me#VGiID>eD73FvBkBZy+b`5G#cMwztvrCJjWB1mVRa*(_NBVce zeMx{{=6vwAQ?-+--nmQHv?9!mlvaF5dekEUAXREjTqx8cifA^tv gS%Qb=TUV0%(PVmaONkSyWA*bvpl^^*r588tA8!LECjbBd diff --git a/firefox-ios/Client/Assets/TopSites/adp-com.png b/firefox-ios/Client/Assets/TopSites/adp-com.png deleted file mode 100755 index f5bf11232167370f2de8f750ef2d79452c5cfff8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2513 zcmeH|`8(8m8^=H2?~Gx_(qQVyGMD9;Qebb=~n+mS==9k{AGhu=!aN zoBd7yUjz{QbA2Lh3jjFZicB%xKY9Q1uYvzd0}+F=sQrSD1=v{H0sz4XBp-@j0F4n8 z5*ERViizV69{Ne*u%wi<3|>xN;b%p{k)uk-jw`F2P*qdc(9}9f{6$;ml&;=seFH-y zV-vG8XV0A{TUp!KQta$6Ub^hy=yb)|#r5j7>o?roJv^!2G@si6cY=b$BO>Wh(f97h z#6E~iNK8sj`A=$E`ooOOM~}0zbMx|lEnpND6+bC?_M)_mSy5S4{i=rb`nTG;`i92l z7WSLgws#-eJAUu%>h9^~^nL6f82mIeJo069Y<%+1zow?Y&dkouFDx!CudJ?pTi@9H z{`WR-XLrwx+_(z>iqG7{kPRMFUuGz5 z;Nk%3?-EC>?158*KLsTKw&1J#fDovSqRVv1gUYaG0rn|98b1Gge^FQFa-^>7LcM_$ z;;xSn*<5wRe+2s}vz*QE+h}Ube40C!^h!m|?{>=%7l9dg!L)G3xONuv zWi_y%fRT&>BuW$h_4qp|So(}UWP%%X-7UzC_q!0Xx_gjHUp->&B#5Of-4O+9ErO#h zl08T^LG5mVfr?koS6&`7y!;YxfxNrd^(~OD#4Rj6d3jh3{}xf0$H&NJ6Mmcwm=--> zT}O#>zq9TsMS6KPV&H97f9LpBAwY#Mw$=jd*l;qH=EaWytx?ks68IBkTu_gGiG;!R zD-|Etcni=WaQ~*{ksKD20!EP$B3K07*F9Cz_AQFuNnZZNVKR%&HIl^uDLZ&bj!1HO zvK?(buM=|}-XKYXPhPfH@1uc%P4NiJEVGpuwRhDM!Moy)P!E>^{J7C_V??-{zc zwApHW+JWh3<#z)%16Qg_uGGJKK`c0HX(GzcnbvYCyTtoauB`#d18^0;lbJghcw9%^ z(oCmzc&Od5;-0{Y#FDC%00f3mdWYMDTY4TP9GKraKo`OlSCS{NSR{bDL)}(|jWKMW zSW0S4lC7vFga>glS{g2L@RPz1g5k+S~?#dLxpwN+3S=Yj6qKi(XFYi~7NV!`hjfe3v04ndD)eqt@k|Q8Y+PWs&5r!Bn~% zv-eOtzeM_*KiTVWfjd(XP%_VqXp+}f&*7FWVxvnJK2n3H+_lI;Em zpCh)F$53<&SC9CLr`uo*jYD8ag;kV>^^&!U#-~Y@1C-KkE%379e1TNHKQ)Dq?oaR~ z#-Z3J?0Xe>?Go&0vx`C9FaGp=U&Z9~A~oJbLfTlq=fF01!tmkL3fcwY>s zNj>F`$4OM`++jpJEyeR>3N(uBs@Ll{%%0fW!ERRN`y8U!E7B*Dh}R=*H`8^UP$p1g zK9i-GxW)h23xAY)+P|@{X38!vuRZ$5?SRC)M>#p@k|+O!7P2eIQaTjWT$fn4|N4Nr MsijG|k!$pS0lMSi8vp{&oC+Nelg}2gKx403c*z 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 diff --git a/firefox-ios/Client/Assets/TopSites/allrecipes-com.png b/firefox-ios/Client/Assets/TopSites/allrecipes-com.png deleted file mode 100755 index ef1f12d15498ead8589ed07c9e12c59570d966ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5060 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 diff --git a/firefox-ios/Client/Assets/TopSites/amazon-com.png b/firefox-ios/Client/Assets/TopSites/amazon-com.png deleted file mode 100755 index 9bba9e5c548baa84394b92c857287053eadfc3c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7169 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 diff --git a/firefox-ios/Client/Assets/TopSites/amazonaws-com.png b/firefox-ios/Client/Assets/TopSites/amazonaws-com.png deleted file mode 100755 index 8086e5e2273dc3e414ba06c2159b8238d9a86cff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3984 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 L$3(kI(<%DD4%zqk diff --git a/firefox-ios/Client/Assets/TopSites/americanexpress-com.png b/firefox-ios/Client/Assets/TopSites/americanexpress-com.png deleted file mode 100644 index 5ee763c129ae559fec97b3fe7e865510184b8adb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4734 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 diff --git a/firefox-ios/Client/Assets/TopSites/answers-com.png b/firefox-ios/Client/Assets/TopSites/answers-com.png deleted file mode 100755 index 5ed923423be58ea39528ca86ad60e8ac5e1adad1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3017 zcmeH}`#Tek7suBObIXRgwyezuq1;B9T!vZ8Fl@PmrrdJmfrbKw8Qfs^-^ZMSav8_mVE%D?*i&RbZ-W>Kd9_JK#ID5xbBmoxgPT^miK=?%8W>VrpiNwy@l1g|R+hV{2!R zb#QdTIpYr!4!ICr-P}nYo?c{%kFVbm|A4@w)S%TY4)^w*yZoBkx_kBa z1r3c49yUE{Zh8EqRrs{M<5}nPuI?8-y)R$&iC*`M2L^|RN8Y@BH#+uyeB#5$PoF2J zre|j7=D&RX_I+V-X?f+x&(*bG>l?o}Pw3Ke008NS1Sc$6UE_;zEtxz3mmdEXrYk22 zGz~FNBjcP}vpFQ_oTnrm(`%23_{W_)lVo5cKM+8>h zXIB~ma!y9WVRFeB{mz>3^e@@K|fE%9v8_>p~I zcNp)tQNb|L@lVS4+}$v8^N!aJ2fv2G7cjmS8mjy|q3nS^NF~3w-G;WIS>6N>zC26h zfVkazZF@4<_a8E+25Nxp1-^RlBb+b>)4!$5*{&OoG*Y z&|nkA>mLiESs>dx3bG6u+&nm-Uc7NWaN%g1J=JhZo^nCRDke+{ov3r(;$dLR#MF#H z7pTnOnMI^X@=^D3CkprWQhuWD;FW+!V%$Tv~;DZ%nQNFh%gYi6~PX|1pE;u1Mr zuvN>;3r-M5X(Z<-M#a3i62t%{?5qxq*G<{WuNv|MDf@KocSzs%eNCYy@P)Gpqp%!( zO}?yZd3b2sF3{nk{$RK;csuppR3BYUMIO_Rif6F*Mt>|+OkO&yO+HZn6#ZA&2q!Z7S1!h7rx@=rJ zmG;YWR<-A8r9TpGblGMhdO%Gv8SH>Pu-{Pri!1wPxeZ7X8!1}w!GsCh^u8~);exT6Aev9p?r#W<$6VT$8gLv0ueOq<~Qep<8 ze%j8t(}1JuWudYKu>N>8awAEgw56k~KfWMx?zwq-T+Ts*iN8bwb&MgWByCHlx_h6Q z&MlvHt;A9X;>7f^DKh*VG6dMt?1$-Q z71}T`iHI%gq7_~}(cEb0%oFr=VF8S>M@0NxUIu(yEzGg1z7To(3)f(+<~re3|S#BrDgc`YvugPl7(#h`-$9k<9(aQgLTG*Sqf1 zSIfU;(0eg1-lNS2)IZ0tpOKT6*&Zt{xB!to%k(^d2?f#lBTvzOiu$-;qP=lD2&DOT zx+IUf#9cro^#rq;))Axt+|WV;c<{RBDWl1Qy*H;^6(ElBkraJt~1s0MN{8^PmoO?t|H!%Bg6@5glBn6iT$WS@A03i0oK%V zz4%+G=T#lokJAQ5r5WzVx;>1%SDb|tAmN+Q^$k8^h-fAZTb~z2*2-+r z;=sO1Xfbt<4_5+rKd%~#tKAhY{;hL;hqFNh7p4u8V`f-dkIeg9&I>ApXX2o40>MMkV1|~0;hc@WNstYBrKE{`wNysYApHrv4f@DAdq7McJ24&4C z#h{8IW7}S8O>RsMf;s*C3wnR@s-5vB5}2OaZ+VlISrY9Mq&uWdt;Mq}ej>gIiGybC z9^t23Ra%MN8Xt`AAG!uCCgkq=fsHiq0+_Fr>>6}1OongG#pvI$J+=6$d~tCR{bQ`QnR#4xhhyxM-#3A%VnUAU9>0{KO-1@J V_bTW>N7dH<0wCbrocIn@=D&$k>X`rl diff --git a/firefox-ios/Client/Assets/TopSites/aol-com.png b/firefox-ios/Client/Assets/TopSites/aol-com.png deleted file mode 100755 index 5e7a26cf009f0b49717f02dd12ce21f2bb83a5ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9096 zcmV;3BX``1P)45Ab^Z=H58DJq#te3pok)%K$bu(ouzde$59+7wiDZ;EZf>;QsOF-_w>iR%Q^SGA>SJg zmsoQRTI38l^XA=i&-u=GHlVqhtGSx1xtgoFnya~*tGSx1xvro^Sr0z=t<#Nq{az4` z0T^QDqX7MY8AkyOG59C|Feksr?rIFclsv)q^6al9|1x0wBhhp5>)CIT*K>c*_Pq$q z41i#mK}3LIFxl52imrj}1u_h~r^DZa!g~Xh{5~iDvVWAoNdC^a_p{dm0Bm2_{Z8`M z;q{4Ozo)_*@y{RGmic%ozgX0@_7VWY+zU`I1AE2R07!%Zzz^*A?&s!OqLnQG+_2X_ zXw-{RIOaqEqYs2W0DGhN9JGRPTzuaYj3pC*#;kq-y%4I?X%_~;YKG(ivhonre?KPz z0x<3q8fnmKiQ__J3^%uNMG64#gWE({TgpgIzqN&A?XZ8&$%(LWOu@Jls2|||=#7Sj zFgU>&Y;NuH3P2A)`z0uH8|*flQ^<|7@rOrH4z#77>ap6UKQbfEY&<2tZwf{p0icD0 z!2Qh9<_iqK5}G@-t>r)o2g%JQX9+d~dI4Xdr`?)Cqh+L_KfWOp9 zCDOY}(R*?F^mFQmwEL&z%YRGJ1Ijn-O@xE@0!ph~ksirnn1Fr|dYQ#0aO|rmes}Qw z8BFB-gOpids^O{B)Kpyaan90q3@~#a1AWBU8~w`L+9SynfNH6J8!$1$`_$(7W6I*h z5*(iqz@Q+5Sp2T|c2;gWWfMWlG-N3cN$@ZSOO&ChEFsfRUR&{f6rO)ucqEP10Np@x zf|C2}ZWimqX@4}%L*N*A2%GI$Jl1A|QZ`1Pa7x<{$FPxm5en}`RuJ9w5OM5~c&$YQ z7;ry<`WbA0hrr-0k7Pv)Mk)Ign|fdGUJ&&#r;RidCnt_$s83+>mOz|v@*7Ven3NWY zPklF|kX!%}gN=4zoKSdR%Yoz#f<--?xT*b-!CA2$NuxEuL5K}zb<)D) z$qCZ>o5h|`1Rj~i&72P`LTHRy>fhQMR(Qglerub^MFB`)7Diw-DDWHh=lJ>XZvs4- z(a-t=NWoYZkED?T&ijfUM?WPHP7TMwNHM z!g*j1TwRa~Rugb0yd?ko^6^BAi7PeMBO&Sq&~KRKrN!(0qk{XUTus3Th5p=2{w?j z9-}lEtm)ik*?J$ZO~r}T^@&&nb5PF4+xu`0i5ZaAB#=@ZZNAr9M2QK=(mpJ%(Y`QA z?L$EW1))N}6`a9E)c}*Tb$~yh$FOAl7%8?lV*bJ%n@8iQIKe#XUtj<)cbp+7!T-0x zsE{8(&SVh$#`_bie%E;p!3;>1?}W+;w*NboZx9KnkblpWu(5LD%}(#)Qo#k|!3;X6 z!@ZFqwyInm0!#ilX_x!UBI&_kKHs0`W-!G`<18FO6um}p|JZ_(L>SVf7R3P7+j@>% z(f~fC`j@W(3W+H!z^6=Rq2R^zGB+k>-_n5B=(PYaV@phsWEMAH>R}NFVAeM_1db!b zu6%zTHsHCqZG{pkQ;gW3>VWQp0CMW&v$OH`HB*{_p&t{PkRqv7+QbS2LE|G6+?T$^ ziv<)*2|6gDk~$^!1DllUCQs~eYIh}C&T#)I+cx;8Woj04gw!EOAPNkCJ>kJ*u+>U& zOhJ=P#%nfK*g$##Zll?AAkn?HsbR4xbQpsmKNJgGL_Le90a_^k7r^`FY2w=WJc{s9 zWRD$M4x(g`b|2$B!8F-SnfSonV%L~|_NMZ&_pHjh;Qq_Lb3_Koi#1GXZdN`Z< z73f-?lN4_xyaB1kGd&9{93rnJ2nK~svd~c^p!!F|rbqaJ#r1J8C8X|y_ynFT^Dol9 zcqSkxz+lk6l*wStz{T7=iTyKDturf9W)?xcIzO0ex(3?aBCo{gTJh#4U3-L#;J52nF*Bfei;rsXHmOK2ar%J5L-kk4?w+o zY-dtjb%+i|Y+NJ^f&7VM0ERL?x6?YlE`SyK2UvSb(fgS2Q$t+AmRh%9-Y=rPDS0MA zhj36|a=VxWIin@o;{a1jC@EVw*%e$+q~0TIL0P8Bc_l1QA*(omcwzN(%u;Hg7oIUS z$SM$}16wSEo)o#9DYBz)Q8Yk~wU-&a^6J@(XRyCc{j&7=>q+~X6Ns?nmOzm|sK^`y zPk=-i*W(Pw`YEzTtAA~Lgo~H@omjeSSM+e?uBrqX1r#B27yu**u}hBu67a{0QBy=2 z2PP|(mXqlWbH3f?xy_XG3k(Nu08!|dWgZ~2mlYLP2l<@QJwe9$=cjePsk34%GLzkun`@)$K zLS)%hj?>A+6${rds8m)+(>UUWjld5QUb@XEVevTd_fnA( z1v_9v&Gz5EB{u9wJGbNFwtRhsLw)I)Apy9~Yi$IQXHeEc%h6@}v zgc9b)PlRWR#N~mb&7~0TrN3y5qlS# z!wkjo%ad=MnGxIqJAq)<{6h+viV&~ASeqE)!o5Xq0+CK&Wu$lrO~x&*2Iz4qN~y@7 z_`q!93r&8!eOqVYi+jhqN~Z5mwWw!#(;VgM(!*Fs4ZQnE5`c2h6vhRlSg2l7Sitze z3~AaSOV@Ku_~h7sFH~`zL;$UZxyRVgH`iAq1YmzU6~l$tjOMzdq@Nv~C9Ll#jyJDa zSH^})Yo>B!6)}uDi5Si#l!$bMEbK=>>awIU1ZD&+?HPZn8E><71KJe@(z%KGC=P^N zgXH^Jg~6!LX|K7y7Ayb^98Bd3)!^}2gKG3`uGX!hg6W`iQiwk#M!SFlm@x-bFLOb4 zjtFUbx5kNKAHmDuGgxFead3Uz7ZVjD+960aCu9^{P;sqSh1fyuuZ0Rge*hd&1`CVi zMb(%mgi~)Ufd1ok$M#hjA)xf;X{t0j0bT_Qg+&tU=#xy|%@W*zj1dT7WTX#)$pWsb z8Y;gLV2R0ClRDNb=_Snn-$HqSeX)*XPE)r~0gL2r-?_Ph_EP;p$JON)+_0t{FT6Fa zLWnZ!$K8DL>YsgTc&chxoTA_|Cg}dAwe7fWO&JVeOIHb%wiX<_kZ=*NUA&CrmuB$h z_;ihcL`Lorr>VgG9l~5+X~nL!;dgIYi;b(= zuo&yt-r0?x-%%B$SSSq(scKyC{8Q%X_Zw>u9f7W@*9(|S10>BJQXLoKmKxA;0W0Ns zegDe^dJ){URR@STF8Gwe7Yf4AS!%)lJ!?@e5f*d(`i(t!@8(MIlmc24aH$^1COfXM z$PjX&YV;Z_B(=VZ3PAhhEbe8SaiU6}WsxNXpIQ{tpxV}g8#d%q|4$sdl%EvZT$#i5 z%2b{JfZyA*23_SAEXDfGcXeZ1M{9%u0v|y|`|w7Q#w2~skwNU7nZ5`HrM?OYz<1vq z|0O_{dkcD(C{)f0g?%Y zN>$fhuU?qK=#0UO=O=RCl-sv<1f4{>*C4ZwmvptY;QhN+VX0T|ns(gc4uSAYiW5O| z`34Yujl3(^7#`q#+dIDajT7Tw=KDA!ZPjI}xojU6IsV%^OW4qvk6?V^T(a@cpPj-- zugiDAH*Tz8RjCD+W?9wN2Opb#LjQZVR#7RyLQc&vo<1>-XU~k|<&kL+2%T+&J2zEu z`_?M1>dCL!K5}gro;`OyB$d`d1jX%8n4|VIESpxD6V*RD&3GlJ831f%kqgY2aP*m3<@nvbGymy7GdhjGeEKZ@?d6MjWn{*y z;L&Nu*H4V&FaGZW9{PeA6 z%(910&;&Q;B!AA1O=EN>#JOKQKbhYf*wN{eER@^l;}neEuD0C3@66~l9{TQioE)D) zMv@s^uHU~O8^gc;D1XPd_igV$DuiCA1qeNaNF73k-?^oV z_MH8No;y9E5c_jy^J{<&oh59nltR}GpW_#9$es=PNvKDT4r6r2rg14XoBqgOe|;P; zoy#YzSFbHA7fJO8$YbkkG{kao50cC*Q*VNTYkUuLb&dR+Vb=>DuG2fM zWdJ`olV1aLm0NJf#)^phhggJRVY+}S*U2OWwqE)F z6!8Hrqgk+yeT@Wxa*Ytt;kcmD2s?G-rh@1{Bh~-hwGkX2dJ^`2e6MBy)iSqdrdhv z;=VLxu&!Fdx@t)jWd_xIW^5K4I`f_0-RsI&)e4Nxi0a`20hdaNRKo{~3PQ7L@`A$Q z+?y|4wc;TFM2(|ZeooSzV}t-a`mybq;ZsBe`Q<4+`xDp0qM+>YFjIA*iglCt-j3_5d*L{%`jfe3DWM`RQ0ExeXCeXx1nQA z%Jk-pFPxm1^~Iy}MrP&^AZK|)s$-~Y2=xi*`I~z-E!+g~+!5LXARKezchjaamUC@b z)rQ`#HVj>w5%v9qk*R!V?fpAD@${)l(V0x={j+w!6QNsQ#^$bkX6lWxne58toa9eP zUX426g7Asmt8n+W4s2QNuciOwrI{B1d;&>xX>POz0DvI|9(FhSwrw3)?seDJDr9{> zgYn9Rd>UY9Pdk2YQ^l8n2UVR_$&>ti@Aa#5z4i-dCRL%R;o=}r&MR=@_^zHd{PjH> z@$nnF<>mtbwse)=0pM8xe-5CnE&(W)=KiX*;(lffZ(mhk#ZRNx&6}$N5hpiX_7|9M z{l<;mxVF1p?K7!H5+NVz5B99defnR%FeOS8sRq3_Hwa`AZ6zY~v=Kh@?hV*7|22FT zz!w)o0|3AXfJ1$oD_9AuTx!7wws$DD?bP^8?mUBXsRf_BZ5=*nU&A<0KqPc-?I_`M zcdbX?mi&0c&90b%-@mCFmHe4a2Laq(7y}%koY!2_gtnD#}^u`9B6uPbA7M+qm#W;`-} z{=yVa3|}sk5wxkR4Il1Wc;e`zKfUC;hRf<{)KejBHQW2P)#Yv717I_NQ@Kq*dx`RV zePN}Xe(w@)DC=JP3_MmKhTo|5#4DHZ#@I}Xy5)k=Krx>RWRqL#ag+eOqtP0m7f20Q ztPO_FO=7^t(c?aSoI#Sff8V#YijQ8OzYo&gJ38^7Lt_ER5%BWJG`{xJi}=v))l0JZ zr!Gz7t3MgF-Nso}4NF%tHxbC0C74CmWTQdg{vyBp(uJw)O`l8hnepuD$wC*ky3&ek zy4#{&y};wg$MM{$@kQVKk;z#+_?>ea!IRVjT(CcYQQ_pV`o{U40`N+s1z=xp(VH=; z*ni3$lATn2XD!0$jKNO}q>2GR|ISsSBrMRlkNj{1&z+oDw9Ox$oW|jvgbRbgIMBjX)uIv8>fU}JhfPNH+I=y;+3Zv5|-S0OJ+C+1NoZIyMlf_Q%b?eJf zQ%?4$=#l5&!go%LEsEN||66D9lE@`YPfwY<`NX_XfPmM=XYtJIg|2@Vz+W|*2Pgx` zjjX|M1Lt9|~UR`uZ!E z@VRfDh0A5}CtqBE?_5^1L3NFd=MddA_BH$=V#=6V!x{N1%7g_m>IZrOEo=cN`!fTc;PZ0{NJ;9^4KV*X6i#% zM^8@R3s0TFS6{jWwzYrput+s248>h$BLY5-3wZ0Y!GqsEi&K|o=KR}l^<_Iz{jrYz%O3ig)LpdnLBxL8s9!K z_R@*5**%BuTsH+lBQJ#j;J=QIbx+J<2nd}kIKu<-*KRZQOO9M>JKCuJj=vQauvd|i#gn66xbpU z(fX1@#+8wiV{-$@zSNKULZw zx!)XS4T=U;p*xKb3D%GKyn4 zs6k@lR;k9*Vg>>L%o>F5Xvux+L5{KYi&ZlFFo~+7nluN;^M0a9y>TF&q6unJO%SCO z8;f4Q973ux0YoKik_K14ItE9aQGKho*Qq$JdgfjR*P~3>yx3eYr z);@uxFHd!F!!*F>pE?!Ye?9=hld_Dd7Wy}U^^rvZDr5>2>F$o?Oa-L?p3LtHFiM|r z;UN0o4Q*US7fyR8wNR)mT#qZ{^e~sU#iBDMM-#_qMJk#Rnt-y*v7bFCAZDcHW9?%Y zeaO)_XfccC2LTKsN`|a8=mBg(H}B|F`Xir0)Pi&&4XO;ANOgqg4LBM&78*H+;Zcge z3#wb`f7u&Q&J&C<0BOOB1u^a(WK`C#=r95|?Zp0PU)MLnwC;jEAGvA-8X^FH^3OgByz92xqR5hzAc1UE4yViCSrtXFZbm80 zh}=@nNP%~W;zs5p!sskw*_1_=>WeuNmklS?++3~x zq-G8$Ow`+f1u7S5-OQ;vKRMZtWE)nw!5oEg#hd|WE?hrpW<3DeA$?;frjfuW90olg z^b4WLlhOSE6%h7tf^?CQm~|u`UK$PXXWu-HY75Qv^^ilOoJIU7x)!N%Zm9_zs%e!T zxt^609?$v<+CsO0Wy2n2hnJ70ibwMZ-9U+?Lfu#oBfFWUzGlws6{H1{b@`VYKSR20 z{j7BxOqx>f%QHH5DH`XDSmrRB_>p9H92*eeC#%ZIdyXD}+1q6}j9yRi4|)SkW~c8g zyh15>G!s#HB@V2zXjAV-f=cf~{a=tyPV>mlYz{w&o6)-@7$CeS28;R@R; z`q@OED>Si+#=^!b-F+6}?U;0zS>fJ_Nhd;3qr&rHW;{%UBa21^{pmMPquN?H!gb&H z4DW^QZL3)^L=(MTg9aAhPxk};8y^D}rPiTCR(QE+ycF2_&8JJ~!8FkJF zSP2>c0FHopFm|_uV;?$U3D!%-?ZZ%zU>~(cNDBswn7t&Q2)ZGYYO*WUKI;)Klz|c8 z{d?#DzC-S;wScO`_B=id%fkRLWEh7CSYuE7V52sov?wP$&muYi=3@{y%P3b*gFemj z$z~1nC$Ge8pgdAC!bTh?rs((NsO2jg6UZv>d&O=l31TVDN%+C@N)vcpafCpJ8@b^t zMFY4v!NY+J;yA_!DAlb`88fE@LUI3bi*~LNkAUdwPr8an&jl9U!YJ+>mYwRR>1vML z)QC^;i5xt{zyo0H0&wqQZhlP-P+78yZ@PbC2K$-0$8W7@(?U^LOr~~`7~<#?JqXGR z(2SbSGmr$7qJBmH;Sfn=>D37nKsso}(Fomm&>_nS%Uj}ewDNo^YY5)Kj zVZ#p)L1(qNkZ49QBV^Eoac?oYmN|d^kb5>RaPo?ahzCxnTmwqesUrW5<*XoY5=i*| zdgQEgVGS@$i57IH{m4>pz;X)!06YxFQ4g-v=~08z0+2UhH3yI z2?Ya0nXJO@3$r0XWSH?Q6IwYla0Qq_O2FJ28z>uEuA85!>_;#2QeVd*Fh5B?DU?KV zXf&EW4%SfE+Cctr?dhIA;Ub;(<$xwd)k(oS6nVQYH^5)AB;)mn7kdrE2}whTmvh5c zq6PqfK}tH12~mfqz)?YT8T$MQ6OI59>(0g+cS!MbB^W7invloPxAi-N8s`%w01|L{eS{OaM>>8k2S{}Kmmhh!>6SMn3+$)I~-N8G-{zgz} z@ut_9Yn@EoQuzm@-9eFC7kCC1#UD@@KwRShgBwQAUa1-Y04@^QBvRHv9+?IubNOWC zPiNY&%K9bQY7?Q_R%!&wK<^ai-UlXdh=>k>sNwYNl`H^&O&`;V!lbfe@}~{-D~;yP*tHlW;0{bcDh8Sl|6&4aL75HGp%S20|rP7+6Kn{5&Bm z>sJx`Rh7L$?b_yZpD+=Fb5FS4986PmfLWUIu!|m351>FX^wv z{rv+gs7t=mV~}-bpp7sN13W;qvIv_iO#=YH2m^<8rEHw%C$NA_pAnfgS$P3*TDT2A z3^MbIpl6!`5SCTD0ik};cOv)GJkoB89Fbw7a8+yIR0?;dJWtxDonU!&I z7LXla;7PB#4HO{sCP3u#1)!IH-X8a(AUfPxqQ}Ojc?4JRYWW$s#z7!SA4^cWh!L_V z{9uveCo_3`W-kweXaLN0WzSww8h}^aWzqp=KIV%;Lgj@T^e9&-^yDFc4|le;{L|PB zU-29Mv#0?8U9`MKS|)|Ggv^w8LhImkc{IIjKktyYEz zILyiB4>z~>?V|x;Pw=65%BQ7*C1LY$bMxPx0ssI53_fZ(fguJzV3?OJpYCmI0!F9J zO1|bp0QDd__082>&DC7Z)m+WhT+P*7&DC7Z)m+V$fBio{1hAOdnYf1l0000hnx&ZU%c%LbqHi0HHYIge zq|29xxuNAtbiT})CgSKMrLM*lo8jDlaX;Ma@p!#okJqoy$NTXrAo_Zukj6*=08n@@ zH~+0<{_Abv)?J?A$N>PtBN77Lx9aBq`k%mmk3ihp*PN~IoJ#Tc4FCWY2ndD25!+Oe z+tpC&8k$<#I(qsBhDOFaOujJPg*G$)+VUIgJ$r31`}W(}A8>HQIyrym;)*-?y}O4e z-kad#>mLw!Bq%uKXy`Fg7?~0t5g8p5OFa>H@>BvXF)2AEH7%WfI)jm!b>=KHCpRyj zb*`ZB!o^FMuW*WrOUk&s@@v;CZr=L&m)m!$s_)j^`}KZpU46rY#-@kOE&NtNd&eVT zXIFR6lit3kzxNLe4vB{U7!i*?lZ-u|criIW^YX9RS97oD-z>a)|M!QF(#0j&@~6)$ zt8&Gfa($zYgqa2as2uNhFpxgc^J0yxd&Ce!~HyRE+3Mz~)eNQmNKp1+Wjmx}q={qF~y1hQ*cXD3BM zS+s*w@(?#YA|l89O&~WR%~o=c?lo}rw)bxjALOo+ORIsR>D0zQc!n_C`?z)M5LKnh z_|(`e_r{tb#(HInE%KGYyAzJz!uA=lr4Jo$JX?ZYEjO3H*Xm$msT~&CRx^oImpCmt zB);7e3`~NZES}S_ScFd6^dI-lwwPgCyV4H$;j)!bJ5^^DLA1QWi4O5^x5eET>Jazz ze{4vCHQ{AhVps*!?2#_FI$=FHmDCO+9b6J4NSQRWf7VNKmYMiZ76hz>2`R7 zl?X{-&azfFY?rRQMbO_UP}MFZ0P^eIV(}@sd_LK8wjDM8SoCDxxpktocTSPy{daPH z^Ldp!%AXKt1R3osD@`YVJZ5Hme0!bp?eSyx`fK-e7rm}sJKE$TZK->D8A>EhTeOd? zI!Q{QRo6bF1&(xSNzb{t^gC9mHQ0U5%*2C;9fCH`pjW(Z#B^iLg?#IkcM=ScKSj7Z z>EoU3X~Qs@D;MpX!v@soX$o9~f&J;3qTcdy8_W-<3dGR*P2qBFB-I#@8*n#1joH~& zu98{R*${MPY+m?@Y9^E~9wgeA_y7b&@ymrak{-o*fStM&V~<1GO^4o0gWI0t$Pby< zM9yg1Zu(a&v{dSHUD;I`Utrb?oi|$-f;%0BN)9)V@wkPr6h`I=!uLv{nK-USCaXWe zUI$n#qsVhx0%F{RyF%P~Iv;Z8(v5aA6G4oy>ldm#CFG1C8ybQH1Bdm$W`vVfwxfn~ zA){gmtDt@p=ZIp1;G_pQaAS)7Gx6vgydBr^52D^>VTmx;k^cP~-lOi%frap$UD%u@Nmy zL83x#FTGl((l)$mkfxul^=AUJGB#}OT-kS#^~-1#fhtN(Wa@|0SD|3DK|6Ma*Oxt{ z{3hRLPyzla867IS zxmLWK*4WH?l8>Dy4~$~dbq)F^gl^hez89WOKCB-n+8#TP2qAzez>?nj?`YhE>6 zAuw(piIOHfd?(AvZAClaWjjf)i5Yt6=s&Bbg3Fa4$!dQ}W>4f_%9e$+O#l62kJE_E kiHqZnJG~@|LeG>1*CMdvsMDN;u(kF8-rd)&_IpasKVsy9SpWb4 diff --git a/firefox-ios/Client/Assets/TopSites/ask-com.png b/firefox-ios/Client/Assets/TopSites/ask-com.png deleted file mode 100755 index 2f9ab7100701ca9acb7e8c0a6e07d85011411ba4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5997 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 BcfSAt diff --git a/firefox-ios/Client/Assets/TopSites/att-com.png b/firefox-ios/Client/Assets/TopSites/att-com.png deleted file mode 100755 index 7fa9febd0862a77fc4f5f3405c4f5cedeefddf7e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27266 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 diff --git a/firefox-ios/Client/Assets/TopSites/baidu-com.png b/firefox-ios/Client/Assets/TopSites/baidu-com.png deleted file mode 100755 index a72237ae8e8961cebf07f42abaf3b37aa1b03369..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3287 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 MLkoj)J(t-305x)j1poj5 diff --git a/firefox-ios/Client/Assets/TopSites/bankofamerica-com.png b/firefox-ios/Client/Assets/TopSites/bankofamerica-com.png deleted file mode 100755 index ddb7ef5019acdfcb7289c4fee6cd8b8741c60963..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2781 zcmeH|_ct2~8^;rBHY!{sirTexP))=ZAzCr3MaAaEC~AutO4TfF?OA(-qDIpa;o2n1 zRaLvSt3~Y^*ZbrB7v6I}=RD8%e1H9%=bR_b2&2o!dYKgf0I;F;kS6CD@xNiFKi@lZ z&kq3rx)r0lW;*Bf>_7f9@c(W=e(w9)`K|B!nqW);03aRx1qMbYW){|qAht{FU=Ged zxVU*BP~OXY`~p`5g@i>!#l){lNJ>e|$jZrIyME)Qg5oWu+c3B?LPb?gT|-k#TSr$9 zt$*jP0mjhC*u>QAp85R;7M4~It+6(?cJ>aAPR=fW;#}R_Jsx>_c|Z2?_45x13<}1F zgoQ^EqN1O~#6Eo%pOBc8obo(1?ZwMi=^2?>**Up+`2~eVuZv4c%PK0Xs)==P>Khv0 zHZ`}jz9YT=(AG}wpmcV1_w@Gl4-5_sQ)wd~N5}pi|1|M=^2^lp%pMkEN~iTI{eEU^0MBty_6z? zV*$7{Q1C%TCb~N@3z<^%@L7$wq*PZS8vDc+N=K+Ll4N8R(J!{}kCWuJydqiN+bS#)R5uveYnnaZ*mV{HhakpH@*4@_J zqc#Lwe+L0sSY(`tik|{JUkLQS-0Izy#hGl0R+^Mba zOgpJnlZbqdP+tAx1LUvR8gpL7*|g@k{3hkJO_`k$Ro!m3T!2f5@Dcx)hAB{=Qhj{M zf%1@?50)^c9Y6UEl;R8nC6Zgl5Ib)mgh(nCPBRhEyEz}6V~qJ(2E*5RcR1aI^EtL+ zsA6Pqnbi_De1=+_yF&6oVq?XI#+L-qDD+k`)M~p~C!+GT2}OHXB1925T35BB`7*2+ z?ekE<@}+|Owum^~y=wYaCjS7wS>xHq(_%%(ZwgJeT0FV!itG>C`Ye?jNZypP9_8XG zO`K=nFF;4c@1+?n2#U_9t*rLs#G~L_!{^CCp+-^YrCT;O)A2NU_!?8=FCHg#=mRpn zgBde3`$z4EE-!$+JzJbt-}ud3NA{?p4BE^=>HW5U&$8CC6>xe@p!4nV(vk@GfX3^3 z8`66WQue+J*3o;zo$-O>cP=GLM*IT?XtI3T74u0`**?1@3u};lwh4J=Qzbb-c+3WL zD;B8IhAny9l_@4PseOCqOo?uH_)ryOU;6~w(PEWM3sV5bsO8}~9Nbs*xxvBX*;cEi z5H#audvB>Ir`_W@dV8W1g+96`-)mWO_UQPkTQf;5*x#+3rAbaxBPlyPNh&Lh&1JEL z6lERymAK`#J;NRP{bWsKh{>INL&pv^jT`?)UX{q4l41*{u1kR3Z01=cJe%eji)>o? zAi+RSab9QX9=e{%{>J^qf|qqF(O`T~;R1idB1e(UBHs%bIWzs52S{9X;QE?cXN1Eq z%`1wZqf_v9yg45v4}~d6R+kEt)(G?VXgcn*zBBn@_EfKQ69TWy<=k#aA!4&ud-K@J za-E>Ys_flUV*aCPAx=zB28SIC`?izDMxOe*zaVBAQt?rL-R5ejt#pK_P83SWcT4z27f&Ld`jQF>c>>PMmt1I)ZWLYBXE}*vj?B9R(eaIcT0SV>e`_W znV-4;3I5dg?l7N{77=-%rgb9z(~ciweXW7$N)*X!vC%HC^%3k|o$zIMtFc&OMZois z_d1P3c9WNk`794W`SFaq6y`^7lf9ChI z3&CLHA9|*DW5cy67fmXbkM@!y?80w}d>t@E;Fg}nv?m3lAM9l<2;F~Tc_Ngw^n>M- zlt&>P+P~N%iYW?(n_vD=s*u3wX6;UY#;PF@D{ZY9X5rCFQs-~3CX6=2lZ<9B_X{gx zB7~gBKS@@*TGDHs`AHCHj6f|wXub?;EPFfTqDOlMEEmNsfSnAhzoCa3Bh@3@#%B|F zl!X1miSk!!s@rTyOb8*`NL8jbJng7w!0+HuMsXHlE!XeR3oYAfFq;3UXf%EFG%bLq zfT(6x=$25OXAzRbg1bT|1G% z6>?s4>rPW8IVb4s28A2e1HDC0cafz JlBi`%_y=6Ux61$k diff --git a/firefox-ios/Client/Assets/TopSites/bbc-com.png b/firefox-ios/Client/Assets/TopSites/bbc-com.png deleted file mode 100755 index b90feff3fe359dbb9411515e5bc3a95061f1f5ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1542 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 diff --git a/firefox-ios/Client/Assets/TopSites/blackboard-com.png b/firefox-ios/Client/Assets/TopSites/blackboard-com.png deleted file mode 100755 index 3692d392e6156c4b38d1e56e4290b074b5115080..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1248 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 diff --git a/firefox-ios/Client/Assets/TopSites/blogger-com.png b/firefox-ios/Client/Assets/TopSites/blogger-com.png deleted file mode 100755 index 33947ead81d6dce936690f5424947efb4887dfe6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1943 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H3?#oinD~={fyqC>C&cytC>RX^>V-hUjEw2P z6n3N}$S;_Ik%^gwm5rT)lZ%^&mycgSP)JxrR7_k#Qc7A*UO`DkRZU$(OIt@*Pv5}M z*v#C@+Q!!2$=Su#!_&*#$JZ|)C^#%UA}TsQAu%Z>JtH@-u&B7SyrQzIx~8_SzM-+H zrM0cAyQjCWf5OB`lc!9bHgope`3n~$dGXckSM@cmIJyhmRaR zcKpQ2Q>V|IJ%8cirOQ{YUb}wd=B?Xz?%uoq;NjyZPoF)1`RetXw;w)!`uyeVx9>lG z{`&pr@4qcCGEXuvuo!!~IEF|_9zEEdd^S~v?ZfjqTf0xUt<;b_y>yGy6R}Al+P;%S zS1$?b@Y<-jQPHzVev*!*^>dS)w`U~prQLk{^Kj8iwdddK?tk9BcRs&M^YZ=wj^1m# zwtB8)=@Q}g{Wb4@UKC_mRPgUP?_QIOVZWm^Yp%U-om+1p&6_{{fW2z=t(jZz+4{Rb z=)P!rx8(VkV!?{AKbhipSJw;4?Jen?_a#*PaP!06FC$;e>@YKSmH$#Zhr3*>`b9tU z_k*p~W|z!QwolypC+gRVwLFohZo9^BweMT=Bxm{gTgQ~7U%%YFEYViz z33oO)v^a28Q#Rb`~tqSkcfqRpd<@v#XaT&djT1E);ha7T;dKNpJJ{tYDMt zzicWgr zAv_clP;Nm+D3p@v3OfqafI*o$U0mg+5p|WrmHBJ8+|KP5*2>Sr;+L-x>{1Hl3-@}h z+2t7c>9@*`EB_f(4K=*99^Bes!fL3&b1)ys zpMxwFADO>OUGO<5QX#nfUf`T135GTjcbxZHU{y`tO(gH7i z5{T)_S(akMwOcc@ifNrl-qI&tB0pv>dgnX2c;ebgOV5hPG6gsbUyqL7RNSg|jWNQd zTZ}*JrU#32qwt34Fj=X3m@3>>R&Fe39g)sixG%GCR zVg6z349DLJf09LYR~*^j6(zaL#qQtYISXg^TGyPNkb88l+Y-rD&yxO}-(%Od;8)9yvdwjlGpNRfQ$?SyR*L$%YFWq#fxfrVq)zxp5&z*xc0>1 z{Z&6UkEzZf*A5(*Bf-qfDqmtKF!ywEV%i;Z9*4IYGiFy#vAb>0dUNKs&C~b2yk{tR zQ#(>{v3^~o8IzvvuV>}5U!L6hx9a!<&vz~2_t*aXc6?b#b=a+Q^Y3l1Os$NRW2t9i YG;COzFzq%susCG!boFyt=akR{08B2hqyPW_ diff --git a/firefox-ios/Client/Assets/TopSites/box-com.png b/firefox-ios/Client/Assets/TopSites/box-com.png deleted file mode 100755 index 7f5d62bdb860e3ad3e23d10edc6fffd6cbd5dca7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2653 zcmeH|`8N~_8^>ocj4k^fqef%r8ZuEN4YC_X)*@UpAySO&Ln4ukghJL7Eiz%U?_^)g zpd{R3&{!vp_4U3#yg%Ik;GT0o=X{^Wq%=*>igO=M63x8X22h zGBq=|u(Yza!Pwei?JqkxIyt+zUb*V#e$B(v%NvKk?(28MKj3EIt=oijSAH^9*VZ>S zx0t`Sf3tRW_x2A$bH?-m0QT#q=nL38lRuqVZdiNa=l~+WfMFk$aECK_i&rtJM?ISEQ9GlLkK7CWimAlJMi zDBCb;4$`#;z78`b>Nagjh&4lQ0$lJzbLBj}=LfI~Lh%{qlIXucVdrYZ<>Dk?WYIM_Nb z{q0YkWR~XYr?!R8d{FF$ieO9`7B=!7wa?Y<*TXvm1xvYhT9~1s3cW-_5yEEZ8ktOO~FR|pf=;6NjWpFr-;I6(|1bq)Pg}o^zSJY&ZNa{uv z01ekZnYU=^+V*6gVd?QC-UJ!z4ei(7S(V8l`&^Gm2F(ea#8=jbjE}YLw%sxWyY)Y z=;-u=K4+(~H=gG3r=zR%Ic2Xllc71!gljrlZ^Sr(H-xT-?q2EH`$fU`eN@{QeVqAq zOEc&xymP8~)g!>xKxv;gX~so0zGccH4dv?>!``pW{ z6rc1qtBc~wHypbJA&Fy}vG(UwTE8ujv*s#!N2TYr+6i_G6!|m}(iZ$fSSXuIZ10L8 zJ=OS`QG^JQPw~{#^k%ij4JQU0&A0foS}!G?74l30q`ODG=7~9kYHL#C)nBc0dK_>c zR2FWfUtmq}bwi|$U-&#B1i#8iW%rBfeLPlnrw#**0JFc+_F!O~#!A zr0k>q2x)6{2}~gopGQ%1kMZ7rF7cV;Z1-mbf{A*l<)SffYgaM-o)ZkiXJW*aeYhCs zvpaakwUaDs{BhL9%;AWAHw!Dey%5}|IoP_~b3Npt?d+ajPmj{KE?*Eb*jG@`2T0Ew z#McHJb4|yYzSTgTB3~0~pV{>{BU?-gB5D-7oxy8}K2de6c+QrUWkK0@ko|Evqz^k& znSirlSlA?#%lWTwACC{hE7(Bdh#u9E8lshh##AZ$7?@N=2>0lS)fyQI2xzT7W9lZr zn@tq!l}EINWX(6t)S8@7U3ek(V^0G&FF@IHo)t9x*0yop!%NO{9e!ABu_5 z8tPJhbd4cDVW7FO0qjCs7V9WK>YfO2Hd$udlG4E%PpPQI5ju448x5uLG=5gbx0OKo zAFnV9o#7(1v2cHw!hE3~Dfjec*@o17eW{>2)^47|e$m%+q@YH`2Q%VdL{yk-6vz|D z_Vz>l4dJS=k23CCB5+#2_#UYY0WDWM7~@#=1+`!ECX5vV#Ak+AseQKNhv1=w_bGD7 zFLpZzjR@k!rnm~|ll41sPRR*9E{aP=4YpGPl~MA}z1?omA$|8?Zi!0m++W!2&?m@9 ztNiJqs|6YP&QT#Zc9tJ;I&!2DJ_>c#e~8pA0&G32m{Yse#4v`vzL=waPxX3o_%82) zuP5CGBOAZd`Io44lZ~636FGDO4J!gsaU&b8BV{`~+_cslJlRm3Nh719OKyLE+KZfj iX>yQ>=8vQK|O9?9?O9%)8N{J#!t$=haEscaU2rMb3go1QPcS$$WA-zaTH_L)F zBK;EA_sjh!?tNyS=gj$ZX3orW=7bCOM={|@}GIzT7}CHnUVQ0gig06=hX@$d-E`fLooj`~gpB zqwbxha;F`knAjg(%9dj_6!!V5X|1POs#mJJN6bl1yoCi$^RrI$B6ZaIUwR@e^kXbS zvZX`a4+wBR@8YuEy4UfU1D>YhX(Wx94xq3c7H)dy2DunZXg$i~_1RQ3zFxwIfK;-< z%Z_lh-H22bh1nCw%xUU_Ih(c+*h2;V%8Bm0!K$KBZMw?SsWyoq8xoR!&FC4mJYiM{ z90z3D-dyew03MQifp&JJb(N)6P%cHm&jaQ9!Ue)<;FqCyeyBzwGf`NC1*lU_X5*=FiWY$<&(E_ldBWV(YsfPi{oW@-GHp(70Mj4y?Ki^k z6qt4JOm> z+ce5~#7?nyzO|+3%TtON`%%8y|Hu^8u&%?`dB?)YPg#4N1`U)x zV3;C!uh-<->*gl*Fm3nO;>X5_YA#uf1n2wM#<*$-L1~qRohCYg$e#-rA)0hH)6nMt zeU#4mrL0R{k(wi^VWPhzH;HWu#p#J*N{hCW7>Zp zS!>Xp1_7AKmgI|=Y4On&eDVwrBQ5Y z2jP0$wC$P3`c9R}#a-EWP~N-^MEM;?TID(5_?n}`8|@!HP+tHwQ?hk?qLbZJZls|G z@EmxYR`t09_#`t&C3pG-^*+>qv30Ohx*S?<_e>ngqd7~(!8`fctGBAUG-D7}t8z6) zisaOsZH#H89mgdyg+pNqTZ<4)UF&^(IJ}XcXy!~%99en-5Va?7a^g|xTV4GL4wjo(T$;hYKbm+=0sCV z#aR{67hJyMTFI@&@ejw~!{@m)f#EXkM}+N089op2ChxcuO@PGH9irGh>&F{LBS9s!(XMeo68if+wCM!dW&8&7=&$T zdAYq(uUkP`qLqQogczJ;h^hUf*;S!biYCD8y6ami$5Go(d^g{7)}G1xrcX6v*f&G1 zgrbu!jw3ANx!7$Zk0i}SAw+{g9!PwdXpyx0nwCFoVUvWx*TdGW`fH0Wu*c2>leE9H zZyx5oaD{rmyZ_kpU}R91Z8sbzib*^p2Q>Gt(7_pmgkh8@jHSsN)ZwAGq;D*!iJI30 zwD18jSLn*0JHvRc;ob5bKD(39Lzy&60TRH8n+xGDUoCXWX)7>S*5)#!&3BIXqCOvsb5EPmYG*fSu46FSzQG<;y}Z3z#fN}fd@y0ng~vxP`RvK5 zeT|J43(MG{Yt!4{;$Bu7RUa0eoJouCTLK+$+PZDj84vq2K`+uEBO3PZf+>d$vWbGM zKLyR&Ji{)35_HIXhLn8y%&=RplqH&5t?nJ9C(=~7f|}%d!Ga}iz~hbj9>R?a^n8Tw z2n4p89W_T*Rv=!CLx;(lB zn(~`d7McUFWZ<1`zYj>KES^{g`itKd|H!($%V$2@THA~t|7d`#c?-RF8 zhL&G>xslE7Rq6@mq#8$MmBr8~920s`-*6zf^p(e;DCAwg3J@$mdk)#bl{zjI<}MXO zyXh5FXBVg7k}j|dy!OZ?zt?MwDw$>OaoAtEL<}_lqLcVF-O?wTwwrA;Z3v?bV2ge> z!ou%GPOz;~kJ=!tK6U387j%WtkP19p`#qx!XY|-uD^s<7_-#KWjYIO$UZUA_z91t8 zdiCOClFj~6USS$BW&cv+`FC^IFniItN)aaw)=}V3*y}ww_-d+Oai5@W-*zlgXXEi3 zCti}0QD_nmpzk>f?^RWK8@^ldXQZ5md?!)M=z6DBcZJajg0X(yvw~n~@`n<@Q}_BD zQ=hE{d)=qIIlzoZGw4LO-ORPE<{vBA30wg33oA?iir<%a5eGODjg7VOaWE3ZT}wV% zajzA7r#a--MF4!MxhN5P4;?t)!$WzQW%seuu3a_aX{u6{Y#?rbczj-IRj~i`Wh`}0 zXTTic-rD!c-Ezhr^m;(h_L=`^)=Xca2S$x$l8;&{?B-|1NFOZ`;AC$uYiY&Ls*C!C`b|yFqAA`Ggi*7Ix>++gas(m)%aqD`_N-9&bPlyqFjO^7=+~aJ zH=1Yudga_JUl`YH|2H#Xy-a=tz0HrSnwoQGw)A06qTC=WwMBeHUDi_T?u%4f(zk|6 zL<5`V&lwHVjnRp5a1t~Lof_!D1qb{`LQ16 zFf)F9(B&kj#=#a^^k!0f@{6fwp{d?oGbuA_dK2yhJ~)ZcA~qW&#~pUNif6Jrvg1f{ zCUHIsBzE?aj=;h1+3s#AQ9uh9Mkzbyxp05mjqfg2bRgi`%$pF diff --git a/firefox-ios/Client/Assets/TopSites/buzzfeed-com.png b/firefox-ios/Client/Assets/TopSites/buzzfeed-com.png deleted file mode 100755 index a0af65eefefa6b197dcefc9cc24919537b7d40d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2887 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 MD{CuND_DO1e=!6{F8}}l diff --git a/firefox-ios/Client/Assets/TopSites/ca-gov.png b/firefox-ios/Client/Assets/TopSites/ca-gov.png deleted file mode 100755 index 10479e67e3a763fdf1755653d5222f2fb1165f21..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14382 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 A>Hq)$ diff --git a/firefox-ios/Client/Assets/TopSites/citi-com.png b/firefox-ios/Client/Assets/TopSites/citi-com.png deleted file mode 100755 index 415b8f8190c33345eedd996da259561125c16531..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7050 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 diff --git a/firefox-ios/Client/Assets/TopSites/conservativetribune-com.png b/firefox-ios/Client/Assets/TopSites/conservativetribune-com.png deleted file mode 100755 index b808aeeb7cf2641e93b1fb977eb23337f7ba5c6d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8064 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 diff --git a/firefox-ios/Client/Assets/TopSites/costco-com.png b/firefox-ios/Client/Assets/TopSites/costco-com.png deleted file mode 100755 index 42827a58b179adba3923cf9c9efb5b4eb1bc8e33..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2810 zcmeH|`8O1d9>xb{4TTY75aKl$-Wft+EZJs^F?VdkSd(34%@!kx?953k+nAihKR);_Bvp&EvYKm$#3vpMSuOo3{dkfXZih!i zMc;{uCC1&2zn5@7G3h~aN@`kqMrKwviJX(0N69aE_~`MI!lL4mr_{3Yipr|$n%cT& z^$pF>Tie<@I=i}iUeJ19zUu2ApuZU$8XkE&IyU}pf-yNYJu^EuzwlvkY5C*Ir`6AE zf30tP`O4bd`g?n4cW?jO_k+V9KYtzlR+oNH0{}QDkj92KV&bfq{&&)o*y!79MaoFq z;Ly-bIAy$Z#KE&kRL8E*u4TQpx;eLCIHxngN2{e@WwI_TrBObtz_ts73iXHi^2`Cx zF_a*NNF&v?@3CW%g=>#Lfe*iu?Y~_c`|jWFq)HiH4et1F!|81wDX2z=tc~7K_7=QV z)Abr_zL44GQaUR0K{7F5TX;;U#2`FL#^TuOL6cp0Qc3apl<}k52GOM*#JGaXJ6u;( zbZhDqkuujm-xl_G!@_bGF{5cHa22S^=WrkMW4T9Hs+_Ul4RbNy&%b%toC{$^$-_Pt6~M6Ma3^tB8}&t9z+5scMGYi zr;V#XYT_HVCNuWU1Pi|_*QAM*!p@hHe$CXvGUJF?^>>9k;0v!nzMsN2&qg>V-WG1% zLR=nDWh4Oj+k;)3g}}L&@)786qnv6C{egzV3Wo;MRHF2}yBQfMs#BZD`Sww2-LK{R zd{t{JyK-+K)=|$Sj~i(32n1@G!K3o6!fcT5mEOjg>#Fh3ehCb9|5DKQJ5ruH#HCOn8x})pkW8+I(9yWaZ z6$JG}_Q5Q1DDl?dA{C^v*UC&$b+Nm)Qks9lLWV7VWNijT^3+LU;UN1T92afMeYNK- zegHEXc`x5%8Kndixpm#ZuJPRG?}b@pc+6zHFs6oIyV#S&YDW|MZ$s=dMzv$*=!OCP z1D>x?>enrn8u{pfvyL|I(Q-i?*_=p-?TqM41`RoTZ7U|i_p^zw&7XOLkIBXCTKrwBHxe$MQ0wsoy)0CV3WqB zn|};4wkY&KG-;@sc48jNQs*&Ns=Zzv} z%+^(dm&n)KEvBWoOkl6#1XY1~e(23}nZ$j=x z=&NJrO8lH9)-TDjzNl2`WNZhws1_G`!1)oD2^;C_jNm9#qDl`%vi{}mpOZx~yr_r2 zVeUoHuZq^G$f8nYk%#>l{dv`4QrzJ%k;=UD_9c2-g=7;GLoih z_%e8=*T$ zBI)LpmK&HXn<{FLev#{)t+->uNqHcxLy|5e5GtqB*3j)|bt5s@mZ> z4@s-%E?*!Lr_b~X+Ri!3N4d~k4+GuRYsW#w^;CEzRCQ5-oQ*7fEX7-q zs(k?IQmTwmOwUqc!XTR#l>)stk;09-nxB*mxj5OI^9)K5an;6Ea(UC9@HsCnOpT-8 z^6b6ISN@>W0nSZailLa{i! zwwZz)d0=p#W92z8!ZC_#h{}H8#JDMJ)75zBrQ!g@r!;~q<5y;9BYVB^?`i3tPtm5{ z#FY^-=J$HcI3xDh0yZH_BR<>Hp%D`&VLHUM&+C%Z09qMksY&z3#!y>p_xL`Nwsfoq t`5>(sQL;2)snGX7NI3z_v*YMvHkRhrP|C<8>;&%sqzT6OnUP!kzX8{f$_M}e diff --git a/firefox-ios/Client/Assets/TopSites/craigslist-org.png b/firefox-ios/Client/Assets/TopSites/craigslist-org.png deleted file mode 100755 index e1825ae0e26521d5e7a6612fb2f542c8bae96706..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3639 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 Dx*G4R diff --git a/firefox-ios/Client/Assets/TopSites/facebook-com.png b/firefox-ios/Client/Assets/TopSites/facebook-com.png deleted file mode 100644 index ae85c46988212b8d2a201e9c31766b4ce3772738..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2689 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 diff --git a/firefox-ios/Client/Assets/TopSites/faithtap-com.png b/firefox-ios/Client/Assets/TopSites/faithtap-com.png deleted file mode 100755 index 7ade921c99b7a04f1c8450538fcd568025d54936..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3536 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 XS!td@5BvVVwG`0B8){c-62kunL&NtQ diff --git a/firefox-ios/Client/Assets/TopSites/fedex-com.png b/firefox-ios/Client/Assets/TopSites/fedex-com.png deleted file mode 100755 index 4711a9ace77cc84f1ac6ae9e6f0f767b220bae53..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1830 zcmb7_YdF-20>=MyA1u~j29t41j!nX#G}d*rim}2-MaH<~Fvd)XjPiHc8h47Pv1}}7 zrNWw$OSGoU7<(L=7Ma4BR>@^B?VwF!JLlW^cFym4-uL(E{rnaL27IHbZln$XfaWn@ za?odk{|*}Yxd+^$h5-P%a*XU5l2N-deUYJ0)f2xh>mwyzt+n?q0Ng@kzIHeemEffee=hGw-`zd&*`I?NMs`uL~0b0)v9QPMtb6 z{`L`yhfQmYdj0&(uRpC?L+;gLOo#tlPG}vHx)f`^^RayLykiDdYGA%o(`_rH^58re zgS+fiim8LnPHgz(|7iQ4Z8*=?^eYPJ2dcnPkNu|F&A{=TG(ndjsNOYC)q$`@sOLC` z-CMiE%(hoXBa=*=p6vB7QC#T>ds;E~otONC{78L;H$EFe1aV+%>03na=rifad(J>B zoG@_B>?<4~zREp_DrFbXXtl7o!(xIRjx={#bI-t!RRSo@m1VM+=CTVdgZ+#WIzi6D zR?*Kc=qnxC4KqXs?V2V8x4>R-Q;T0En2~zFvc&Na({hO{TM)}mhgd;0Kq4`|5#YhY zA=Ak1>*h^PN=w#-q0SVrBELp<^tRptN)L7bMpuDdd~(K9i#S*2p?*xaei-(xX}jiT z=E&>$Nk=qK+tGik&t8dmm3*0!8Ix=1BP8f zg2v7ZKi~C|*wKo_>G&KgSZP0YA&0V&Yl9kna=8Z&QUu{PkaIoZi~}5lu-670_0To+ zAN!p@xiz$5;*7$Odsy7W(rkJwDnK*7QD^gLyh8UraseY5)vCwK8n?4r2&_yGQrnoI zpS>*BC75q;cMi)F>p9%cJ_TS4KOS_+FwRJNT`sDJwt#at0An`(-8?GGBvl1DE6OhH z!Yvt^ZIy4MGDtRhaGD?sqxH8?yvxwTq6=NMS7p1y{^~eDDByq~D2`x2# z+|$sBs99a{RsDIqg&Cy4>7_wC%DNxL2tbwG8C%x5I60vm*-H04bS!4X zS(*k~{&~{=I^}WiLWjpr?;8=->i{Je@RAm%H?ky<(}KPgSO((q3sMR zCUGgZ>c-XbhaN<|t2HK1L}qii%q$s>7vLD(f#?6m`RAcyd(`X}Fwg2Kw@ttIK{?-m(i;rUYUDFY)NmuU- z2rGbC!C|>e9nY0vnEp5ClQUPSIvo0^3zD=F@o~{ydxVE)CZvueoOmFVw^n;AuyP}Y zr6l&nrSJ{=waIO}QhOlGiDk%Yi_S7|k1n{U?N?bPrGML!@XCZ6pOcioGS8Z3GV=S? zdq0S}lM<}OO!oPxL&aGP;p%zS{`RUz)QM~v z@WtMZ(4H7EZD#oKOfcIPwVQijl3CdN=m)95u7}ZUw7>En!L}4->kY9D4!`oA&24=m zGm5ml^a~WPpdRjcrnek-WN!fB7Dka4Q5i)l;xA4Im962Th*y6rUm*yd&qiQNes_Ry z8uCIQ@1uJ&gHCZvZihcy*X3WTY&D{#oWw1;x%KyLG*<^Bb;X;RJr diff --git a/firefox-ios/Client/Assets/TopSites/feedly-com.png b/firefox-ios/Client/Assets/TopSites/feedly-com.png deleted file mode 100755 index 87beb5cb8e89833d88fb9a9df23ebbcc54667771..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1802 zcmeHH`!^E`9N)t{Rx^1^GF=tPB{JQcXOYKTW**UE^GJ!jx%1e=dN3tiMb2F!I^L`j ziaYZN-3sYuw;3ZfZ_8sIo7vs{GwwO}d(QXsIiJsOpYP|KFAeSK0)y^{0ssJ*o2wH> z#*}|o5iG;?$%1VF0LVal_&Up^^#A$qTmU=AOpgJB}_{Gx;?TzvA_47X;5O@K5F(?>^4+#wmzZ7x# zN@P@gLQ*mzl|;_GaVsk)|F`=^4@&5jPpWF`>Kj_yUbS~HJG*=O2j0AWKREPZWRx>L z!JC}=#-E*ETo!y^Srcw-Zf%RiJCa?@Ff9fEkV|uOa`Yu|md56=J}&C4DIHZOu0~z* zc~`}G-#j;65R2}Aoq1Nzr@xyGDgpzbVJ@7}I1&^S*nyybkBns%} z{@53O*yn$=ZC@bmi;wJ1y!&eURDUDU3S8bQG^%(2S>I<7iy?X*SI~5ze>Zaww z-9!8KN7CT=N;g6^uwOvU#$rr7Q457uhtSwsVOV<|C(GW4*zdl0|`YIY2Cmni8x1NAN z0#CD$*LeN_aLW&(pS!M%9-u6YDIr+O;W(3l5@6aeQ5TpvQcO)Be%_yu#PY;ET7w)$ z=U0JJ_KE3a^>ZM8Ew667$)>alkWwfX>Gcq-4-PMsn?bNoDYn6)eIQ8LkPi;p5(3y2 zVHiR1Suu1&cQK{j5)#4+ZX({KydEp2>Z#xb);w7Xn*8GJa(zt?g&j>44w_O6j2Aw^ z7eg8LEu{N+XdI%CslKQT{<4H}jJ2A?zmw$PL2*VKGP4E{QDFul7E($B=cHVHS5{MI zDj7fZ7)*Cjigr4KS?itZdKjE4q1#62MhVs zz3rjA)_oTvhTJ3_&teS-gSRRUzCz8SGN*9Umo_zw1ouv>U~N?1}NTYbr*WRm{J8RbwexUR%qZUKS)kTKC-7 zUOhE0V!RVm_eikAkT%JbtuR$1{qk2H$6=d_MwUr+Uu=BJWZM~!>#%5&F0HeIA&y=B?Qf4MXh5nS3cZTvc|SQ4qA zxc4+7k>k}luL-j`l++z$ubW(0t7pcTJ+J@uM2unFD4bUv-J^6&;yoXJcFVlD{2b&c zyF{P7hqha@`>C&Qp_x>*9AS0b2=>O0E?NzJ$W_L*%$dZnTfbOueY0~b(~d+R2&e>O z9wE@Mpe?s0hhG z1vYnbjsD&GJNWqq fZHQCbz!51MsV$dh*>F2$4-(+!?CI2a22cG5agIl5 diff --git a/firefox-ios/Client/Assets/TopSites/fitbit-com.png b/firefox-ios/Client/Assets/TopSites/fitbit-com.png deleted file mode 100755 index 9ea8afa9d1dc1e6f9de2adfb252aebe8414f9f31..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2903 zcmeHJ_d67h13u@nFC0!pRV2tIUWpx{u8vXWB%78{znGdzxtDqb^-tZ zXAwr0us{FdzXbm85(pv=W&JJs_ds(K3jhs}7IcA*o`I2xnFV~2m5m+3!N~>XzQn_O znUDX9fS{1D$W_s6V&W2#QrD$rWN*mblvhwxQdUvDbz4ncL-UT7_FWyAuAV;Jz|hFp z#1vs>Zee-P+ScyAy@R8Zvx}>n`=iGmo?hNQzEAw020VKn6dV%z0{Kr^ctm7WbWAKN zJ|QVNB^8~Po{^cAos*lFUr<<7TvA$AUQt<9U0YY*(Ad=6f@y7Q@92Ep)&1se&pT{y z|G?nT@W}fQqqvV_;}erp)1PPXvvczci%ZKZt80YyjW5K_t?iw!yQF>cH_G=P2R{#w zsK+O#XXn3uM>_dM0s!=ya2+kn;Klv>XO1R8e19}xHp;H}^f7513$usYrMBV8fjT*t z#75(X?nW|cqx0x-H)tF9pi{leX{l!zyV*FH?6Yc#PBs{tQ@D~w|> zO6-Vr;0P5N0b%>We<<3b-{%&E1x-LeojYE@R0iPoGf{#TfjRuEK?xX6NXM@ANk`qO z!h*134A*CK`apcWrEe#Sj)R)49;f$tf_f{W$^C+S?tX2`s9?T8*ofw0tfBUX!d}-@ z%!3z#(|uB6K>pL-?w#&##HOn#ejWXhJ-lqs|c^CX_hz9`?(EbwvIBT}eM z5lLjv!a-rMORv%B?D}kK7dgi_6X9u&MybE18O4-JvDF#(` z%*H%ZY3kKawHBUu=ijmsqQJ-fQG6X7-1MV9BNX|~{Bh}<^~5piQN0Emj zhoIK9Slr^rL>((Ph2kM@$(5On)B!6y=X)yYw*J{L3w^+E}ZTqlYc6mH3kf{b26EO|Hg z>6wpJmBh3^lA9nuxW*0_vPO99_z_F zsoA?kO^Fl{=>7-XGKK=9KN|p-K!#o}PeCi7Fv!`Wg=FC!bHq77<13xJ0LnFNDJS?w7(x)var76^A#;(dq z%_8KI9sth!gj;~bGH!PqXoRtW^;E%4$lsa5%}e zuDN~QwV8G~33D-Cl;W_%~TLTEBvb3J-6${(2-Ex36gsUrZ?HWV^`vc!MhTsw0QW|yM3=551F6H zLn7#)tV?-Z?`my7`F4OP4K|cExmNbOFDwsIym@N_ghnQJ!M9l&yHfYNSY`4x6qz5d zPDyL@{GN&9ac}!*RkJy1=`nB|RtCdFY{f6*#d5~LEWvSwE-ti#+Ti~9?%48hMG<1M zXw;O1nDlzfuTT#TLpp52rcwc6$%o^msz|)S@5DFBkDBqO>WfbAebhRM-CW()QU({L z`;-IYBz#D3@G=q6DmrB7L6)J^d6(!&;|o?sqV?(D9p4c{Dl6R{zje)be8MgUa{tK2~2YppP9*$Q7c^n)GuL#H1jK_ zGdTe2-Dbha1B|1S{x*`rqkgKMYN*W?f?s3;Z)HN@@Bh#$$Q;O8r#NsK(;I>R{s;gZ LW}?%i?G*JdW-tYu diff --git a/firefox-ios/Client/Assets/TopSites/flickr-com.png b/firefox-ios/Client/Assets/TopSites/flickr-com.png deleted file mode 100755 index 41db127f9e9073363730e5c627bd6892c686b2e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1832 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H3?#oinD~={fvGRRC&U%VRmr>F(9rOYp#{i5 zCLvs)2m}GSXbOnyM5=*-Fx>R zJb3i@@sp>|pTBtZ`pvud?>~I_`0>-{FJHcX{r3I)kDot({r>ak@85s_Gy6Y0-ByX=8+rST}@PeR{dz zs^eQW{FtJ{?DW)tL-;<9`#h*%fZ0>t;U6Es{HpQj6GISJ*=nfEj-vRl<#Nk43U5D$5mh% z*6#YN?1Uqiz>H26qnzzZj3xJfiF$uY+^DgjTxOEy(NH;qCv4MR_RKXn@L6+`ZvHx% zgfhKpZ(FAeBqYfxtuPCb+OUUBIK*J7ZGxMk(yGL{A_>0AYOAi?mwAxv&|<11$gZPm zv;XHJgM%UuCN_7h{vyikv;NSLm+l`JZ$)=3vI$RYNH$ycVqYJ7hf|1ZG#Aq(gV2p` z2cEE5G2GH&iEu5q%lq=1e}m6L8+lQ_JpO_cOIaQqzn0rDwPTm^TgHtucJ;1hSUvqq z!~48v49|_K4oJsxCrC1t+>qHI&Kz}-$)lB_t7NAc_A4@oWN~pET(D;r z<8H_2i@ldMbQ>IKOmnc}3Ao$Nzd^H^ab84$-~I%KEfe@Zw9oCIEwj_%!B34@{5LpR z9wg`qaqT$7uHwjOcqdasp_#vel{MzsJ154kQF05IxGK)2IxuFe5WK)&W%ut$EgSPO zX-2&S2ib5wwjUCVaS04z(jS&H%OCVmwQG9BSHn4X$`7GeqQ4}=4%WA=ith;7FQQ#+ ze2aCzWMlsEZjoKGtA9IuTJy70!|ScPQND!3%=Sx#r);N*H^`s9T5q_qYVEbvH=|>p zS6GJr|2n76VWVp&qw8e(3YX&8mx8@+)w8oao-R8w;Z@^0G3Z^mB+s-iyr^71kxLoxVtNEwzls6b13PC@6ONXZ*{KA zY1*`;PhTtvxSK5Ax@+GoJ~};2-PU7z*kS(;{k2K5Dc8!FzjLm8tMz!rwX(&n z*UMN9&$)D;cG+C-ocl@bz@tyIZa&&HC8zM_u3cYwt*8Fl$MRR_jE{d$3`5M_TdXcI y6-(A1Fpa-=*PCO0s`8#)sYn^2`{=7re_7|P)$-*Q=-dV>SUg?*T-G@yGywqJuu~ua diff --git a/firefox-ios/Client/Assets/TopSites/foodnetwork-com.png b/firefox-ios/Client/Assets/TopSites/foodnetwork-com.png deleted file mode 100755 index ba3cee06dd54ebedada4648f487474b681dce7d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3889 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 VWJH9n__zIYxHx(^Jcb2l{s)-3%LM=c diff --git a/firefox-ios/Client/Assets/TopSites/forbes-com.png b/firefox-ios/Client/Assets/TopSites/forbes-com.png deleted file mode 100755 index e813d38800379f3049dffb91e4aac63f965520c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1850 zcmeHH`#02i0R4Qw-+3?$@*EpsB1YCA#zgXsAtX&1N*+6DrcvrNJurm6dYs~*p~ne{ z9+qlNUPXlOPT8b95{0sjM+aGtmda3B{R#Vf_ndq0xxe0X&rRh9Y@||tp#T7=zCN67 zOOE}Z3bLfLiYz4nup`%>=d~0Uf8u8Y|EGa`ZT`}1K;6-80f7KOFhU@bRa7Zz>QoJ_ zWjcEL1~fw>;}s@!i&a((>(w^4OnV0>ma~iNI=A)i=mt+O?~OiwoBTI#;cgA&1qE;4 zu`@J0g1;+rw?McjYG3sJgW^L+Vq)VY@d=4Z$FY>tXU?XkrDtTGlV)X~zi{!=<=iXz zR|^Vn6#ZUYa_jb;KV)~y$}1|X?%l7ct*dWn{8QfC@~pM3z2n8puI^Voy?t-q_P6$@w>2|K_60LJ zGwVhO1a&{}a@lyT>~;Ku!=c4bmD(Gz5Nm3vL%5S^udei>LA!y(9%U@&Yibti zBa$AVQ@0k>qJSp`Ep|A=8;{h$$o&I$u%bQTZ4+Rx)GeEc3)e(Y9g0fgewy1C)~Pgj zxD4jEOwMwF7Ez3dXkc;~V46BwTgUEs=z=HA7GywWhKL{+@#8>YQBPhPO>^w=7p1ha z4zBvN6)Am;r{3(Si>zRfY}Rza-qmUZoA;oGnt};p(Z`~D*yTN*4AXv534!olNsYl2 zy$`0w64=*)-oj_&ZpYG+oB!_1sD4m-rZ&}_f<9N_6YOAVqsH)F%e1!Oh|=VqxzC}E zx~TOxKbme{NY5%Ge9lu_(s5TGlszt{0ehw%vNS9jIKxB!QtBe#o%AkDr04RG`z0iH z-6@E5O(geUK!kE|CA@;yjY%V#F!x8cz1aRE=q)RhHS&;u#|lj0^0m&4y&2K@0yKr% ze|Yn7PbQh04z(Nr5<**M6LR|i;HkRexGE}o(#irKi22tCNRp;2HwVd8k(db!^mX*# z^;}>0XgLLb@u;-fg-NV?j%OrIPk)esM1E@MDmUl7*` z863jf`Mns)!_py`rN}cAniZ1#>7OFc`H^aTu)J(2$Q)yGtoa_ya+AqyO0${s@VF3` zN68v2S`b1|V5_;j2-4`->^13X4t3TtMjW~|46$jraYJ6{zzJx`V6yh(Ng=B{W_##* zCm$74He;lZ+@KoLUb*R5pxg$ghyMC^(X2@&iG4uH65VmaKIOfB7lgQ!LTw?W#0t`m ffoe+0F49*xWV~H%_rX`of4rHmR{%%m!9VdI|L{#l diff --git a/firefox-ios/Client/Assets/TopSites/foxnews-com.png b/firefox-ios/Client/Assets/TopSites/foxnews-com.png deleted file mode 100755 index 0c1cfc983ff398f5058f919e48c54e5271fa5366..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4308 zcmV;_5G(JAP)|q#WXb3UX9hX$4!4mcs)Pw2D?m1(l*m z1eA(KF)E0lT!H~oilsm_Di|b?07*94Pyg7rZ|8jPZ8kuH%=`m8^N#tv_hx>-@BC&G z3LQ>|)8X`kPE-&qRdFIAYyP|SxB@afjtkL{|8ekABt&_@s$Y}t(To+=AjE$CPrKXY+>> ztvdjIW^G0{>oGGuo8OX3s4D=X9AjJEUlgsly^fzgcSJ|;4mY0PFJ ztJ%tK^2zjQ{`r*F1ppB?kj*GMSsQXXdE~K{#Vq7?rt&buxt2?4MV3eN8?zZ|Gk_A_ z=U%Sj6waVOk8+{4DR)~=y~fjScob?QfD#rmkwNt4ddBh^t0|6E<5a61XMU2EboOX| z3pUk)4p0J6#9VrCJbjtXS6a1vYY))ha^jCXyT9AHnAY4u9+86&;4Q{*4cGA?OW9|s z_LQX|VLrATah*r=e@_(HO)h`sW(G5rtp^i8e{y_Bf*#h9+?>9mfwlRqm6v}vFLDvx zm}$kop8@!Pi&a*8?k39-BaU2KyG6W zdukVe1(wFt=X+!QE3D0L$`;?N6*89gybxHYH~;`9SuH?QT4H@)GI%54Z58nh*Ygnn zt{nhue&DCZ+P7Grf1jjoEy}xeVkjjCAAs2kJki*FmT{~Vz`|#?i*+ z+-$7CcS)G)M*ju-4L`*9>*HS^d9ORHbm6dl*mW{UV+P0PvVa1u8Ps zeaQO!vs1p+4GiWcK0ojPu1rG9J>Am$D{JU>zu^~5s!=z}7eE!K7@M@fQ1>0H^1G$R zZn%UY+){%slrMlS#wML*II5JkuGrB;$jt(e{z21QT+I~94h(>|jR2l9)Ew{Hhuf(T z^8Rpmqm-u9sU`tnve5+oTC2Cuoj9`@$h9;10vK!naIvA@KNSz5kmqfklvMRKkz%&~$-cYZT0wC9CMktXVHg>&>=tDE9UK*_# z#yY89Z^QY1qx4KB%k;UR0LnPhpaSV*@%w@Rnk;~Om2+)pGG|+BXV95!_gz?H5MI)m zBlHzF7|wAXdxHY_%s2u>wdZw?<|GFPFhc3!n+7=M5?6{HXLPy?ozg|d9&AJKKHyoy z2_DdDtuUwr!2t{s&h#(OxdbsE%}VDLKh48YzsXQ`RWhAmZ-Wf}rB-WTN&v2L&+|BG zfsYDtJh=cYH~1f6a)IT>4`gX@097$+W7z&maH!@UpvLEngDjR z!A#nfB!DW~rwCva0P8$rSVH{RndeRd!2R0SmZ#LXUAs&JSIIX47{}*I-Ut+W+;%Vk zotzr4dYtLW=ClPhYn**eK8*_&8+%C%cw^TkDL}j^qJ!@G&7C*DljY z7-oV2I3MpwvS0ujy07=E76&Rjc|D+>8OVf?mC0A^bUqsszBl=bq^6z2uh9v%z| zpuMEW=Su>(dikmv0Pwa|EQy=28#&5Sqlj&WUL=j7hFIlHM@RGlu#d)?WED^H_j;-| zmMb{`Fu;PKBa6vrl0_`fWIZs(P;!N3;5LpIA?lpcirG5aq3)O!i z{GLxepV2=R0Pv+n_%!F9M1gk=%5_sW-o4lu;5EV-zr>Sh_zk z^)!Aw9soq4<0rx(Cx2_t_%x&X0HBJ=R`d8A-f-`!l2!o%xZgJVkL&CJdKh*2U6Ok= z&^JJ3BcrsuCW*+6GL|rr;dJLh&Zi4kGm@A1Tyo0t8LQ=owDwf;n4#V)HUJT!+h`() zAa_fn|G{49vL8caHb}v(@w8qVQD+*3Bo9M-?ZL9w6Td^pbvQ zF5Oo?8A93p(pA5sp<8mQ`|G>L`Ql8528k(I;(xwopvS%?=L#nLUCfdJEEFO$5`42Q05V)Xz9s-{ zRjm5gt+7gHT4$)o06VOc?eTmh1+I77M+Pv-HG!8ozf5;y{Y~*(f386QQKjxAp$9la zS$SS&nZkP&xF^8%ZgY?BF9YbV?ClWcB2NI#q*WZL0f1jxmgH>L9Gazq6D^WNm5OL*>5t0CA2N2>S!6;4@z+Fl_XFM&|>W_8HW=U#Kls_02cU?qVEs`bf zGVK)sY;wQCSDjyeE^~5`Y(^-;Q++?iaQC-Q8>cN%-|@qWnauIhYb4%E!uN zUK2;?k%qxHT@|Rvv6Vsr05o;OR{a6=U==G3ITn1GryL*m*#2VB14^AwR1A!nLZQ-; zic7V=;$%XEX~XTj<*GswfCrt!u5+fxP6-4c5q;wiV4$~Sq9~5>Wf@l)t{Iawb_l~= zm@TZfM52L0dY8&3G#hRCmi8< ztuQSZD+SC603H?=oUC!0*Hs{vrOXI-)Iubx2jEVRndd$rXwm(YrMpofPT@RPx;w`A ziYEz6CIkRog%4n;V-FSzwuy~HJWwCAkJ*h{j1`` z<2NdR5}FbsjZMH#8WWft z-fb7a3Sm9aB*$pM2f%t`|C}0tJZ+z<_`li#cS@%6txCLbA{9GBx>x>41~A^`xS3|c z*zN_uJ9NzipaDl|`EQE4bF>nDCawd@5lW5_YS!mFO`Xc)VLE$k=hIgP(3KEb>;d{3 z#SSxo0*?!r0NffttLtew+e5%k%R6_0^=vzs#uY{nu{o6q0DEcXEGYP#bV778SWhMZ z_C2PmX9;=*&(8y*#&tj;{;HfK!WYaF+OUTlEsi*iT?qi|UE6zvb+->QfcP6za{#`y z>_WHE<7&%XJ0g$2)6Kc+hthdhDqVCMI}!k5x>_EUv`|KWe*jyptGcQOpvpMo*T~sJ zW4*X;>TX1wi)6{QyKQSxm!?%iv;l zW_a`fm0EnkAKcDyFT<3w3yCHG^d-cz?4}v@th;pB0c^AQ2|9pAoNUbUmP`vgzVg+c zYXOHD#IJ7L!T^Iu`J^}soJn(v`G+JI1_uDI7#BSTSA@DNqj)3Zx}cbjtHXXqh+#|* z7+=!TnIEVKQO-^>83nX+g`#8uphSlA0?4jW0M~hp^CLaCblYp}Le0x9T>$rSCS_b`9Q}g=s4%<()dw)qW5Gj?b#-an zm_EzLCGIUCs|Zm}7e?}&Hg3wPMDekDX*ITM5n0s-uuv(_kpih?>vN2DClMxCcQi~_ z-tvkNdpM5SoS}@GdLUyx%cA#0dO|Z#s zP!Zx2n(`v8B;VgOoBjz)guKB}C&E&xP6<&yASXaxsTo7LLg@nK(JU3p-tpLEZ5NA~ z%6P^xjwe}Q+ycHL#5e}iGpPWkLn&2+=*$ddACDgxfNosnG5Y@i01WaR{SWn28RA&F zaCt4xo%rc~%pH=C(Lcm;i0c_pEAudJI{h=Ci_a(F%BnoErbb9Qzr-db$Zd#7~8l8Zcd0?UBKi?ksU@ zXHsl|D`pP>COejWrmz)Wtq1V3JFnNkQH;{Kk#b-=ml#%nP6u#=?<{E}zs{1Fv9@ji z_|TD|k76-9c-MUs<^iMJg*PwpnLEXGBqc6@5RK`@Ny6@Nm*TafX)Od04|n;a^ZyC- zqaXd43+^PvOs6cqX7FVJz_Y*>>N{fU7r>3y4gG2%fJ*o2>H9~OI&wvQSLqudEYXMq z$O9tIY=1|m*NBzeUpD~6rI44b0P4A0=MNA9G~2jQp9uh+q&b0F44|AMiYOvNB8GR2 zE1eH#IKx>0u1X(Y%6x(I|LJudz{_M%j|>(8^PTVa1g4S86h~A|XE}+upXNNkECx8; z<>{2xbpSJ@Emx*#QTt)X^)8cQJ>qNma)n{AjsloZJKAxsD?NTlZ%(2mlO0_dOf?kBGdE>I1RNYM_ zL_~GUwxwxnh)bK7PB0Zk8DWP?U5=uvWvn}E&z}7U_UsSO^L)?wKIi-6_rvz{^-xnj zpbP+jnwKZ-^!|naJy?bP{qn1*9sp2i^`cP&8N9`cuURBF9aubiSWnYtG~88n;j*Uf zty1{FA>+=>PIF6p?71WyT9QLlGS^30-V#juwCCs)6oduR`g8mPKV?&mCsFv^lv*41 zD2LOvRMj%d=g(L0e|p%mxVI;Ws(En#LF`uf{CwGi`aBl)uOaU9^|1dDQ#i>Rn31k! zUArsmV0oRY>79cY{iTKX_z$7Q9TUv=;ZFM{)pP;lW*R#Lc1CpCjSyvF=<#HSd>ykc z{em(>`oeSTr1f~Krf-J+`EaOl;P;7jT=HVyQ#}U7CA@_%{5y8$btfL-N*5epk7zBD zE1W2Q9X9eJqoJ=LRICqF0xyJ|ZKX7>$_-Txu|=)}jma%$Y1Dr_M?9h)PEkfnAr+|9 zfmPis>w<spJ|V!rp~E!=E|rW{4-1F^(47N^p@Q^kLu4EyZt6U%gvyj&$^6Y!eTE z!U@g%-sUjb86s0<9M4o4_-Ji}p7VO^^fk}2L8;(efD_lmSKCKh{>*vf{={-VCDGJ5 zb41ZwvAaoSo4GaKPOQnhuWX1kfy))>bgw+eVaWFO5;Q$3sYr`3ORztBKp=G=i~-Zt z3NG6Hx`y7VEB4?&ah(uh{R)w(>Rb8#TBfQqS&3rf)Sor+aC<3>EuA(iSap!z=$ z1m8VP1|qEh!72CyRzSB+u-8b>q-&O8PUN;8p7#GuW9TrVwIjQ^x&v52x8FEmOYXif z5V*lT3DG;l&~(4Cb2`pkB7=er1ld;;uc$u4bXR%7hY)dd!UAe2oas4D2Lpzh03RJ? zeT=mw_j=hbJyCbL8n#e`SN^DP4^{Xxw99q1|7J?Brnbbi0Vro06h|BEsQa%|@Zyxb z3*PVO;Olpl$$ni@!A!GkaQ)(uGbi!r5q4q{#JyFh{u7}^$}7?7ceHzrF{I$V^5 zIELd!Yo?x{MKQP{s{-Pq__6UfE2;(zom0s&Fpl!Mm@o9pq^>Y?n}v^=P0UlwWLOOS z7#>{JI4H5Qo51o`f0jgW>0G(pC*XmatNS8-Lb$Mx|dpk6EES>3ibBO&k|a`ugn@@8<(dtbgM9F?FiSzL$*+kG5=b^7tL z>fYnO)pejb)R{Vg0;n(!-m7g>Z8!^SjL~;4Yyy!`L*7+9wiPXPDaUj>X~yC#OW6{f zJUEM-=Kao;NwVagn=vlbfwCC#Xx$csE-FOGwPB_NSD20!<2m_J@t}og92AK7k6nNA z5Fx2L~^!@Pnn7QNHS?WEh z@+5iCn7jW4f0;VV1hGvpsOMsuxYL=F2mFC$A6f8d}U|u-c4_LyLQh z`&ivx8Y!n~1hctH?Lvyl%8TDu&OW_-gfVdkT!cHaW89P}NM)dbqI~W%&RV5oU znh43d!P#+lYZ4Din%*C@3oarV9nZ%~bYAYLS6gEaC3^&w0`52e;4K|j$LN_H{r^?? qJ`JWq7el%R9dDNj3ICeH#@3 diff --git a/firefox-ios/Client/Assets/TopSites/gawker-com.png b/firefox-ios/Client/Assets/TopSites/gawker-com.png deleted file mode 100755 index cb2ba8a90d106cabbe095ef1d863150489820fbb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2768 zcmeHI`8O2)0{x6-roz}m#n?@DDN1Mv8OzuuOU4#TSq9%;wi#I~k-Zs28GP+~wivsF zNg+#^5ZR4=seF6qyuad|?>*<i&tx|Ki^U{@)vrr>!jg+4`QpImQA22m>P%GZc2>g%H9bqGI9_l2XX?(lWAg@(PMd7nCnvQc=BpMeVA(hUPVtmiBcWUA-In zXahqdV~mNZnYo3P^-Y^wws!Uow;i!g&MvNZ+&w(+-t)Tuz}v^y59c2c_}9ZnLBS!R zVR%A#L}XNSOze}V&*GlPC%i~ZN=`{lOMgiuWn^Z(%FcP6OU}zL_`9&ExTLhKyrQzI zx~BGRU428-yXF>3Yg>CqXIFR6``!Phr+>tgb70lZt$qk=Itby24e25mQHKKU zgd6tyyJcLUG4_LN3LUjJvS!H;d&f*7Zu80e8U69iwm9zSooGiChl5iNoQ5Ekc`s3* z%MEtK#t@e~U5EXRETJmuM-BbORFVK(@B-O^2cizm4KD1ASSxM`a6VYh34Vt5@EEc+ z4sckuV8JH};HI)re<2tV}kl`>Mk(EWX?vw~*$i`7&7JAx=XOUlF;g^8CPMe{PCj zb4$n^x^dgwWp>0$5|%4*Z9c1!DL)~l7W*cz?#_-_x)bxKBoPl_F z^nDQ&2j&P=-kOxQ8u-~$)B$N*Z}*F4_{imm=0S1zLr;e}0u4Yrwq{fUd#fhGbc7V7 zVYAan?*^d%g=MFOr>lSyO=u=m2JGo{&Gbu6yla#Y0@YA02;K0|L@1)lOL_Sy$MW01 z9F$oVMVvH+@IJFHNK~Y%7!%p7GB`RxoRN*gJ{st|ae#=- z8w}z(BT2DF43~AK@+l0*S9)mQoI zdne|}gJ&aDioVrfs-sW%6%!Adc=Ymfx|@P7(`yi{uiOC|*TFCnsxLUTPq(iIj|>7$&hX3n+|_)d$p4b@5ubsUdrtxD2^b#l`Lmg#85Zd zB4qKf*GK~=7SI=-|6HyZ60@02KDadkn3A&XLgJ&!nL#iv2W~I|P_CEyoX!UUA@BA> zoqTdJ1ej^&8v5WAgTO#i>BQCa`HfqQAS7|cUHgj&-!1?)PSZ-q0cs>5R<)vPJe5*; zLYTkib11WjJ14+@6bw9$e0MzKi9 z<6&EBRQsu!qv&^$cEki3<+x-HkkFjC)i~^6Z?Y#g%AMBV^VVU7SQM&u)34A5H|90i zY{Uux6@64vcrj_7P4vp(HD||?9p{za(o2R6(A}-g?d0Bhp$|bXkf`{XUQ$E((I||2 zQm~o0FaNqj)(eqaQL1RQNSMyMj+w_7giFh6Z;fSg|8(7OsV=RgT)9GAxMz-YqaVE> zL_AV|KEVA5VflAu9x3L+W2!&s_twE=H$R8yo%) DG3lN) diff --git a/firefox-ios/Client/Assets/TopSites/gfycat-com.png b/firefox-ios/Client/Assets/TopSites/gfycat-com.png deleted file mode 100755 index 7305cdee70b0bdbcfe6b12ee4eaee35b7318a9bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2950 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 E5B|_In$-w{sfZN$xy8d$Ne<=$2 zrK?lfTL1uFb#`#K`W1ivAOCOQf2jex*Ac3}cE5AO)yWM2KwyZFFjPcT3?_a6jzFR$ zBo9g*IxH>UeEl{%H~)QM@t>vTm4AP%uB~ruZf)=E?(I7dKX?HEq7XaFv+m@HE*j;cLy%0L z!f^SVnE@ViDD)8~*f6L(|6&Ur-t4B*Ly8RY%FBNT3*v>Qi_)qM76$|B$H!H!SN4Zm z)%jX7YJ-dBcArJRzg+X9d&&69B_?xZ=*QmB;~(84OUBF&`+@{3?QB+m?2=Ms1)S*ws zk@IK8KNPl(G|mJB453x#(nMIjkwdAup6F`35^r?g;YyL1j5WlRf!TI!03@Bkt`wZE zyf>-}q^XK=jt0#Kxi;PI85N;c+oCBgDU8PLT|!EK-brdYKHOVpz+Ia6&DMbcik*Gx zQgf`(-Ypx;OBQDJg=oszMhDlMV)270mcdL>>Tiwh`O~~b8Q>A+YW=Y_#+B2D0@?bY zh0+Xt#{LasO^Nl~~q8X4yrXC0OZQ}TAMIJ$-zPIpF2Qt7vb zR3-1~o^S?kCk_~p=W|c>NC3UlH?zm{t{{b*4)h1HMYu)?sFLUqoA6Yv#}7CxZ&x<~ z12uW`lccAlwQ(bYHuCq}EgV3*byMfP`UVw<>3`FqoWT2WIpEwvMwO>`x2Bong^TIy z&2S|k&9rxWq9uy1YgWM7B3{Jsi527V$nJO!02oG$ILkf$_TC?I#)SV$Em1-^tL7|? zJV^jppCoT@-^?0X(-qQpDK?WxYjoug(8|XE%+6=Q(odPsCsJFRFZa=pi)a`=qxp?d z67@?ZJi50C3}392s{f+g^V(-&4a#p)^GfdUx&#kbb%3Au=*{y+<3G zoL7u*-`%$PZvJM?ro~BYLZo(3+wL|%ylK<^u!K+`P-!vsFE)z>*WNoi3v!5JBbsDa zAxEOHEcmjWLdiZ+r%Ut`0CQe)F?zs)D|vu{OBz?3Amm9AVE3yPNn}$>|Bj333d9m( zlKnP9C>r>tf;;sxkA>70<=%bg5QhZfJE}nlcnlJtpRWc<9$10gIA6Km6XjyM3v^wt zN}x)%hW1l?qH-MJkf4}lEv>$}30dmmrC@58Mr}#9hMLI>u!;Kx;>VVL`>{4v78N{? zT*NggA5)z^uPiq|kGJ2xDHMLHJpN~^EP}N$!q6G*e)8oLh_!N5)BcN-N!uQU60<2CBUa z4y6W`*JD^Q^C2S^lT%~Iw*6~z#5w^n!2Aoi`WiFs&(jYp2)TMJN@&_MeS# zLju&OsTOr1mI0B2CLM3n>o$P3qf!i-MV8|nZV7UqTcZGe?E=WO`lrp>VS+g~vN_*? zs;7j`{-Cg~NC*vtlSCf5D7K|#;WwTM15vLNFiGu}NdwQ}p$mX6NcC0Q@(M%H)SDA% z2vmpz*C^Lr>b#cd9}#>q-4BM#1RR2DM~8xtl#S2!o*kZ@a&Xq7B-K#z!?hLRMZst$ zl$(&CWq>oj3rf*a0d&Om%Y8I@k=id|K=>PZbE>q4riXMuvI0v(65vKpD4Yg#(5+=- zl^;kV%ixA@(y#7CKv0oX4xvH**Frc-RB8SnU!d9!V9ej=rCf)Ams?m?#otIhV04-? z{1@(o+p?^fh zn^9dyRo}uw>?VNT(jASScTX$hgksW3vvUW1$z6#~p1aoVvKk2d-s)<>^qDFsG`AFn z{;PE~gu@>c2$lAY9`QN6E4vh$cb6kr*$YtST(5n!nRIi4V&d012o9L@7EmHP+iMA=BnFVo0u!e3XP9FA<5EzNIUa26wDxJKmND?A`3(Pixqu! z^->~w$xPs&=Ume4CZ-yfy?(!bmeo}Lhd#nsjOr7eGW(v3yQ6cSdS zDi@^nsfA9KyKCyXzQ+`*7L1_8hckt3_xGX%Oi&4r5`Zt#oc;BR06Qxu%LWTl(tiLL C@kRpx diff --git a/firefox-ios/Client/Assets/TopSites/glassdoor-com.png b/firefox-ios/Client/Assets/TopSites/glassdoor-com.png deleted file mode 100755 index c92b84b5ed812b4b3623c8f18ae9d9188ce62a91..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1722 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H3?#oinD~={fypPpC&U%V{XYsuLx36~(0jRY zJ1{*RE(!7rW?*1sVrF4wW9Q`I;};YX5fu}ckd%^^k(HBIP*zb@Q`gke*3~yKHZe6b zx3ILbwz0LdcW`ocadr3b^7io!2nq=ekBE$lj)_f3PDxEm&&bTm&dJR$C@d-|Ei136 zs;RB3Z)j?6ZR_aj?wK%g(&Q=AX3Uy1cm9Hfixw|kwsO_#HEY*x*tmJ?_8mKS?cTfp zz`;XDj~zd8^3>@wXU|`_cGPMb-@gC& z`Rn(ezyCHazcY`4fjP?4#WAGf*4x{^!+8Q3*gw28%bg~=Xo^`Wfy@4vrue(|$AJIl}g zjN|XW$-HdQ`TSSX&4>4%b*;X3hBfF><23u`MNtpq6RTgJwf>UzlcA@zb=}7OtL!EU zsjxS!Y`h~`6|&9#TD#5yj$OY0_Z~XK!K>)N#NB%I^S^hmj})9fF}&vYN%!{48$x0l#HMaI+y5~-+ahD< zwOhtqiY*0365#k$G0tEJ+j*`frs1;}GmjVZqL%Y7YPaqA;?t*?_S0rg zL%_p^m&(0+_dnjj)bK@;`Rga;J?lTxoWs}fs zVA6mhW`Xr43Nx8B9>_Dv1V|NlWjgG<)F95q+_dmegHbCZr(f*4h?$I?hlRL%FEMa; z&E1_7pf2w)x8&~Dc#C(c!VR8lBxdBsSWjSnAX)yCJDt7P!a+3lPv>UVlj~G?BVunH zzpk;DwS(!P=LYFH^zY1! zIq@bZy3H+U9XfPC+&Ig;Jp3sh^ua*3@VHZCg;ySe~szM0;Wwn#A9d3l>0Q4UtiO` zPBoUfL5E?1d{Jyknyi3q3PZ=AS6g0eGh#Tw${QTZ)dsH2wTo@QQc78ZxX838} i!wi85GJTzO%y*t1mb`ea;5)F;VDNPHb6Mw<&;$Va1w{Y= diff --git a/firefox-ios/Client/Assets/TopSites/go-com.png b/firefox-ios/Client/Assets/TopSites/go-com.png deleted file mode 100755 index 86b97210d8eef6285043c8fea4ef5ca2c3a7b206..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2989 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 Z`G0k|u16lc`Qtg~opt`4gD6rF2>^ho<5@fR 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 Gr~WT(m@G5^ diff --git a/firefox-ios/Client/Assets/TopSites/google-com.png b/firefox-ios/Client/Assets/TopSites/google-com.png deleted file mode 100755 index 6b3c2b2e019dd236600ceb241a4188c2cb2625de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6524 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 XK-P(u@x1??GXPEX$7-RtBo_p`9 zDxkI2T5GMf)>><=wZ<9QI?%_T9$o`*l^MM_tQ?*)b5UZOvL^j7!l zRsiL|zYE~zLCU?SDKIR6VZq3YB>^l;Y5~An`(@ydFDd-trOqP&@5LknB@F*hS&q%` zcXjW7dyL0NjHBUf_k@<$=e@(_thk5r_$3 zSd8FnMvNAX2$YcbUwd@GJu&!JMaAs zn|~J)LE_XqISC$vK6Bs^{Fnq# zCyB0GOHg@oiN_wv3_gwo3|7F(+9ePv6zS1%H^7sCF?qwp^pWSh_J(Huo2H^qAOesW zC9&}hOU^IQED-<%1t?%;{UV?UI!$LGUwD25o)sqmhFJLbIti@AQ+lXK(+L`nvC$~b zGht=zB62!Fk)`8+UPfeRw`XDaevbkSZ)|i?i6$WdBOx#y=LyN$1%L>}Fr5?U=e_of z=I0(w5daG{l3i4yQ;Z0VWNjUIO3+z)rW>Ipf%55q6Q=-JxUuM>(t<#qJhzUV2zr=~ zWw8ut<9EqX66k?yT&yUbxw+4-AqSv`S&a*BXbwfp;-X z?W{fv0MPmHYy&cXAHo*^%QdOBuvF!|#s?gUfKH2`#34BP2*C2qq~P-c_$QIz8Grzt z=j9F|*e4{RfR+yVGQ}h_x`XaB0H@$0U-}}M#?KAxI3P#lGDkw>uhW_A2 z0hPw&f`uei;ZJ^}x~tHj!e!*5-nfSfQ7SL>Bw}MMj+j3I$l}RsdC?oAmm+@Ti_Q|5^k@V68{+V=N122h+l);G63A&-)dr@hDxeI|!yK*cb41hI^IT zkec=By5=Q;AH2bM{|z0)x!&3${A-J9D`Uc(loAtw3Pk`xe^$oCYGTZfhD8azCVX4n zXwt%NE_}Hp5Uqs(Kd2<|{*S=FzmiW`OiZ}k`@y_(aMJ~_Js@lkAYMBtSwZB}@Hs32 zu$`vMcz+%E#$R_EtpIF)9jq?+K;gR;0Q<4qCc~E#fWVpm{xajW%YG$$Jm*@s2cw+D zclbdifv;T#KJaKN_&fpK+EUma_%+;{XTeMbdzGTp>^6M*ntD4GY`N?33BFeX;0U~4 z6n;og2gf!Q94q{wlE7PAgj-u3V{mMij`<2dC;^!ANZU1oKEn@20LI4b1~-fWzPAD} zSpv-h8;iq_brfLfOB=>NRcjLbQu_(MAVdK4l~);8UNtKdDLvl#FX7Gu@*aLrN#KhY zM(Y6~M522Gs>ap9+CZ=mhx*(Fnf7{aY6Rebp@#t98v$@c-X0Qsxg=0vpF59F*4URz z>c|=Ro&7N22bBYS_JHu&gY)hbi3-)1H<7eSAlu(XtnmF80K46lP4F(@yB7fac?jF@ zA6jM;4(e^;juUXncMO(3hR5)O$^kxnlkwr3?utUU2ZX=fR@Os4xAg%2q$9C-{j{}J z!4CQ#U*LNe0l4AdZNnE60Jk0=1pJ_KfO`V~TgsW}cJ|%EZ{H6vc|U-F*92cd)TB{> zsW8dHjY5F$y#SnkhF%c7FYuiSz;?33mKt(E;AKYv9t;E6V&l-fKIj}k^u{>^?`rs* zG#Yrt9hoj9VTbBS8U@=k@UG!|B>?vLAU;OsW7THla5rB)r3$Hf4YggYb1OT1q;Y5HUOZziD zwag#EzyS*$&jvSS06I(i;dBA{@OF_NdXXB`{Svtdcq|W|0Tk&WbUwT-agW3vpu6&M z|KaMT-}IzDb|l$rh=uwR8}ro3q>p~?fBDJFF9#C=#(BW?Y=2jDWyoZ&G4XaWkFN+n z+uH>f#r2>@0RZs%C%?O+^Za_YzYDIJz(}PDRiIY}&*e7bJV&;-3!M+I-@Wn59Vt%Y z@%f#vUH^ssrkDK&s1Te9; z|MKlM09OI@>?ebkrv_1Lskjf|_T3w={0FVI)>><=wboi|t+gg${|Enw?NeV|CgA`8 N002ovPDHLkV1iDDfs6nE diff --git a/firefox-ios/Client/Assets/TopSites/google-drive.png b/firefox-ios/Client/Assets/TopSites/google-drive.png deleted file mode 100755 index 6f43fc7dc54a02aa6335b83eeb6d04c0b6fd0b0f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5655 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 diff --git a/firefox-ios/Client/Assets/TopSites/google-forms.png b/firefox-ios/Client/Assets/TopSites/google-forms.png deleted file mode 100755 index daf8fe6e5d8483f91601fdc8241308e2e13aaf4a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2743 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 diff --git a/firefox-ios/Client/Assets/TopSites/google-groups.png b/firefox-ios/Client/Assets/TopSites/google-groups.png deleted file mode 100755 index 8691079905a764b29358d44917f34cf24fa8c40d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5025 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 diff --git a/firefox-ios/Client/Assets/TopSites/google-hangouts.png b/firefox-ios/Client/Assets/TopSites/google-hangouts.png deleted file mode 100755 index de2e88bdae10e00b29beecc040a420bfcd1e756f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5445 zcmXw7dpy&P_y6o;!$yeY)?;&*+m>s!Fr{2`R}w~rEzFe6lohvd!*NspR)t}}$( z9#Xy`mmyIjb021Yo%MtGC;M}fk8Yt<|IG{EEtXW4H?rj} z8q-F<^T5x(N*PJ^&$sE;={A)!F(1$|AYT-zTCsc~$f7Bmi%_~yD}i<`m9 z>LL#8J6bfKU@#ddrMS+AB%uJr51EW83u!>xI18GRipm4r7XALjsIA_8b0is$HNlZJ z&FQE@uU)D25OWdH==Gj^L+nkf8(Z7+qTPx(eP{aL51}FUeoV+|zk@FDFZowWs4a)% zB%Mv()$acfAmbl)%WVI_Qd1kXIJt|b_CJ7Z2T)g4gyQiMaAWP-_o+~uZE$4gb8#Gc zjvVGCQ(VJc8>|yIi4ysbqA3_B=U*PQ9{FDw1r=Yb&TM5HUZJBuIFp_OlIjX3$J9)& zm$ndY3x!z3a1yv=ei&wUhx8Ybb()PWkly|Y;(AVYqglMWQjJ| zuVgvR9NyhH3as__%bsy|B6jt#7B&q7WIqcMjaUNC+%##>mEEXt$+1slW=5EU_w&T__c2y~eI>d3DFzvgN3}M?8AfA)V zFwK=oaFB-?mvm3LYS-3~P)ByIcxg1fap#^$7vTh%klOAF?=vREuJWJPVbAA_fq03| znkfGJE+Q&K&8*l*U#S&WY?X_*sB2J{>t|mU%!yJeAWkxSpNRhM;+>Ua9j|jH03_XGUaAQUf|Xp&l5K2#>jkIt#X2PN%M?X zXvHDpmrJ%;ce~@bfyeL0JKX=9v*?OU9PCcRjUMD9wKTEMM176cBS~ma%V2+W&NcO% zxgqJXNTuyqZY&D43WguY{eEeNrGy57fz3t}%X_Q6XmRg_5A%=i*5!(Zf}K#*WXyf!&YqHJa+mV}&BSw7hEa>rz4^qw6;WHjV z1$zmnQ$mV)6cX(vi7&!%C46_a_90>=)wjD6nq7Z z8p1592-$#|Fv**R&UD%MBtoM1r0wlXYv_GR;?kc;W>`i(s5>3=?*mZv-}qW^(eMz6 z6CcrGC^VXoChTC+@=GWaoDL*@(hNcY1#3=#rk+NapK>*8OJN!Nk9DH1U17?XD+UZL z56<^b%8p-AzX)k61(O0rAKX#F89R|o@_|AOQgSVItYfpO#~48h`_c26;t!sw++b1& zInM47p<4z}9Bd>_9?&@Cr5gB@T`dLrze_uP1m^@Pvqx7vQ&F;W;GTleRyM76;4F*= zwrF!~I3>n^qOH=p3Lyf8gkOPpDwRiMmI6*BucuIk8eK#OZVD+o1HtG$iRx%Z25sfE z3@-m=IyDil_riwMRN3k`ds_{Mv?XB#qD|WoC{eoFQO`Cj4KY=d##fWc^~*y~b~Itj zjqJ0(5GYBISR}W2efo|DPzEldNKes#FwHv^u41CqjI7$_1nnT`(XTGO1$70(yre#f zp=Q2WlTO=^FzUD?FjmX~aT2wLF~@$W;o7&`4<^`HGrM*_`SO}LnVVD-d&B%XBt#hG zh^XVB)9t31nJ*r|dvI_SO*ZZ*3K>#Jp;V4Q>+Wm>x_$d&X9|vfO(BV4KytHTFpg2jz889LO z_oF|;_P*gdWKRH>O6%QWF<;arnqO{fN3m()gggbgz;Mm zpm@AZk;p-uM{mJ){CKngQ5C z>FPjR7c`(uaTD-6Y@k4ovjdDc*;2RI&N|j7;cU>!%r#h?^0`7(_|AHiF*Tm0MSdI)ds!;HD#V+DgDaMcA9{jg-eq0iaQohnWB8<$D-+ zxW)sE{Fj&29x}Gbz`t2Gm0Qmf77c$X@7h%V9oZ$rcSr?A)f4-+!t?RCr9Sw8x>=EfOR+c5+*ie2V)-_M zEH||qN%-hgYj-)h4k{ z*!I&vu-XAqRt7wnidKW?3m}_xiRg#6I$h>~7%nn7?sGcb)XeEBghCD!72N$5D>L3) zD8)h;C&WbuX%zwz+->Ds3!!2vDs+AoKp=YD_V+7V5wzSRG>Kp_QJx^XaAU@2RxTuS z*q6K?jf^z?z2nM=Fd_Y|f0{eXEAoE315BJ&fqJ$EO*0%JtXY>FZo*mj>r1;#Pg&1z zb%?L;coVNz|gD4J|*@7b5WyF;yA<2$U-au8s9k%VVkV4eG}Zveft{63bi5@U@XR4RR2tIr*>5#*k_ zoa-!qzGuL^N%Kh<_63icNqb_lQIpq~~Jbemr_`*qL+qrMeu=eG3SbF`t<@eYy1; zlp)t>mv~bhVVC(t-cyqQYaU$WqLRpy@}Y~l7$0o?1ok;9)q`YfyqCmL-9hB-VSfps zY*sTX@)4+b&ox(p83H2x#+%&z0pfIgjn-M(~c07bGzol zMg;(h!TMllUE4Ck(X>5lgVN+37?yCZC0&BC6y0#%t+{(Lxhg^pSlXjGvC`ZmS+&PW z#&cr4O6Cgmg8liHPwsnM)8!AiZR*p8w7FYQH@vzIKTYaHYxt&SOC6w zIZfi61H9Jl4RkgOMlYT^cP`=9G8Ng@jnt_sX~qj0%dm(L* zEb!;ChlMMdVQ~Y`_BKD(l!d%V`P5XyJkv z`+xuM`|E2r?O@j&oN@oKsMjjqJ^1XPb(DeU&Q6&-N=`S5v6vO>?Um28mK_)>t-f&u zDfAreU)V}%pBIts8pMS?w_m=S9K#{j`DP!~Makv6*HInr^;X5n+B-d42l+ad`{pM?8|Tp~pD) z0`7;E05tE;0VwoM2i~^AtdT`T{#lv5Ak3Gqxtq$G|3b&7kOr)joSy%V`AI4rkv1>) z<`HSY&ChEDNu`M^KdkMrIjuse;@BTOqpWtwxWr?iwaZG@hiLt}*#ds>2}74XeXn(* z9FJLX` z7_z>)v~i3O779jp`13Yzy+_kA2s81UKfdxiOQ^WA)5QBShh zXf3Mr2uNpcys{ev7vxz@sRdxPoB;btw^Lu8#V|dFQaX~u6Hjh{N9Vrqei!4L=v}N+ z@8>wk^qwBrCeY=AB#}=EuQK#F=fl{UmJ53*(x?;SkRtzx?^rOOR+u<5ODGI}UvoQ1 zo*lHxI>mAp_{E5DoVF^uHg-|1z2C&~xSmVY`F8?;Nkjhh{1%$57FAu?C}l;SWv|_0 zpv~#{KEbJ^E?Qgvhl|A{II^TA#b`l;(rb}&hgxuPih1Woc=H(|-iD>F>}oL=xW;u5 zr@I;aoalsS{h=$pzg8^T_o<92{+uJ7cltH$YAaSip2D#m7T|B;;L2iR!xb#xtWSw{YIX!wk&K5rT z_0&I6)Do6NC8_1P6!(3pzUrQ)$rqbjn~5c#jed^SY6KtQZD1SG(nEMdgqmr}?$iv3 z?bO#Sh!J0YOmgv5EbGHX?7JAK&!^hpm(7^Lj%h232~~oQ?*X~mVhum1;KjyIp(nzF zYI)16Ky)gp?ZuVJV&+CAD`;_p$QGZyOZcC$=h&}9iitBu&0pV*W}lOo>iRH)cA*-e zcSTvD{X6p|xKI!P*-;)~t@^eBr4kQdd*X z2NR&GG*{Z3LH3)Kdy?&Zm(+VUBL#PhIsi8!&9|4#8fk5x?SK0E{#}%bNWfsqTV6}j zJTyOAOv0RUsk?-gp-sof6zGjTE{<*~9hY%DG=3sHX4Rqb=ir>ywIb0U-Tj_Ycuk`O!C#?vT7!e`>{;Pw-Zc9hHXvyw<6mZ{+KxaCrgiG{;ToV z)wATq@W}Jo9=6j|#p&hjdorw`!>y;sYoE?9-h1&ZO|Rx3sU`@B!A zztADYo8&TAv$4#r(P`6*>MRhxN@|fm)Ux;@LhXrXyr=WXD{V%jzi)GDC{rz7i@4oj&%`vv8EmEwg1`Hg5eb5Tb_G!~N5` zTz;pQ1C@-?PcbDCyM3GfUkT|}c0dP1?&taN7sAtgNtf&5pr4?I>TE)=Rh?A9Z#^lh z|08}1FJbbAugGn=^Zwil5PxU_G!3ZRpRO%P0hzJOZrOdn`$FA6=rqFKl=#12hXBA2z@7 z&Gj8^QIh|h_AdLx^?1AusG*WSIidgWLPi=eesZAiPi*Hu4i}!n0+QC|#zwsJdI?JZ jFFXFHKwi>c+J{7L{Ip9UR9!fbM*)lTHm2{-dXoPSWgtYS diff --git a/firefox-ios/Client/Assets/TopSites/google-photos.png b/firefox-ios/Client/Assets/TopSites/google-photos.png deleted file mode 100755 index 367751a8d29889b8f360f8afa161d91c9910b9ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7428 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

  • >eXi!aob9zjS%M#>O+o6Z*;6AiyD5LK=(CeRMC4egd z&5XzSS509@R7=us)aCo2;3^U&hHbGj+itr%igHgHPbc|lR!nstJxUy@&PrOxi()qL z4>a`kq+UM3q2r0|TrF1S@yl^<(LNqZxn1gFrYkC!E9bmyct>h|I)y9RFEM=GkS2c~ zsT+IsxP8#l}-}a!J{Iv^=c=Js&)qudT7%f*4Pa zfbcecICAR0zrueS&r!CUrDF9q%AQN57tFqONF*zAWi92XqhwZP1dFLaG;sKqNYMms zY${I?JG$=7B%&B^c7ual*=1HB0Re#!Lz%FU*K9YIM?d=9?~f9kX0z{3C#r0>q>{6u z(IU)q3=JZ|f>09xis*w#d8w})TP?Hb9^3wXJlkx6bQR?3<@HM2HW9SLRM^o76H)}Sy|D&FYY;|= zxunm?(;$rgwuab8m~wj%1-pF<6AXQzt&*$~$?O@|7SmldvyyP38!k82h(a z9#Bg2t0D=5rVYFWOZxdC>}?UYZMLz~9IvoY+TZs&WeFEV@Wu*~2PZA-dk&F6=l&l2 zmNH4FP{sq3T9b>%LMrIO3{aPm~ZkMEuyz?FO&t+jPhpZ9Kh2TU1DAN&4r zMw|3fjXF3u=t?Z2(2%i^Ep|fTVVXVrJtd%#*?+J;UQD=x@Np1mX=-Vi_&MILzn0L& z9xSj~+kB_tG_JzWC}UuX1ph>puK-hMUSFx139lQmC1e!qx3U-Jj_{F7&Xd|7%*@P; zicqdCM=0gM3+CugqCU17p?R|&j)4;n7PR6i&-#s}_ovbiayuw)BhNXj&x;BRPybIG zpJHUm7Y3O7YrPXoUX~~Utc{1ZT*cl<#b0)o|A#jg914jZUuk`6JnXj$17|JHn^)s~ GlK%rX9c>5z diff --git a/firefox-ios/Client/Assets/TopSites/google-slides.png b/firefox-ios/Client/Assets/TopSites/google-slides.png deleted file mode 100755 index 508375aa4f7e3bc5be216cc7b706431ca5a02b6b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2471 zcmV;Y30U@tP)n&N}O?v!yffb)o)W-ns|iF2Jpc2aq*dcd*~->W zA9n<(2mBiV?z4Egh5R#s$Dln1>~RAC>wr4t*c$DUMDI)AMRx0ZF93NnB@!5A@ZUz+ ze`F8;zQvEaS&L;YeVVy#F4DPq*~Ir+)^FzjhKLfldS{`*)c?Z?53m_I%C~ktJ9jMNa}1 z0Cj#W3T>zc#zza4z7?I#t z+g$`u6?E)KkPZQ;9H!})Sm&~XI7nd90H1+Hf_O+^+5w&(JleCcjFbdM7vxEQz7#r@ zNt^}=Oi*_-6MW49Bqg#$Kmrpt_?qG0)pM0WX9p$-;1>ozlBf`HifFU&H(5>>n2Y zMR|CjuL({`@QdvwBY-1K;BZbs#_mfDFnsz!!_mumg`qzZm@q)68YKV?0hA}W)hB@w6~2C1;fI#9R2fg&7#!?DWWn70v3TaUJaUI z`BVoGB0z7281DZG&v)O$@rwiZ!jOJRkcADri(H?Ly?=C+2w;TBRs==)5uQE%8?3#B zmCc*THm+6E9{>ZPTugO#*C#1Pql|gR0L26S7fW?k}>E;B%o9zpaARF3G+XLVsH{J zra?Wm;+Rv$AWn!NNksq+;O7CqS*kb!fgHV~S^X!K=dWM0I5vV}DAVto_4hXtKy6o? zY&n2;JB}c7ws*iO5l&taYp)TzE&&1Pa%RsJ_?$ulo{Q+?Ub^}P zi(D!aoIk1N_I4ij!phu0xMT50MAGeW>s?*9bf5~S79`+1S1Aq3=?#O!U)c}IcF?~8&l8*rN-!1^Xjw6Ya z>SO&(!K_x1z!vRQDP_rk?iKt+z5i7+s}>Lei#FhIod7NuQMwu-)B=C{Z{`YNA?G$% zr>8N32t}Y4@NIz4^CZZ{`{xxR5`kmgcH{fN#vRXujK7>+J+210ATeiu-~}f zIJY+$VR|@S3piSIvK$1MvbPX#ycIV1VA1ns`*z-z{kltu$SZ|2f1O@giA+>o2 z(b&~Hjle%8fdRy@T1g}^O$IUY4?wix2vbZ(1tCgZnsvP&@|XutBY_qHOxhh7!M)EL zEtj({fN6U^+4{3*9oWkYz9IoS5f}sbk!gT5RK3bhCd-@!$jc8~O<#HK+ZUQ(1HI-y zaz;Xc8B?jdKXTToTwpB$zw__;&!?YthY1kC?-xJlU=c}-;I~Ww2GQ;^gP%|quz117 zGJ~Il2-NZTdD_*lJnjhKu*2wkr;$eBvm=13j-ch|!CqeKN5rK&Sf9bWBenANRw-JojFYP!0+iAmR$vN8< zi&^YI^Y!0PX^HLdEh6w03E)r2jIYUKP$g;MgP(*5WQ=u)?52Ykb|}VPc*<@%c)>8r zxWT8dS;wddup|{k!R}kwm4+=f_(_PsU_o~l^1Jl_sj?)9C>l?3=;1EXxz}(qfv^ZL zY162aKiPi>44;G#{_qK8{|_^O4J!>azJZ+iciGK;@^;uH7(Rjd_{YJ%@1xfMa=44$ zU%v(3_#trh^>#b&B4H1AFY)}PN&}UNaPSZ~c<8WWw5Ex}&jcbQ0NZP)l`5m9P6HW6 zn^ag>8i*#y(g9ZCdem548kQJLcqq8RJy2;?ae$dXLL-3=I<8gVyEL$!C`08{#a=#h zpF9B+9zF=*+XX)`0(c02-Zp8B1N_8ApoL?3_hJX<#wH-pXcZ3qu1G zgEeLqi-FnG5Z5ZN0Gs1M(U(9#XG4#t&hc|E8YPOpz~*?M(L-t|J^S72r)xLumPjmK z?kNkXxt4$y80?$9TRZlv(TG3*uqAc|2S!=c(t(#Zi5Aoc|G>Z&*oi6&0D#*+8NP4x ziUhWB4K(3yC6I?KpjMp#N3YQe{2V*C-?8s&;iMj*|MT0`Hvru4t#K<`t-gtCdVus? zhwT8xV2$v{lCY(KB~T22av*zvF8E#ua7KhH_W;}lu;pJ1(m!byUpKf1;KA*8?7Qf! lv(7r}th3HK>#Q>k`#)qdymQ=t5Rd=>002ovPDHLkV1hEFje`IH diff --git a/firefox-ios/Client/Assets/TopSites/groupon-com.png b/firefox-ios/Client/Assets/TopSites/groupon-com.png deleted file mode 100755 index 10e04e5d81b0e7bab3ec541ce8ca62fca0f669ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2556 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 diff --git a/firefox-ios/Client/Assets/TopSites/huffingtonpost-com.png b/firefox-ios/Client/Assets/TopSites/huffingtonpost-com.png deleted file mode 100755 index 38a215382661bb1b3550b455d80da650d03be448..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11004 zcmV3R%ocqwddLkqt#7kfT#x)9H3>cf2WrHCNu^ljB?0Q0o9k*#_I+R zz1H6QTIsf?|`?2Ts?$W{Y&HD~6q`}XKVVjyhHT_|~)%^SN>$FBeG&KE9* z4rVqML$c1A1jrz)VSlrp5hE(hB*Yvd&Lt3x5So6Eko$$_x7?)veYDesiCzybJ^rMJ z%GG{X$pLOJIY6NiK<5u1_|`4AJ^sT_V7HqwXppf&awY`~f@#kQS#K_<$mI(DIW60U z1#lLKa2HAt8zcye63+#5?7JlwU%O}mer>}!x83-T3qDnI1AOqA|685#;P!v~iL z`&*%!d^D&!=au3DaTXR|%{1i7h72|z8{8iU*GTod)jNhK)>L2p-#X<(PMBB>H*7fP zH_lmm+?T3j7p{K`l<&^7ukZVn{>rZ}l#M0jH#v}G5CTM4oHaox-ZUhU@O$uf=jbx1 zv^Ax7;E?)F+qRb5P(pLIRzDi;^N$xLq3xKSf@k)<`YUIyUDqk!(3w7R7{2}Vlh^(A z&gU4ZeaZ#R@UPB$Hyk~=7=HHp>3O{}bqGGU`S0M?$9_-}L0lxe zqx%jYhR1ikba{8h`!D_U?jwg++48IZ8XFmbd;aM)aKqW}go)A7pN;rW*~`tzdrO7> zJ?oB#uRXi9LUnE3s?SkQT)c!jFC99tE@jKlmG8UD$-lUKz|USk-LH3@upaLI#cRqr zBh?b9=XI{+=6j|Ot?Nw9&W#u3Oa%8vXg^c+{Yd%wlV`r8y7A9m|NjudC(k?=4i_|- zM?R)Kc;(9#7^Na zH)kux#uQ7c^*}iQs)LBeN&VZNf9!FU!sqGgL|ImTg>a=hE(kCObHpK$hQKzdpGj#F z;O(nFW8@snY_sy9to~xc2(Djl&dy(VLKK^EPwbFt)3*xY+9gZF%MpiPHAV;Jz1(?3 zw4i(ET-%3T(R+668s0vu-wPR!pVW)@Wo>Du+u$8lQ`|wKC^P9~4APq!Jnb5OuC@Z@ zr1J@N@7xKM*XOMMVTgMut}-MMS#9I@=^#ddFBeMC=>ySexG|@Jd{P$L0lAVjB9fD4 zJujynv3^+u%-g3CkQ|3V%th||<7l_9FJKg&>N#wSsv+RkC=1xUUaYaZJJWJd`Nt2RjaRpT%EI?t2qipJ%k&iZ1ZR zm@ORlsc2$ALcG$=Z7-=ZdHPb_*}()g(N^S78gaN3yhtx%Jqadda4)Q5v6S8y&=M6N z4Ps7w;`agnd3+(%=W!BfpO1RGnn6bI+?ooB-M^sz@7_4oSRAqmSA1K9wG!R7gU}~Z zs$1{%TM}H{2h+24PVTRkK%zLs3w0y?9OZmu1Qy(%+5t#i)7NLvb_^=#*W3xg=T`E0 zTEDSDXh3oTRE{&{ul|iZkEL>deh=&U)^CyfQR=*=<6IvwW6IO*)09n&{D^3O zj~w?6do)$v3JI(fhw6=u645tvu>X#sR-STzI+qZWFNrBbZg`Uq!{QMOME%-{mL_!O z1gD;dEa^ZyS59_>;H>XdD~8^i2Jb)#q)^q=bOAmgl6>oA3PkX-D}b#UO(FG^8LrJ! ztK7AAm!h1pRlvDR)g4p^29@*tMKC@-ULJSvu|XgE1Aqv=Sx0?_cI3z`yz#~~96Wdkrl+UM&u_rg)HEDA zbO;U{H~?*EH^Ip#pA6@mbB;kY5RYIJR)`~xXPzohh0%5R-h1zb2OoUUgJoORLr@e&H9);y54zoM^&TA^t%$&V z9&5Z<{nyOQOm&SLh`G7B>ODIZjRzKvfLUcX#BMn*=Oez`u3jP%MjOsb;B^`-thH#cA2zuzbKoVp+G-6tep zZo4u1;Dw*BF2u@t7h%mwQ%gQ$HJ;rt6;2T#Ye4J0e-v#W!muJHIB7kfBp5PczX>FmZE0I zjvesQOD|Po#}Pwn;&MHd{Fvi#PQL}=z&+3acN-EGbQrLoX#K5{*2cU4` z+Y1)v_I>MH-wJO#nd^3YQPH!`7lf~cdyH@xMF}7wj5^X&YiGj%a%&#*|TSNMF=quW6A2&bO`U99mFKa_RC}LeZmPR!skE#1$h7EmzN6hST#=h91Ih1wh>e0 zluY*ww_2TBxN;3wpX={NBQn{WsVWYDh>v{aBNa!GM4$~&{dO$!?6c1;UFI zih?&P$6{|1-{*^Y_{g=_!pfB^RRYl1f3GyP&cEP-=yOng9t_pig}#e&P~ThH>7%0~ z(N)i1PHBD5MHe+#hc#~L@do8{T*vK%Fcu2fmIj~*Q$lLrw=%9I{>H}MoijO5c;xD+ zZS8uc)PGm6IvSQOTONI06N3%+Emy9(kxN>1A&~I>gLW%JR#x>(*6lkgt5cQtH8T zFDD-{VvLgKf9KIk?O#$D9vO&qeLQfzqmt^$5ZuuLm=&{PYWD9;JTDCu87Ld`i-|eW zv&T77NP$k!>xT_NYYcc8HK`%b1U4i|t@ylP@ez3D zZ8V~|BmigUlVxb3Ey_I~8|jK{LBhww*c-Jt0AKl>2sqYEAxkF%KxR%9*{*^Oa(zOt z*Y((Z3I|w7wh?+jO6axLCRK~qE5I(5;W1i80o1^uCUBM~(FkN-K2rkOL^{AtHH#yK zR}RAHdPLN&bg~3|sz?KKuYzCm4x3R%FFZlUx22Lg{DC4id%VVuE*ntHF#53`kx*g5 zA_$b{@P1(nq$&N;`d4r{V}wT_aUDaiH;7!m@gK;9HL8QXW^|g!)^MVUG$tz=B7M`| z-+nJV*(Ru7TQS@L5)7tv;gA)kfIjhHOE5@c06_{-@*|G}zZ->vP7pxRR=i?s-6+tC zsO!+Qj}#5J4sbwgzN8#!waAJC%ri@&u{lL>1QnnJDF{b5YViY1NXbA|1QCT4_YX9j zqL~o3q$!k}{Z&&xmrX`}EmCMYaP5j%+xdd3`!1CTY};k^hm2%gV%&r@PE#*Z9?61& zr3IG^P*T)H4OMg63*tdYM&poT>q&|dY)lcPBxS$Q9&>X7J*kAGWJm^ln zjQh?>FOwwgO|N}%9UuUQ#G}!)t9`B3FO#E)hT5k?A`_{xZ3hHU%Pf?}CnjbgFA`e6 zm9I56>@cP%^*19SXuDmWB5& z6PTAkmegf5kSl1DkOdUPWce9cs4Y~kn0q)+|8LJVZ5|{mEdtw)P0^6OfE5P#Eu}aYnxZGngd#IKiVW|j?04WX^x`m3K+=X* zj7r{L12qfu5&Vp+UJ85XIC#1Qv|rF5aG`=-E_oQ4DIwR^gI7Nv{W`(qx6juJQLS5? z!-Q*bDQhCoKuO8$K==%f4<-+fhK#mJsVdx9o;@xZb-iGVVXOdlM@ncMb&sT)z%Z^MXcteUt#U;4sX@u(1) zZRKR4n7ggbT;wN(Ab)l!;)6kk_#PhiHcjD)+&U{1kw?t($d7Lb>o63M4$*~#I@rVm zXy)udy!TWkMzc7`UNLIj9_2TV%b>s>9Jk>bvsdkke9@%h5-9W`1f@P_OgHk3ANYOS4>^$?t_IO^EuZUY(#@=x=Fy;z2*=i!~ zPqs_SMHNzzx&zw85=QA1W=x>WIt~I_6ru`H^xT?vtzD{uTRq|@AV$$QQ#g85gI?}? zP&q`PZZ!jx>DGvtPy$JlzCgn``6xuI)nGhXXO2+cGKh7pV8kl1jj)iUQDj0LW{Col zD8|7>m0mOhSR822%<@s~0$ieG&ybBr0l(01)L{e2T&7lJY4ZA;Ff6s~5X=-{C&9AJLF2+Axa0fCfD0)@EIB8{NGdq__o2@HMWL6HC>V}T+( z%k*jFyMtXRnIlK`sTy^z-{B`&-#>N#unJ1SY+GeaNty&&gs)UqW99VxteBoEbWpK( zIgAt3S<~cuf^RXSoCI>Fm4%Oa2<2xDLDb^%0#cQ=d!rK<^H`GF4|TtTLIIOy2{^7T z2MG?A-P1929IZ?o&y_-9^RlYc@yJfYYOnxdajq2-CMU|(7;+_4KuBV_+2XLih~{20 zOGohe`nOcvtSk98J3E&o)?xr{6JJy@%N@7}otfGNs^yxqz3 zx4kc_L>gbI)kG4{4D#UGplZ0(qsVYlP=gCl7et{12sGHr48+(HK^-0DmGnX;&&;Fd z+Cm+Cj-6{(fTjaf1LiTfu&9;q*Dt&RNuYQMYayrIr~T{S$J#xmzFR>H?N0&R)f|d9 zt*RR|<-D2=DjMTmLoHi#rsqYT5Jga(wxA?>j>t9=KxWAL0|;KmunZ*0O{F5GT)iYK zKR5z~`xb-t^8v*mss`D8#f~3=o#XE+VuyhXLhv%nxMSESM8ALb0%&Eo6dz&H?OvEs zs4IaO1S^L4JhDcI18eyx!lF=Cu}Du*WI-t86+lEUXaW^AP!6UR)#Tq7nqwjVVq;LP zrM5pj#xdp((04))K`f0kp&-zJxGnS23kg#Z4s61zq1sZmWr2maZMul>j|5{%F3@yV zh=5pJK+(8^F<7PYNhC~AzW^rR5X--pyobA{Fc3w4&pHo}yMt4fO|1hEr37u;AFZ8o z4m#8s#C#YL!F6sR#q31n#RXd-fB`ciZ+TqR_HVI)x_!d_v7Z9cwFq5`e|9n^F_^RfFXXB<2ec+M!zCPwq^S zbp46rykuDe2=-+r#{r_i31^w41VdPEQ_J*^?aBx|pB~iwz;JuEesktCoLhZo(0mXJ zfqrR_T=+q!091lU7gLki5kiKI5z86}h{q|I zbq6pDTjslsr5s0f4uNM{66l$3a(_m|$o8tX?e95*!uY)~a@3bw7#cz3|BeQTCQI6I zjKE@-`XGiA(L7s=^W%_tObtMx*$X9#XVk>J;9fbJ4DTV2oNALpGkCqI=+|rnPNFI% z+5^y|m^+u+P@_glp(q_2$Vdv6+F0R>!TA-un-N6WPY)MTlNI?RG6=`oJPdWNK!N+3 z0`MqE4(4dAFl)miRhAAwLvVS2(<&0kW;;>-hEsgIzA!I9vI!dK5e8(AfNAFtB-rji zxwB+u?l$h>F4BfWGDmjC>H+Zk@&JB@c*_W8Ye#W2#4Y7+R2_XvnV+b6UvmI&!nLv_ zkdD90^|@-I!H5UYH~~>&qEY3^c?u#K*QeyZw!0pIy2ZTY0u7PGCg1YHDwc%|D@c|0 z?}ddDbn}UF+`f=O#X)BV#ukeRie=N*@pA;3D`DrHc+sDjpHyE6C&;!Rn*<%EDF;&}2X7 z1eFe;PPk!pSP3lZZ?eRn*i^G1;STmHe4>x+$-qJzh=XKkj^Z884GRx9E67;!5iNQ+ zT}1#Y=KZLFw_~Ab+zf0sHzY;P*MZ9zsF}GPZLI^y?Nu=Yg<41sxN%N0?JIMRv$23o z-NfW-8KNV%<^d7KMa)7tqLuBWY@^%Doh8c9tt?Ijkd7Xg6+$ef2}HIs#5f`9k!iAI zj@m}KeXoQ|EF6q2TCF^c{7y=LWZRQc7JakSif6Q)K@vLD%D{qBd7M=LLI7l8LN(z2 zfRxf?b})lW#sDEphtfoGRNq3sPbpwao}&>nk-qOXSqoFOj5OU&?jDXh4yvUC)LRP# zg|ab$NNSCw3>)7UudTtO|cyq$1cyS{%1_G3Q!pXFRg3wfT57mB- zU<^%S;xYrmmU7?iOb$vUV_P_a0>b7`L@nGM|JNy$F+l}?IcMJRSGsTar0%#7I|i3Gac$lK)7cEMTI zdnDn@(6vAoHxn+Drn*pMh&b^<-~zxhJ5fZfX`x{n+d^=geZT(t>n08$2XK07x-p$l ztO8kT#ph2XcJ|T=@rY`NBJMw|NQR!TgxE$~hY!zW^~ZgG{k7KzVR=PFw1&~WTK!9s zl`%lk?*be^RRS4gNNwf`sR|HfVFX%du+xJ_9^RatvAbu_9+;b(_jWe-CWm~@g}aU^ ziYlSkJIig&&o4B&TxB^GuzUCJJPV-g_oF{}wAv0&rn`~%90YA|U@IrG4Ku_Dd`*KC zQUujTR5q?L%@~YIe;ZnQ_0?D5f$wYzog>Ch;@h`xgXeyo+4iMWeULJd3)26{g3bP#;+e}#vc;v?m2#aHqs`bnJx$NaXz3ofEgj)pe z-cwUk@E8B{UZt#kY^;+8raq_416wp4z=91?Ge6KM)2=mCM$Xr_?Npt;>EHi5xV;># zVPALObtg9-mlyZx8Cx_q5E{ppL`LXefF7Z zQP^%*FbG(h$r(-=8t7nZ6=?D`Y955eQ2}DclfQX81{*~- z|NKXvjjjx91wHoIKft>$I1j$|wXeeL++20f8np7;#oLC7jqgRMde9eAuXoSw_C{dO z-aYUyfAe3!uiyA9=B^SLL{_P+90lfIqi)EiipwsOrec^v0XdeXM z4R7k8Bz>>787cG@k(57qD7>5KS6x$G1FIb;u3M{!-ijhadhBHvgaR4~6<^ z+Or$58$SLqShMCBxNPG_IR5w(U~GI0PCD@utT|?FRj?^7F)0I(?fdR` z?Rpt@mNNdyCmt`Ym;I$eI$O#7@04ga2Nwp%ItaE1Gcmuxh`9Fr6Z~g+DcmDZs z)>&u6iWMthVsa8rdCObixOKeZ`Z<;sci;Kv0g*VZ`U6*91%LMEcd`6P zxjzt@3acMO57lb?)qnO;_^WSx-81j35;j%<2tQ`^)73us{`bCDy(QthZRv0Q((Ukz zS6}TrGQ+cp8*2}DwsoioJ1ASxIm z{!)U_`WIzWc_~ilSH^JcIQ1GIAFtTk(xuB_a`7ZATeiH~Mt*$JA{Z^@A8*eaGt)3P zJ6CDT)8+fXfdkdb-@ku<^cjv_5{U{Kq^xqXh@kbPxh>vTuU-Q$yzspFywTB7IO?dC zuzdOQs*aIk-4hcNuw=;+vDy(19z4)T0ZYPi3hh*B2{}Dt{{R$=y~fJtn7;Ygo(+n5 z--}uS%moyrgvm6r!FLDJ{Lb(G9$a+EB~3GWrII#T4#xP{csVE&uzcBya-zp8t=Vym zZr8m#UVsEj4!Qn*{ zi{R4B-Wv|K*e|%wwsDHo+J?5D~5@UD2W1`-*B3WL+B5dfY#QZd~)@U zf=GkVbvKcwgU!pnYE$zZ@wm6+8cvB-Lqt40$0*_%?DQt)Y;X?RF@e6vnQV_f*eN$T zK>`VfyH?^`y%*{COveY=zf&v(Bocp3ksL07uv!|aAsr@omW&^d)%4}@V*^6%P_*HK zm7royA!K?0jB^ko1rI@Wxej4G4sl&7@iUb%GQ_%4xI&vOy3y#iJ{wCt}HSpO+|*iG#>xH1uX0(>+|w5u#=2qvDA& z2rMY9Wat&z&b2%$M=RAvF-IioI+DgINfW7<-q@oh0MPx#tZogWd@$MUR1S>C2^3VB z)vXOm)y5{qivC3FuaRaYSFg!nlx52~hxdH8xh3Y@JE1~xB16d)!fbA9lTU4)d;N0d z9Wy*O$Xt;Vt%aq;Vwp5u2BoZ)Tc^u1_Hy9(mgVh?;#?wGI?jE-@jO5p~(BDTp$e zK!SiI2vgM|Wc3g*3VI8yUaR*XkG0F^8k8a86pHDnF=O1~C#B=oWRtcs6$L4Wg_D>t zt7B-KCkcd4n#}J*ftJb1H8uT+Gf~^`%`3~VaVW!jjX?ycjP2lfL1|N_lTyR?96Av9 z;-R8pQ$)B)>w!qub}^zA=YWN3dmzq%0(owLE8Z4i7`Hfr`&k-3+RANCYzz4W?BMS` zQwNjKLPu|Tdu;Q|J7Di1Y+KbhH4`Z)!G^lBMN$a_qdq|bq)C~TsMyTf{tE&s^~D?%{`^=Y?NIWS6iY zbmdR663|c}5uDnp1Y#v>tQE_ZQB3Jdl$UPJUGmt0&u#v0 zHFtUmy+O=?i_%)!9hr%4T33GllP!7;`tK>>h>3XKMUq=8LfnVOmY2MOe;+yE0k z2Z>f{V3;50;O6Fk?|cqE{*A9BbS113QI4Hl`eN_2RjarD;I&uIFrnPR-`D2n;FtgM zF8I`$=fZEl^CCEUax&a?m4_E{sEJtmq6o@qa&ZifK@GHtdKt8ivWZy?Sn1euwQfiC zx6|>r;pr&JrKCtr@>L(+SK!%3NI_LES+rFe4jw+^F;s-TQ-|P>H$McoJpO2#1{QFQ z_Si(P3+q=LwY7KY`cv<}YwHsqf^IkARqGG@En6Oe`?hX@^Nu|pR!=U0k#5gpTe9T3 z&rpaZl=@B$!Z6b{l>sc5cDR25#o}Wi%n2MEBUzzDlLOk`xs=#DmlX9uuL2l8}1Wu~Z*sR@2>GsfKhD(n|><#^_OhuPSY_mA@0Q5q z;C$?@=ZfR2$Hw7f8{To#d_i-aiP2H`;M>l;=Y1!h@{k`SnOeby*Ge5c34j>aEo{W> z@7mtE2(~W+z~3_=)_3#1DcCZJ*XA#z4CP&$v&+_>`p~;iJo%nQE`IT^|MBSx@jc_H zqwn7I{I-iLT|lz)fc0XO!gNuBNy=1Nmbv$P3OEPdoQtMgp|M-1QQu63j4?6cNxyXh z(SkG}f%dg)7B7agj$VEDqdQ;d?O0svU-{6pAnW^J=I!K0YQJ%MaViJD$+;`pf+wZ#MQ!t2m;soHz zwRSe%e)Els#ur^*af41LoCE@6MP|yZSdG_MXK`3X?M>_t8`Mb3m~?^&_ZU{;vlP0B zSI9cQ(}l58>AQ0M&wY0c@Xr77;p=Yi02b0JZfKx<-*(5<*IxEtHeU77vsbQuGLX{? zo_tL|K#10rQ$+=3J{L1(qlGq-?kBLGg_!0%rn0EWc8sz5)bj`T?vB9u>rQy`mW{vg z(Jy}B>Py|+f{1psDuov3tUd0|cOG}bSH8aWsbBrkf!D6s`pTZucOE))%$_5MC+)FE z+l2~x^)cJ?VMzf@tkz+e5yp2*GoNRPU_k_`7y#uQ)Z+!x9-!cy)uZE6$1Pd9>$Ia+ qZ#`|r%5PtF>goTjJUnMz`TqczdDT(a>2aa}0000#miT(-+lb_?Z?kwzyJLG zSKg4j1sEM+o-U3d6}R5rxE{phDA4*a)FAy#;n6h;Gd3$Qr4@z>xSs#LzwP@9;|PP& zEwBE3xBYy#tU4~#H96Y%>$96p8<`nd1RNMJi3j`)hyE)6`{edZ>Bq9;%O6 zInljg^Uf>WSu3YR%I1|Z{0RO2QBjY#Y zl6{SN*(r)7OZ@!)xcB~j&pn^dIp-!h*x@*ji5>$0a9UZKIUP;%{|m`>)H|?$_X5CE zX=Qd6A2IPQCo;{0AkaB^P65qlLPo+(?wcZ{D5u!aM3a0r^xsMDRaV9v5FPm08XC>} zv7Cvw5RVr`NrPr4X*T|X7OeCZfzC=67DOdc349HU`gw6JYs<@PdrdQ>nSq|YSr<)1 z!_VtEd(q*#z2P>pHc8rqigC~F=!$RQ`E7jFzRW1m>imtst-}*B2Q$B?w>abKbEVbO zza9&nu{FBas>5FAJ7_HqF~-RFouyz!O&4vqXi#z)Kwd`<+sh5?bfz)3DC>=Y0Rd-I zq)7Icf$*j%p?S5un4khI#mNDp)$(V7j888~LqgC7loFHg`(XtrN_#+e2-u>F14Jiq0 z)8RC541ZmFLpP_h#fHU|-Yf*n*olgSz8BrAu-qm$TecTZkTFIu;Nn<2bu+G%kG-Xj zClg2NgOW7>=o$@;@!t#0-YVg9OV5*(4=PyJU1Y$SSeE`&d(jt?P%QtX$RZ(d(3)nA2#yo6Lh^H(#83- zU{wCfOWEENMxa#TQ)Vdd!enr$jPWVR+&mg0N!YG2QQPoHjP|f3tv(bWpT)Okc1qsP z=OpOV3r8Uz?gSPApzu58+@_43N?*EIZ6(A(J}Bg8<4DVd#=7g|*g5?f7>l%8o8-Ye z8*)iDbgC1|;DK)DG+taSrizTiB)Q#loEcBQe6C(DSedh9CnDq7#SDDHM;|KI^0Jsr z2v6i&1%ud(guY9r!#z32jxKD^CvxS6MVnMKU`C~9xqT6d*4<4VmhB1`Jp$Zg{nO&D zrcgLfq(%s6SzQ(9;Vi4$w($5qG0`jAb(0H}F6w&viZ53W99+c$VOF;z8eY>^GMFSr zi32U~#b(DC)EEo0RwDqI5A2_e^bc|so;&rE*ccJXZp+_`T%ERL(-TxfzJ|qr?(TsF z)jm=QN5^-G#f^q<9%CSrTjqkIwH^)i+hXrba1ou<^kz=v3Qbf$t1%lcw`RN_zDdIy z>cs(IbQ3d|7kKJj`H9PCEMc4MtjK5+-<&ui)coMv(%!VZuBJUW7o3rygg0ys=&m>V zBL^*BK$2ZoNdmi@0?!R1y_7au3QAaQ4p9gc^o^mpXK;{nue+e9wtAHX&u=R(a9&U| zyP4qENB57;<~>4YYL)S9BkaP}dxq<64;cO;*qw^Bm`jO?sZ}z_16-Ak4d4n2;`{!( zmcu2&Q9dY|E$5J}r1_oYvZ#cT_mqLaRE9WU{NWOeS-f*hW%34l6FutM^+^-TqSe}h zWN~1M)}F4%1sv(-?h(~eTff8F{4ajL!%o}HEx4AwE9EyD!(DPgw|9jgZtvytZ%a`g zyskh7yiYXX+f<6e)U3GhUel7ui%zj_BYBO@W z;;8X54W_j5WR~3bu(p_a8cbi_jn53i3iwK=>1L;^hbjn#Ic$W-Y~B@$TE*|?k6Om8|B&&`8LVO)c^nNyk-H~1gAO=y0S--saU=2*YJoDq9S4ZR>m z*+Y4pd&i6aTuI`4S!AGVbScv7NuV(Dwn&6x{2gAHBl{SH;JUWi$*s6YN0xx+*=D8XGPXsdUlQ_R%-W18~XcJ@B1rK=H-HJEVu6z#PTgCNf);?Kse^i@5g%J78*W@*xG6?W1PFr61 z&o4Fm*x@wuuKE+t_@KlG@0EX!cF#11Uk4HGS!NWU$A$;Cg->Gj z#|(i_vZ|k3h~h?g@_shMAKqs64p*Y5XAjVFLBQNDzdKxU<4kgkh1Yaa!+g}MxZxZ& z;JGRnRJF+Jcd`aI`7%$8EBx2k6lY4&<=1_hCWA~VTA>v}gzbjyc^Vpzze|VTR#jPb zndyN!B zHTCj^$u_m?RS9Rni+WU&IB~w{b&nB{fGfx;6Dep=pgj4-U^2}ADj+i5OYK%A!Cgo1 zVD_<4+hV}-;VqGvfE*$AhHmQDR7VBhy`8&bNoZqIYVKvYCBt!!!`K_w_cgW3r|Tim zLJCr+G+hChS;FXt%^@8&c@5k+X5_!BUOyD+@+mss)&pgo{a((Y2#(erKaqsoFpGvH{F=yj_ZAxdEng#i% z{^3~#DK8!Uq>jtpCIY~0j16l?@>SDoFXE1H55V_olW?DmECZ;oK2|)03kd+($(_Jq z@y^Wl5%Y&q4=$-fC(YnJf1D=QZbBkmQ4784Coq)a{SEbGaSy~D^E z)>z^xwJYe(NqXgn2>&_tWvHJj4&+KD<{VV@Jc}Qw$_MF{cqt!0Js~_QVL}u&58%96 zctbNMF0Wd_h#N%YZ6~FOnXfy|SwXMz3V&Ag@PQGDwSnA(V!nn{Y4t)9EO&oJyJ!Bu z2TtC8CR8-1zFg1^g%&%9F5ZINpz#ZmJGGxMgpgC_ly+VAe?oqy*br1CZ9zJTKdG#! zTV192nSF`AcL+<@f(!Wi$)LncSSjx_e%K^Op1B;xY^UpCcc5uaqn*6Ji`K{CJ;qM* zLC%HW-qdHtJdxh!ZMe?}#*5nzlcFP^d4o4L8K47sPC7{0yu7fxmEUdPOG@5+rALdS zUhk{X3k0{2DRYvgHNe*jF7B)-Cb!s8a44qKcP;2W=h}KZerf!dWEFy-rGnHs5L-a{&z>dIPuiUa!pg zcZhWjlneF?0PSTDeP9UhbPhfqe?w^lW9~Bijh~)h*Z-gT^x$k@{o#5+_en*~N7B{E zY+IHkl&?fj(_DS#qrfl~QyiYRlohd3URJiN+ks4Z?f2Tqo&|;0JI|dK-L$_H-#hVh z%K?+$Ou3h22DtnN&u zesJGYP%Hmi_Rus?&0s`Tm)qaVb zogO^Q@$2JaTfk^6DLW}x0Gf)kl^`XKIwb=I2}&FE2ie$k{VTB%KehQI`%&;@FO&Cg z44)_b^$M$e<*tFaAEm%=nQxO6v)`7QEc3Y3HH`J+ht0RHE}hREp8RerzBtV;^O?qw zPN0LC3b;7C8c|~2fX$KtPvDr5U&O1Zdg+Qt+~gbztpD}39Ya6|GI>f*B7XJq0`A(S z{SU}&Q?C)-U99PF$HlD+$CE{R#U7aE4$j5=n5b)1>S8PZUfCtVA2|`6&%C3yr-j(h|9a>zp8Ezk(xmLJl2v8mS^U(3 zFT7zufp@D(Y)Pm>uF>r?|9ow$c<8~TY&3PHxKQBCd;HXzCC@+|A4cZs1><$mtC*F2 zZuxQCweF&S?-|btVaLk{LjdDZR=Qe=-1T#q6Wnjsh@fGG4^Y?q0w1aZd8 zksExCdKQa^r+fZ3;sB)`+pf|JJeGsw;RMsGv69p;=kvs^YY@tFqj+(OOP;q(sbZD% z?fh-}$tx;(Pq$n?>A$SL^}G0q;>IYlphsLb`ndAB4=CU{d8&qLwsmHtQG4<=D=N=f zw^yneyRlNfrYp2D4ZFfl9;b& z=o6gm0dx4Ul4C+aU?cBZzf;q)ztH~QJ)fc>&X@sr>-9X%_6&xuzt>KdB7k+Y-gEFy z@=?$j6b%uI)GiP=u9%OCQpI(b6?}Pdfbi1Z_)8pNTtZ^*^n~VcFzcW!adOVD{h3kq z4+GhYmj-p%0wf!&TZL-?ZAkOmtC`1TUCwie=_u4sB_hyRZVuYA!_%C zySu`K031T3=|>8kL}iIP8P#$AZtAPMsZbiQOcgp0cwpp_U32L;YXP!_u6`ET6k?nV zz-S?6zkMX*IRT`d20v^@W*6s51AQiVG_qJHc@ Q`e6Vob33zg6XNav0pps>s{jB1 diff --git a/firefox-ios/Client/Assets/TopSites/ikea-com.png b/firefox-ios/Client/Assets/TopSites/ikea-com.png deleted file mode 100755 index 08a5c017c9991dc26582399df2818c71fe28cb1d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1890 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 VH(5Q9xd~M2c)I$ztaD0e0svN61hoJF diff --git a/firefox-ios/Client/Assets/TopSites/imgur-com.png b/firefox-ios/Client/Assets/TopSites/imgur-com.png deleted file mode 100755 index ec963f908d5b1eaf2a58db1a993020824c4bb76f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2636 zcmV-S3bXZzP)bM{=` z=llI~F7JCTVFUYL37ZF&BQ?knGKzeK{0I3S0VXKEm$dv!(soGFdii{K7tF#-5fAbO zGQmbYawa70J(3rXEC4H!$)oW34uBE4?Qi2P ztvjJ=!+LNOgo0dt+Ne)Q|&+B=~~ZXhd53=N0??$;0!bXiOMtmzW%*X zT3*BgYXtI&JX1L*NSrAEbop>cnIJY_n;}ry6Wmc=A}RyWJ9W2T!Gdb_aDd*agrIM_ z02q|J{yKLJ3#oC)LzP2;K`j8Ml$UyZwy%9sY-aFuPq{=qtqj02xi0`+@)_FNTUa>3AWsz`=#mHEOTOM0{e*Bz|G*cM0a&ga&*#2@+u}I@ zq6Q!}I|0fXY*4o^3tCUU2)%zThQp&}@Wyxry!Cmdk7J)z!qIExaPVTOcOIITmZ4=+ zvl2J}TET2FLUD~1wjRlW{5 zFDSGP+7@k-1F*;xZni+zI|U1F`gG8?sSO-}MKHeSj04{MtUM&3wrC{?nhro(ZXz@f z<-wbumWPb_KCn&HHfkdWU;%KorNQ9U5)`{Eq@gxaTR8yp^~8&P9kiX!gEu}c)fDY- z=X=}E0SJPe5;F{(cc7ppnq*+u;jMuKFb4`;$#8hA7+yyqwG7ojwQvAtL5VvBj@%&g ze=Y=63)RE{2;`Bbh7>qDUJS2&A{JCrSwjj3!2k7qGXA#|qF_ZrLbXwi900WwzETq$ z8Y_UKpA-rW)kw8+0OXG^rN=|xxqKAJp$n*1s+j{IvEzgtj@&BH6+2F3asa%yD!1Sn z|E(8w3DvIa0Ho%ug9BIcVer<^bP3f?8t66vO}|Qq!SQ@u({wyTp8+V?WQJF7=E1Au zItMi%E%X(DWFzePvmFkP=Q7Cd_w4!#Kyj@Z4&TgSWH>gP^%H=$Kc>T>o7s$v*59Y= zBLKPOiCAzJqe4z;qWA%DAF;y08<~s>wFgqf4nR_h5&B0m;J^(#qeAZo=?nhc!J-DB zu-b%$W-xwmY)KS10Cj^F_~pmxj2~(bC5sz?&a*by|8W}QhmJE=F$0jA6ORSjn3=e4 z18Y{icmXJ?OMrpvRwe*QE8zmLajyyXT~A>GU{kM2ya4>-xEYJHFabbX2^WBtcg*n0 zwPYp$NGst2(D_d@^j}M20)Vs&Ak(mVx)g`vr*j+q5Q1%M6#d&lCLSs>IQfbfhOp=XQ<1ky^ltALJw#6iy$CJ;y~ z;R4X~hdAiI63YYtX(e0$UOpBJo{!cr0YF*_7l5knI4o{869CR00RvF*avXGh6vG4n zX(e0$Y&mP8^KvvZ6Qj{!%~~twEn&@niNYdRF@9)zH(K0#0yiCufjyUBVEo|PA0uu6 z@?VOD-J=G^5BZy8#SH*;3GX^bg|1{&XgO;T`@s{M?{zMm0tyD7yKt@LK z8fg4G2^1kTR3p{OAB<2TdqWKD7>5DXXEm=L_y;@6zzkjg@9_In)tJEvmmQ78n(SpA$UsDPz_WIe>iduq!+CQ_n#u5 z35C=m)OMDUq!^hr%YZMI~@g`A$6{d~NmaV2bh|0!s^@I**MZKSr+ zh$nwOe!jmim>mnw!6nc*{5XmodQjV_jiIcerUT$RL9B{`>QfORV?4Em+N1^Tgb08y z2+kpP07Y%jL&d>o z;iZ$$K;3&!K>gpsVcYp1!M0%u{F|oHZ!{0hOUux*v<{Ip(NzFu{De*FS}%I4nFFA6 zH~=~($+Auvfd5ed?#U-wtR@yqP^_s*$^iVE0&rJ8(Vl5zu>^&@RRrKJ1z=P@(NUDo zVhIX)s|dgd1z<=%v1-G57E4gbTSWkdC;+wci7l-=Su8;zZxsQkrvOAE6Y?KyX-O=Y zV34N@^T~4q1%UWc{-e{yhXK(bPZa?m&%-7I&?Wz|t-Xas6AbcH5rA%a0G1&SKaf241%Nm$pQ*d26RfFb7Et4)*v#PR?o zao5)>&A%^sJtY7{uX1d_>8fBMHGAS$F=g-v>63e|3_v(?Te(nac@Yb$F~~C&^KVNY zPa6Qjh9<+{2q*Gz%He>!iM80>3zC;kHLs@&0MV+l zBJYWz#hS=shuZCL=t-TsTFrcrybPOd0ElL_Jwcae4^&ohKS9V`=c5;0p54>^=QsQF zc%}dlF6BAFB<&r$yj_eucCa{o`=osvdN9p@Jzef?oXOun0x)@Eczc=+`9=}x_~R(d z1AA7gw-bqOL1MFlzm1EuBuz! u*T{d7AK0j%`9ae1Yf0N7N$be@@b3R;7KR`*Wd!;F0000jdBefb8-T`sDFJy(av;~iKEV`~88%*^E&^TOGO#>52n5670t zZji;IwXapI+NHgj2^uGVSl;&YtwsBTlas}!B`+d}1ZN^@gDYMMZGyC^fQ zweHe6Shyn^IfS7-8OhdaiJZmw^`Rg6PjF|Xt~tsm@g=cp*XX@;zBq-Lmf>Z+;$89` z%yy@A=h_m1x|xQobbD-4X20L<@M-t%u6^48&p_sK+TS21Gg@~@-p-q zXZMF26e@|*?>OA(O^~hyYL1Ycx)1^OFV=amUNdxYqWiel#R4h@Md>%e-Ar*J(>P5q z8dxcd>`36_@k=D<4PNhOq^H`r4BuuXX@9N>BZYt0ZMyUKB^4s%QyLc>K5%j#ZWJcN zny{+?$2!z6zdhC>a1TzPzY=}`v(iE*>1xYU4xl9Hs&bo15w@?kGitcAuTI^>c@hlREVcUJFwgU3gbUG` zA(vr_Q_1|_NCKQZv(|Ji;O(p562;KVReJswVH&qO=_-)&4H4i4feuHqj8w$F@JN~(% zTT{Fs4@PM}QSc(xFG6t20z=FqXX`3ckDdL8O1gOfNYbrA!MJCbgrSzcA znn@~CnKetc9c~t+#DpQbB3MLVYIR@TAUn6JEbzMEFo?Ma8#KOkP-({Hx2$^elYo_H zM@PRzS|s!o$_r8A!iaq_1qK2hYS+z2nC!=21B?s;lLfArKUBp!T4xoP<~7Kz8hwI; zj4gtZ>r2|Z5$+|1Px-NWMdj3sK0O5p@7G(g17}`-4*gov4+q3jlPcX6)y^|C!9)P5 zUOlnoBIz)VD#@A4QFe@F zZ@WeJo(ogejf{_5#vkrw@CjrtI;4n1eYPu|Dk>s@IDYl;+R|zFMXnmHu2-Xkc4n~Q zIoD;UoXi)`(bU^cPI23?Kn6CxZ{fi(rIpS>3pB#ILSF2`(C*8vT`gtpk9tP23rF{^ O5!m9-+LWE}i2fV-ym=-7 diff --git a/firefox-ios/Client/Assets/TopSites/instructure-com.png b/firefox-ios/Client/Assets/TopSites/instructure-com.png deleted file mode 100755 index e874d6c5da352d6b73958598854c66fe42166d31..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 147 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?K3?%mjbVdLv&H$efS0KFz3|!PN{sD5BN`m}? z85qhYpS1w;%spKkLn02py|R#(L4kq!px((zbA{NsOgO)|1mN!JmCA{Cft4g!`vkwW`zNz7(8A5T-G@yGywo!e=Xbq diff --git a/firefox-ios/Client/Assets/TopSites/intuit-com.png b/firefox-ios/Client/Assets/TopSites/intuit-com.png deleted file mode 100755 index 45599f9f03503d6c251c90585130cfa654d67d3f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1194 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H3?#oinD~={fl(pAC&U%VHHkhnig1NM{j^7J zz%Yt03GxdDh8Y_>hmf#{sF=8fq?C+;lCp}Lx`w8XuCa-^g`KmDYfNl%N@{jaUO`cD zOJ`U2go#t8PMbMv_M9b4mo4A0anrv22Tq(kb^7{^+js8XfAH|p<0o(5z5np>)8{YW zzW@Fkd-rJw0|V17PZ!6Kid%1Q=Z4=h5IIoTyyA+l>(aR$qHUAe+x;YhC9WFkoI23E zacffOj{EkA1(#ozSj~Oc&yno5EoN^CdmMv6 z1@re!QRk%A*lY9L(6e%`Shg_u&N23gZV&KXr!#)1qh z`-2nmZh3jKsk{VD#tf5K33sZ_$ImJdS@X6ALBwM>x8H3YzLwf+4itc zd9|kD3Jbe|ry)~R!<55p2FoKFRvu-sVBc~slA+Vx=0I{2;|DQ;)dmbzGaBM762t>; z^Rmu)z~tw|SR3PD&$EH`L~biX*NuiGjt5NA1%gaJ`gkQSGO{g54`7U}IgqWjpod>0 zm@%}*VJg>;7XFN2M)MyH(pnF+?H)*rK6uPrqxC>eULb(cp!u2ff z`@~P~A9?J0vOfPUoD=-l$*4JellYhEmju84T3lJL>wbU6lxMZsZfrYV^E;Ive;<;6 zej>kyQCEM)K7%=ep&{}?n)b_r>jFG=_AI^?p3{DnPwYToZA|{AxQHu-4DvVD=h*ao zt^KAg9dv*}q+;D$t54UT@7fkzSJ+ulT796p^6r$~cHf_xc9t)Fcl^;GW*+G-c8M$f z1p-OlQc0X|_Lugw3q&94?9A`(DO!5eednd5!#UZD4(GgH^ti^`$$!bSNw*r0F*T#H0!iB{*k;QHzs=a*YH}wpM51in-mXT=d-E-q_J5zB zmiCFYJw0Bu?#vTzzWvc>Wv|}48~vW~!NJ{cw`IHU4AqSPcmbRi?ca$1?96-?eqtjZ QFhenTy85}Sb4q9e0Om^&`v3p{ diff --git a/firefox-ios/Client/Assets/TopSites/invision-com.png b/firefox-ios/Client/Assets/TopSites/invision-com.png deleted file mode 100755 index 3ff2b533d93a95b6b9eb4159a918f2ba889fc9cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2241 zcmeHI`#;kQ1OCpkX*Mfa5p$_SxevLu5}HD2Y;JAX5+Vl+aU7Qsi`OEDgvBPTQkYxs zgjpPy^Ge2Ek-OxO6O#MwbezxU{SV$>&-3{_&-459c|OmRhIhJ*fE|Yc0D!Qw#kuS| z{clQv_jPqLYYPA*Eb$IRoA3YNp9KDo1O&_ZJ^PhviEwcu03h%INeEQxAWRyLkU<_g zd_)d)OyRhqlCr9ry2h!~np!$~7(=5o#-?WGXR+tbTUc6M#M#)|**iEo;hkLwL{~R= z56^2PvX{3Hh3f0)A8<1;=vHt@Xc#T>PIOFcd;&c&>27igBlTa*jLfWGavtX96+A91 zVsna1O3S#<%3r*!sI024t*d{;xy0*TtxwXBs_otD{Z@vH^NwdRQ5u=9}3Nqb^HgcV_y7l$Ni4|Ew ze@mRI-=VaEU`BqHDhtQ3&O@baog5=NNTW{tAO%NYz_63k?uym);Kt^Jim?s1^>>-3 zTaaGXx!E3b<+Zrp=8cs*OK(T9wNjsb+dlU_2pY?~sq1=3zQ}3d8%@kgT_O?vm~QUp z{#0}Am$!XC;q%bswQt&_XAYF3oGKAv&#ZzF@VQ!%UoKsqksw=_+y=#8RBHgJrS{4u zbOZ%F1ngVb1n`zUMsRt(#Nz4D1rE(gS6eio9KVLlYmqh(p`WO;EQ5sP@nzPtNEJ}C zbl!6M4B)LanK}bpodOzlpy zyvx1EJ#*w;lC9wMEo@Q92OsCH@iOzq6E&b<`i_L^u9ugU;q40jjjI(0RGW?(ToULB zaN5|9cLs0CGVIDG(!r~>A4~QMOlCQ#7Vd5}I-&f`L9o&diP+*mG~8ySRD;beT0%*l zz9BL9GgViYf89|mnucfl8_+$W+5*A_k2R4!?PbF4>R_e2)&Tk~lH(!nP_V!29GeVF z27>Ygt0RSCc$pX4&IVFKIv{L|7=LJl*I_<8aKFu~XWY=P|tDgyMVgVZ9k^~r#vzf!dJ5|r8aov44$-XZQ&kk2gR7_%L*6SwbeVFJeIdb zGLSLq1;a%Zg2ZXC5X&P9l^j5v@4ClPr#ne-3LRKpv7CE9T z@6*Iz+I}`d=v$lONYSt$723uxE3H7-bkrf~c|G|jkLq-i=6M)P87~<_0?;G-@kjpg zs*F?#icxb>w#0|h86p z2o;6tJ1XRn&hDD7BT?9c4L}z0oee?Fp+QFcV(OvYj63iC6zI8F-*?E!uOo2Fpm6~;H6HN)WL%V!sP&g^#} zdWg5}Ipx^gn{m$@N0FTJmX*5r=!gM1Az0`*U#K#+S8sY2gm&^aW`yPpTcG+IXHJCI zs-m~exoq-Q{k;JhZ)0vzB7;>j7fxDB@G*hnlj1~*ipVY4n$Yt{JV&2aNo9O6ei(Ac zbI%934}t1cvgfA~o@%zKuLtJ$hssh?(LRBMl?F{tIW~`BA#S8vh; zp)=7j9lAx}nInkm0?1$y^|j_p!{~>EDU3Nc}srx>3#0Btt<$bZxH7NThZ!^=tk(V=d-W0tkL(V{ReI$YK9S06QBe JT%|Q7=`UV#KM4Q; diff --git a/firefox-ios/Client/Assets/TopSites/irs-gov.png b/firefox-ios/Client/Assets/TopSites/irs-gov.png deleted file mode 100755 index 2c8986235a6483a8456930e11c153378df612780..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5626 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 ^!YBQvE+a0gf?uhe< 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 diff --git a/firefox-ios/Client/Assets/TopSites/kohls-com.png b/firefox-ios/Client/Assets/TopSites/kohls-com.png deleted file mode 100755 index ad486a5541ed2b98c033e60551df051c55d69593..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1541 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 a&m28#XItyMpk`p^V(@hJb6Mw<&;$TsJ!)70 diff --git a/firefox-ios/Client/Assets/TopSites/live-com.png b/firefox-ios/Client/Assets/TopSites/live-com.png deleted file mode 100755 index 8255e40097aa108e0b35139c6eb29bced7e09fc4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2417 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 CatrkU diff --git a/firefox-ios/Client/Assets/TopSites/mashable-com.png b/firefox-ios/Client/Assets/TopSites/mashable-com.png deleted file mode 100755 index 42d62dc371455d9e43ad9fd904924ddef6712fa9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1367 zcmZ|P=~EMT7zgkroT5aO05uh?iV8E7R$F9RItVt1Sc>3*70`Ns2RcQh999@s+DbvG z6+0*(BTRLwRT2nk0-_K>L=Xflr-H^HVu+Bvcaz=yrR%%C=`)|__yfN46vjkHxHwCl zAqaAb+$h^3Z1`O}*$R`;oi{^}C^IH%TR2pMKyt)Jpg=@&M5I7$6^NZ2u~Q)Sa>QPk zwTMG4;;29zYf-0KbWR=WEKs8Jl&DJ`>Y_x&b*Na0xGK>FN_3&19(5C_FiAZsQK9Zi z)V&^cSD_yDsD}#mRH5(vjY(CQREf`xDq@Lj291(N=!{e54Z@V}NYSBkX zwD`|U&j+NtYo1>A%$m9ulm_K`|3XB41x3U!RqPh87hOH-ZYbCb1+I~0R2g30sFY@~Pi|u`zLj6;^Yw~1g6*plA`1$7WwCtRa zUTnjWY^XOn_En|F&bT95+c$=n3xi$+2FM^)L!$oCiP~T1!0mMjwJjc1B1?10@cf>k zV>X>^lD16_&pp;%a-}tMK;{5jOLKYTQ^&PcT*|Wv$0ohwQMgp98VZUNeGW;z>!Hyv zB~Vw7CZNsD&l&2QEc;C56J}qfkFT>gF{W)v(7fE<2zBEiR9;ym&MCWf!^X$INSt_N zehSn#k&(1#fAV&CQ$^nJiwJ`gWR<5c6UVLIe6Zk(zg!cv`rKcc6&EP=nNPF^vhYyM zgT)zvm|422q9gfsV5jlw#1H??$L|MVY)6X~*O>Bb8uxDzhi-3f79J)P86GW@uiumZ EFEUIc1^@s6 diff --git a/firefox-ios/Client/Assets/TopSites/microsoft-com.png b/firefox-ios/Client/Assets/TopSites/microsoft-com.png deleted file mode 100755 index 32db2a40c87c8a8f7776b8105857500e52386c5f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 198 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?I3?vN&YJLDIi2$DvSB53;>vu7H3Q+pLlL3W& z@^v9l4NFOoUoenn*gQFH7Lbbcba4#HxcByqB4dMr29N RUA`^IGEY}Omvv4FO#p8*KfV9} diff --git a/firefox-ios/Client/Assets/TopSites/microsoftonline-com.png b/firefox-ios/Client/Assets/TopSites/microsoftonline-com.png deleted file mode 100755 index f50d1986bb590ae406575376f80cac71c9265288..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1695 zcmd5-`#;kQ0R8UC<~c()ueEGb%V@wn{Z zB?bS3K6;7!Hbo5r0D2dX&DxS)_vXY*viVQu(2=q1OHIfeq+p%mdi59YhD0)vo5ME8 zReoylBh8ukH0;!t7pS={e1^!OpGIkq#;;%(=L9RfS+LD0N98Z>okIybhh9Ie+1UAF z;TX?eFzfkj;p3*^i9|$nFwI=^^sHnz_(^gH;wh}>;a6U+X`!)9`#W8dj#7a%&>1pT z9L_${V_<{&XxSz?2S2Wlhm1^sRgx1>IP@OrH7=y}VLsJwF2Mxa+Cm3JtLWpb%pY*L ztCCaT{qJiwgIXqb-*Vrq@WMqyGI<}u3phCXvLBg0;0qBQUJXj5#b52w-9DT=U&wi@ z(Q%-B3~*vifB4{Cq)vIe*Y1T`R!zE** zrTsXV(u((mDr$NZ`*(hqff7ua`TcI1(|(>Esv36Acltx4Lv>TJR_h0HLCe1~qpz#1LsUUxO*H*X#_1v^CdFpWb0?1lA*`YUDH7-0KUT(Z^Yx2M%!L_NzX0l>F3fSnv3l7WPAEl1lEMLL2fTwodiVsio*~? zb=rYs#0wk&O|$ppt2=S)t8Ch_FXwFgkxQ#4Jv5Iv4+Pap9(XU)QR$vZ<9<@dWm5tz z5&2Eel6$G5)*>`MRX#UUHYOiwqb7_XTV$`G8P%a@p5jHB-naU!_g0;O z*FdIrWfa_9feOnjHXM}PytpA1a-MXmx4EN=ty&+)2WjV3ns$S9Mv?JMMXd$t_Jy3H zfzR6xMo!(&1t>(2!foHnaeQFU>CnR|{y zm);p+Mg2C=tc2Ts2Jh&0Y2K(gP6{q^M@^QS2?{ZR0S3C&d}~*j<{mo1Pn_NxV%W#+$OMy9-VZzCNd%Z~CApU) zE~=sSkT7b!1uk~B))lt08RK#9er{b#YEZ&eRF=Q{DHHeDG`;{>Kg7O0G7dI6d_9ca z3bx5}?Adnfc1tmnCqHu&>kZPAj%5az8o%+s^)3G|PXV|u14giL1CA_N%~@y*N-OXk YA(u1{C!gT;E*%fR^9x|N`iQds1&c<@xc~qF diff --git a/firefox-ios/Client/Assets/TopSites/mlb-com.png b/firefox-ios/Client/Assets/TopSites/mlb-com.png deleted file mode 100755 index a3e9c96658d99c673546b30fd88b63b414dd0af2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1967 zcma)-`#;kQ1INGH*wE%Wau-twg*2DMu({S;Qg~4|n-VV zxI6bpKvT968w@xh!vYO8p*2uhH)H4P9znTEK`d$YO%mQ;{*0_o4yoB-?3P7TboA+- z3(<>`EoaLEDU14T_j|q_Ou?DmV+H#BF9gY;aWx-XH$WY5m~kN26Rl?s+S#bH>uS~) zF5nicVMAgoj(S!~!l$fB8B@q@{3GfFBf|h=Xb6(W*z>yR>+fAZ48rhum~LlXVu1 z03R?O6hH8zUTKabp~lDVggs{rv}xa=*< zFg23;AgT`wD8U|dv6ga1Ak;u_0qQZ-t2P!%2tDkdjqH^%%YSI@*vabYD9=8wHTDhQ zs!S;N=FI{+^4oj_8(w$C^pP>K#+JXiSG+l$K3|n5&v{BZIm}4g7xfB=eP{fNYIL(bDv$vuqt!^}Z6F2m zK5UEF+k_06KYFHkGZ-LYeo|$3F@mWl}-3&l@E3B z(4J_Ycj0u0H$O|W3wKkR^~Sy>*>4-$G>TxIJkQ*gK@rt#bz`FotCd+l&FV?>E7FDU zBV1L+6fRKm-dtqghifXJfi)P0=x^t-477+zAq{gk;w}Zhkg} zkoJZS?tUpjaUf-0^@wCdtAu_kdwW>tyT|bN6h$a3u>H?4pPLa4@Tk zTi@qkP6Uk<_t(Y126*wpM@u1{1SENWNj)`7b%!qFllz0(R*uNpY_H!au@e;n$3O}h zQ522EY{)KjUcAxn4bB#!REG-dg-P>pp;ZPeb(dWjPjnXc`EnhUt|rD%X}@9H9=*w@ z?zV$G!Z5A&^x?LfkYm9)MfLL!w~ToZ>QwA~mHWSY`A)JZye0TjPJ_0M#on(>Ub#4Nz)x*tjC#qQ(9b%LJ8y>klD4Djm=d6OfbSyI0HO+~1i% zTA=zviQ94FdluJ+JkAXFS|pzQ`{*G;-U7q$qqcH~bF8*d8L4b^~qZlrD z1XCMJgEAAV8gI67d7=8l8bFDW`P~B@FPzQYBopg40;b;tN@fMm&29hsnvCx1``QNy zLA&=u;!01f5b1}R`)4g-&hg8#x%_49l53eyXF*Is_ECXzx=9bCLm;{Lm+FenUZ2EN zqMz@HOsD2JD`Cg=dYG$8p~Jf?UX87GtAFu@!FO5{9wzR5Ir}Y9POBlJV5D~M{}VP= b_N||g+pHk>_l-2xuMh*?1R}o0jdcA#q)30x diff --git a/firefox-ios/Client/Assets/TopSites/mozilla-com.png b/firefox-ios/Client/Assets/TopSites/mozilla-com.png deleted file mode 100644 index 41bb981cdbfc16307fd08f410bc9687565705906..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2393 zcmaJ@3piBk8eTKxPWE<-Qe(PmGdIkP$+*o727{PT+Uzm2FimqYGnf!V>>}FPQqeiN zM7czH_DPp>IM^kM5}|~IN+MmzU1v=@?Q@=UI{&lQfBDw;zTf-(|M&dQO7rn@)z&c4 z002On?nd>6M!DiuQ-b=b!K^uGFqYB+rGCONX$(sY0!|!ZD2Sl*S>d2B$l@G`Yys^6 zKxq?~87K{8c#_ycK8mIALCN?c2n_&s4l)so%>$)~P%xY;AR{OL{!b)=%ON8JY#11Z zhyq4%-D1U{U#u6C9m`|ea*z)82s;@GBH)8k7DC3~FOZOAWaMXF5;Rws(MZH+7b%a7 z{6kbA!v{eTia~@8%F2?B!D113JPK=VgU4en5I77LhsHn;-V$p~vcZ#Z1jLtygrbQ# zVI*Iw%a>Ttij0hqN<}0zIwmFt6=Q`Gio?-ZTU%QN2M%Wmd00vg2&62Tr9iTAg@Fo6 z*kZ0o$`uL_3Px6_FiJ{BLQ4NgfiL<>E0BEICTPRZGL{I9MPU>vtvE6m|KF9*|LQG~ z`htJz{h!1V<^d6i_5~%vC@~v4xUh|iP$CjV46>v`F;ghqzp{%y5kjd@5+M{JD1Lav zHU^8$6(|hmpAifOi7t>xSpqglr;?En2a3z(kgRdeHqJB`TfB>lH5N-F5V15I4M(I9 zY^jk>*VC5zP^56U!SR|>6tJe*MD2f{u>P z=;-K!2M;tfG@d_yJ~A?L?bG}EjB_t$7MMXV&^e8PYO)i)3 z+qbW#rpDjje{gWn)z$U*@#E>~>Dt=bhYlTDyLRo&%uHQf9goL*_UxIVp`o#{@vdFF zEG;d2dwWqRl()CHR4VQ1>3Q+ug^!Pqk&)4!J$n)p6Z7)&?%lhWl$0cs$!cqBySlm< z3`R;yN^)}Yv17+9`&X}CEs;oaa&qS8 z=9-(E4<9~UR#w)~(9qr8{rK_Y+}vC=8l9S&>fqoI78a(WqLP)B<>BGc-rinaT`d-i zD=RCpSZs83bYWrP#fuluoH?_3^XA6J#^U1Q?Ck6f8#W-3$WNa>L073+5jh3AY>&~Y zPE1+v_~RHq6Q?yQA_LkgPlO>7!SHe1Sv@llH`x>%N~j4eIw7=n(Er_Co>;H0-BKc+6V2|5G6i3N_u!Kmc2lv`kChWJ z6K7h=o)a4ev=;BIx!w_UvximDZ)`YpesuX8P>mo-s7 z^q;kW#We$Uzf@ZOmeRM4_=Gzd(mm>`L-riNI_?#el&j`tzG0uc&de=LH-(K<+}{vX z#`|=0emu@OJI(%@9^maKD5+pOCC1*KICuB7K_6_sYSMq+G|=Y+jgZoM&rXmATS ztrOIxkKw>qN2;U*8oyp1+u790)eZoTZlB?@TXjPk{2i@2b>R}^+$sBZUdS@1Dmc~> z`|!kVWuh^r(SWy>ZdWR`F_l>0pSDiRx1E}l_roAx^?UQ9 z4QHPwS6(p~ozFS_`*#JmVt(~_WN~C?QSPOl<3~;rTpf2Tk7)_qw#=+bAXbPC3*3{z zExlP8A<8GS>?DQ-tM5w-REz(%+s?WqO2={S(eSZ-5B$`hrPytg=r|g=tMxkp=BYB3 zCH8X--DY*O80E`xMrY~K5}ltWn60bo75@!i+H44H)ZxM+(@ z&p$A7-rCD7_)>?a`}X=`VwWK%_2mN~UFASdjp~Uok8Qx!Oy{7@o6Tl2&E5$br-uk_ zKCtraZn%dx7f5Qnk~BNalna{T&JO>^l(+3jRx_y&%XA}#_|DB+0gLcJ;3FJTFdGhA z%8(z8t~W{-YG&ySmo#NlE|mhOJ{~8j{5@Q)x>@N8x3ym{KxCTVVjk#{$rHaCTL;+@wi3N;Y|1m#V0z=i(2LU HQ}Vw6(W%Hu diff --git a/firefox-ios/Client/Assets/TopSites/msn-com.png b/firefox-ios/Client/Assets/TopSites/msn-com.png deleted file mode 100755 index 5bb3403bffe0656b9c2d47309259dfc84fe68f1b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2663 zcmeHI_fwPU8hyV6f?z^aS_FY;0w@6%BsATHAVE5YB27vVq)E9by?%-sqzGaR!m@@U zD^|<^zkUv}wzL5NLLmA0Q3Cq}h4!N{ z!q@``4~dA1iA&%POG+J)k;NZ9Mj*;799JYMDgUCXc2b?Jp{b>xOt0_ zcsnUMCG}2P`rV9sOjc%A_V0f@WasAP7d$Hb^Knt}lhU&Crxle|)z4~b>*}93{Pp7R zM$XHoSFf8}THD&W9dA3k-}Suj{qV7WU~p)7WOQtN;?w6ZlT*_(-)86L7Z#Uz-SfBf9q-f1_|*#Q8>Frn((Mhw3BeU@!;9@nzHrZf2<8SNqO?tDwdCd;RTe8QmT zi)NAv`O#T|Nrz{C2KV^EOGU5ob+#(*XOf0fY0qzTqpzxU>GkYq=y)&Ith;tOUY70R z*05{Xi&Jy4ALBkQZ`oCQ$tV0Vq8B;aNTu4=%sr=4{of9Ec)5;ZQ+qu%*sCcjoP?oP z&r~ri70bberac_Iv*;)USx4u%n>#UObjI^b!f@y{>4J0Ue(}&eDuP|4S$r8iZnYD*@}Wz;t`k zISs)E2(<)!iUMJTJm<^^cw-Lhg&<>^_;LfYAyzPS)(_>t<$v(_FdZpDXL!NvdSIV& z8clIoSUOGFULbQwQ4p&N$_eu=yLG>loiQ_ihMMgEN+CYvW@4fp9}d_I0IB&;XZxwgh%F$-q1lV677!6InW$bN9vu5jD*cKIfhnSos6cKq_2=uHRQ+7vq@w8 zWU6KKsQV)>Z!rm?Ivl%Dc*C@sOGbhCqlxPF+V)P)qn==Cm!WJ9uLnsOKQ|wIwRv z5bn#UFC5%dg0Vqe(WY}1Oc&C^D+Dh7CuUe7EFuFle!3lMZPW;0Zu|&BHM-GSp$H}I z;!Q!`sszEu;n{!N!L(@3O2*q$Vj?D8J~9NtvH*MNC~wuC;OA8M!3=ps*s`szEemzA7r0$KUD9+jB~ zvIIcE%}lT3$qp#fm2?|GZ(M?&(K2}*VX5(=;NgKu{lk(W)N3w*AQ__H-!?Kn-^z^Y zPrCmQ;-s*dRA2z`TO6zF6ClK(!r^04ctj z;0^O#}OA*7Do3!@S%S&;_{etiJYx~Q@oMU8^ zj4V_{2S!RpOec!b#nUg#khI7kq-GAYKKb*)1^zfkj@Bgcw_JUr-g%}ELqn~wmB=eS z**(fk3P|hA&7X;L+G=+r#mCld`ZkIzTv4)0xIuX19u%ionwTX#*0wY|c6mD6ku(yv zrmoseer6}l*|3hX(H3`bm;B)*O}`$p^^H30F^Y*PN2fa~U@9m}g%68`y1&=QxF16{ zt1Ua^DRTTbH%{|E!DFoWBA9s|T!{eV=pqP*7VE2=G_DnGmip8Sv`;nk!93PWq~Cn> z7__K4kkAr^8w0b0`wBJ9Q>|_7qo&%_m*bo%YQzRiF$wqmp-EW zj5NT^`RS*c@N{Z1P2}Weq1gN@kXxOrUykb5*W9s?Ui=StL)`F$eS_zg-aUUmRIC_O zMcjp+YgV;{mRziD`3jN}*3};euFjMI9c!Kz-%nZ9#;QdUck|KcwSu;nLvq>61re8E z>g^4S!c0#aMOJ}+cSNT~TUOJ{VKd{;~aEoxJ+x4^)}(2`ny HhJO7Y${9IE diff --git a/firefox-ios/Client/Assets/TopSites/nbcnews-com.png b/firefox-ios/Client/Assets/TopSites/nbcnews-com.png deleted file mode 100755 index 4f7c467cdbeab1f1b24eab6a96e9ad608079996b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5411 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 diff --git a/firefox-ios/Client/Assets/TopSites/newegg-com.png b/firefox-ios/Client/Assets/TopSites/newegg-com.png deleted file mode 100755 index a98d2fae0f90e7ac8a3f80f181d8ea163ddb839b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9775 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 Qk6?g-uF1V>ZReQ(1K(xZj{pDw diff --git a/firefox-ios/Client/Assets/TopSites/news-ycombinator-com.png b/firefox-ios/Client/Assets/TopSites/news-ycombinator-com.png deleted file mode 100755 index 5b1f167f4a9c8ab252f138536db02b4291755c07..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3964 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 diff --git a/firefox-ios/Client/Assets/TopSites/nypost-com.png b/firefox-ios/Client/Assets/TopSites/nypost-com.png deleted file mode 100755 index d9ca6fd43edef10bc26a29eb3b797be07352c806..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9952 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
    Sn)B~4cSJy+~{iGSWMFW89S1*ECie> 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 diff --git a/firefox-ios/Client/Assets/TopSites/reddit-com.png b/firefox-ios/Client/Assets/TopSites/reddit-com.png deleted file mode 100755 index 782b44561f4bde63d34f43c4a4769535c1ff4a6a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5328 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 diff --git a/firefox-ios/Client/Assets/TopSites/sina-com.png b/firefox-ios/Client/Assets/TopSites/sina-com.png deleted file mode 100755 index dd0177b1d77600007dcb96bf5c89f64fed5ccc48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3207 zcmeH}_ct2~8^6 z_t_@^0C3yJ!oleGdj2o}Ch&id0JHhmzTfYD9Aal>4*)O#89_`Jzz}8@RyKAHPAKdm z7dHYGpxbvsLc_xEMnpzM z$Hd+vk>lbiiAl*RscGpMnOWI6xq0~og+&jFOG?YiD=MoV*3{NLs(<{Xp|Pp?Y0EQe zYg>CqXV>!=-90aR|LE%bJXLoP^;PCU8uiuWoAD^85IQ#i)Rt%2@03h~e7y}1>f!%&QmirUKh4=fbtI!mE z4KXn$3@$F`$tz{3^`kM3pdsfummBIF61eY=?Iqzk|g;qk=-^}$SXQZR){V4Qya2?!vuIc z-M@w?;qUbrTYpRl#Z>?MB^&eJthysez+Hm7pNOJEg=4voDc5d7+~){PJ~CB!ly1 zfy0=DPo-6>fCP8G%AHOXo%M*~U7nzidV|TmD#u4Q;zEf+f^q>{;M_Qb%Q!43nEfHL z{{Y}vXYkQgq*5VuiXv^nS`xA(S zlHWK#E^)!8sm{kx&N1#r!ncSt>aGanTFA1|d=%^m>3tLmnNX)lgZS+O&`eoI3P zThNiDc&6e8tudo-$z-T9qsYDo@9>=f5{bS#>oahm^9vP??3jsQy2n8ya=Ac?zCNuT zW_5px>}a4W;l#023KA6}PjB{DPBa$t1+mBC)T~?eC~!j=Xlq$w@07yL?nuxDa(yVQ|1Thed?qGeUv+i%y=QQ~TSyO-n=8ZjX z-CD|XQ&RYf=%fmRJQQAe=rrXx7pR0DP~(dk?n3maKyb0fn%zWGlZIoW?)cr|0kKLt z+N6IWHhJE>#KSWD&4AccwMP~QI*`ry&SVU^*{aS!X3C36ct@1{H;=>21Y`q5YJ2ne z>s++*lEk{?i!Mi2o!@l?+^V{N+VyI&i_&K|MNxF!9;89Z3H z?9f1x)Oca3OoTJPH!TdzA6iq7S~)S_+yLT0DrsSVDklz1IhWw)+|Go%UbGZg!O@bW z-8MOtXqaBAVOv8v(3y49heI8x7oYbt3b50xZPY#&^ii=kUZ)Dy^?G(HgvUVg)c$h@r-t>6 zJF}Y`x?OrIIojn4d)x$i7&cB$%XKJbz28;n6o9>4lYPkDKjehCPc|mh7`ZEtAfx-b z#@_!WfcQo>-g!6_xpE~hvOX~lxRY?MAF01Gw2X~3xMY*7oDEi!4ktLIl6 zHiOhtSVSYSP#t^$n64q{e=1QOHIo96E__AvMOYXWU9)aA%i4YPfjGER)7UFnTDoA` z{XGW4#flFD`+y$@?4=g5=iQ<_l)>={ra)BFeTTAkYxgQtA}G`cL251JumG5JkE8kt zh^jdI5|qm+_jnHkE^lg+-%pn%e^c+~&q=C}5>jQ9ivn1!(VB@6FOV^9$J4aVHk?g$ zD9^!npr6wpugMMvmfxe*EO9ox72g_`lu*Wu`eay znxo+de`TzHxv>CVrQPCUCKDBDFxsl6UqVg8%2dijXi_16fO*q^4tTfn3$?6a(?ml! zH;Ap1f;&RP6_k`~S6!dmjCFNpXgDqyn28Z$vwSN!l8lyCGV!$IGaK26I)^E^!-}v! z5SF`*=Z&t@QRwk5M|dx0TXu%T=LC*{+m=y4D^PW!(^U0obF28FN7!!Tb=0}7rq;pv zXRam3l?{p{xrnGd^W;ej_~N?2;SZN3$8i*^5@@{6Vfx93AypA6A5)qw;!<%Lhcl4( zdZvcm9m2#SM^Ittu04+fgjlv=a0!@G%FZz6f8L?+R3=YNsl+3?@&V%9z3l!mh(HxR z&tb`5PAgp1^<1R9)9VaaXpRX^%qWTc(>qXv#iq$KI2J60)~|ZKn?&a&-@5$MG>equ zcbw~JG07**bltR+#Pu#e;5Gef=rT*vqbf(x%HJ!$wr;~WM(R8=by=I>Q0t1b>WL)A zki!b$fb~pm@F>jGG?Mr>{YQDk&E@V2hw}fdV$|-Qj{MNk(CZ~kI>sZb6){);VXSla ZUc^tp4YRi?*xwZkU}j{6X+~q?{tK4(R4@Pl diff --git a/firefox-ios/Client/Assets/TopSites/slate-com.png b/firefox-ios/Client/Assets/TopSites/slate-com.png deleted file mode 100755 index 0688958e420d9856056266068b7ee749a48f536c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3120 zcmeHJ`8(8$8~x0fEQ1=1C0n*g8Y0UbWM8un5w5Lk8AbN&n##3>kY(&7WZxyr7=u!l z5p`wBNEnP|8f2fY@89vg@AJIpJnygPIp;iYqNTYZJCq*^006tOksj)dG5=d;hBMq< zNIwJs@Rp^ijsDsB`@i{5f&UW)QopR8IsPyhWo``sATR^u93vAm3zU_O{rm+O2PYSt zn}?V0BENv3knklDQ896e%aT%8q_4_cL&(ZqzoDq4tnvp^RZab-hNhObj;@}*fuWJ{ zEfX_y3rj1Mwasl?yF2y{j(<8iySTdD{mb3M(+ll=@4k=k13&+Oz@XrehoNEN5s^{R zF^@2hpFEBIJ1#yUG3i-yO6v2p^o-1`>>O-vUVcGgQE^G>%d%JH6_u~6YHI818ycIM zTUy)N-*mj~?CQq#;`<2w1B3704}JJJJTf{)9RD;i`T5J#*Xfzrxo`8Nh3|_$mX=q@ zt843&jm@oX>QCCv?%uEcgTtfalT-SHuVOX;FdZ1{Y1@R&4CY5`nRyAmFQm-R??!ZG zP2|sAZZa}6WNNWAzmb6#4UW!cFo~887p`wt5;jTbiM)hU>}$_mXCN z$i3V;I|V^SJL+U-(r@Bvbi`Ot5qbZZ9>dN@tzh=7TI0hWA?7nq98)qkUbL#pMf=?; z=}LUu&OczmR>Je6Ws#-NaKcYR>~RMCl@J>p?;H-y#5CDeJHRDU;E4SPTP`ala3Fvh zg7l@@!Dy*BT9|^^O13*Tm2Gx45(G#wJ{9jSVpd|KJ%~ox)v7HvBOI91mGw%A$PeWn zZjuLpI-*#I)7}moa)1TeXDP;PAri!iJ}}n5G;1KE+p~c|6*FJJ1m(2*wzp#n0|n=h zF2A)5D&S+$f{&O*Wo(QDOnF^!?PyM4GQBMt;R9ks)QKZM_ZuOyfggTp1=YUsNEx7u zRpNa_p3f*4fA^8fq)V{)9>uK2Yt-qD=!%aO@8^9inweb$YZydVzh7UF%pQu4G>{s z6iK#~%3%y~s#ZRBHr8$7K&dDSd<*>4FHhV17%DpFg%0A1syyTvpKx+Gv@LSDgocE} z!Wl?fL9gZ20k`Y)yT8>@R!g8rUi3TQ#)3OX->vp4zXy;(4;A5S_yr%!lgN6A$+UZq z1}D5+{QJ)1?)3IA9KhuYG^}27M z79g@g52I5xY8+?%a@TNm=;JL&l^Rb=DYU1@Bo$)UiD$D zuLopgu)#r$lNwfgzaN^>VwPZA!~haLt~w7KK;7f_NSn~Ka`USU9gL7PA;sI=T9W#S z$Ad6#kYM>$CIV9pqpQ$u+gU#EDo)G?vrGfsmo1j(0Nc;?*xEn}Y?)zoa1yRU%lKl> zuf7a^9p5_66ShpU;APEX(du>?bA_nCyD}^-Gx2kvuSMs>mnh2TILZ3 zE7A&znzWJnw5Ge_Q9wwjdk)nqoSq1i6Q3(ecXeQm)105S5hTaWwnEbukbBKFE~Bt& zHvlc$_bX{z3L)_L(+&Psqa+g%KU`-Fp8*kl4;j-Nd+j)xsC#Z9+_U`$*I9SzGPQZV zqC4;Uo{yp>U2$Bh&#iFL5zx?nzh<>sXkC_j4uw=Ev>AhU|EU`!wCwwX;FmQRKIKn= zgUHcS9$3hmo8zDe#qp><nPnfAoSmwxt zaxzBwVjB%lLPIu(kw93we2Qby!)+@m%GA#sE<>Pag2tBe0a4|}^z*4~DA2>N8bNE1 z72}C~`Qe2lX8wkb*`(C!62sSHr1p>!-sG*}0O_bQ>u?CCCvf=LTtEJM{$`t0L-i4!1Z9k_qdQP|g)U_i&U zsW|XJ#*iC;xbd6p-L&zpfnctyX~{p53bJAc++OH6K_+iQv<`0Jf#Mn{em5tSO{*5d zFi_3r3guhiV+9Zz=P`THB6wLeP`YivT6-Djn*ZJi5SBBJw3GxfU=gh=8;VX1x*7MA z8PYC5uuM!P0zc%i}!6U?Recs>+GcCvlfzpmk;v)M^MgR-OU7xfYreDrsK|tZtoK zk?;-T1L;Z8Ltn@!_;LUz_xhGgHMlTqM87QFZ_}x&K0hqFAvhMkNm{9N39SNsaTs}( zVgv2HmWjLm-C_hFx3H6PTN3@U^wKkJlgkjJpVgbMOs<`H&oqXX9c7wU6Rz|p@VI&^ zo0&}p?&{uny-mFL1@TdI2RNd2C*yP^GK~db!bMj8MD8Jy_1q?b>lqQY*B2aXm6KXLMW#JzHgAT1%Fo_e%dtD6|$Y zX4}}3mzKGMeln*fIl{Z__HKJ-eaO(yc^@5Ssm)4rUd=6Qt_09F_bzGnP3sHhs#sB~S diff --git a/firefox-ios/Client/Assets/TopSites/slickdeals-net.png b/firefox-ios/Client/Assets/TopSites/slickdeals-net.png deleted file mode 100755 index 2683ca9adcc237821d5ef591476fe9af5a7d7a44..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3322 zcmeH}`#;l*AIIhTX~-(K&E;&RC6|aHtTo$Q!sME}HaR<+loghgxy{hbEs1uDG51SC zicS}kYq>VJkerfR$u*avukYXS{k|WM*ZckR`}KT1-j8>Zql2|92nrGr5s^J(gLmGY z(f<`7w%b=frf-Ufh|W9OyITJKfBoNq{|yH|Ue0pcP5(xyvxAGs9#JuI2}vnnFGyNO zcAp%0|AB+@3W`d~5U7f(`X4a(p~D(S5JxqSX=&@|9@o=9VPJ?fGB!DBYG#f)g+7h3 zz~b??3{btzwbZD&Ew@4@C%EIOG?Yi zD=MoVRzIq#t$SSm_ssx@A+Br7 z6L{WurN14+&ulD-u5c~6^5oOcwo>nVPO?6>wZ!%MoijwbNlWFO(#Q>Hr=QMBO5|d_ z>8OmDb}#E^T7P_vYoGnsU%9?#mILIpE>dzQh7P7z=a5!1CqjTG{Dg zQ`Ph2lALNPI6gyQE7xqKY^=+p$)??_T|B7N{P9-8sqS3Llx;Me^!gVetd6S9*VVSN zf@cSTrYMS$E#`HFVC+$o>ohV_=*M5w5UtGDHNmwPUB(@9^$*naVPniGcISZ=O1OfS zsl3BcIL4hrS7p^bK*!}d+LKg7$1&cWu#0jBb+3IQIEo2dH*rEA>Jd=o!?P)4fSRE1P{UN*11T@csO&8$Ae12}p+IXBXI$EFS~7aYWp1uJ;gSmFWICYThMvp9 zdh}rK+!bB#)t9r)dD7i*L@lt}3wjGCQ$W(MxSTgq`cFuz%M(3y(BU0|o;x~o>)lZ) zf%6=L{;G_5?k6=H6fY_liNHm<8dOnO7DFdml8;lRa`Iz1@%p_%bBCFin)MllDEmVthn5!1=_p6qO{%p!{4 zheU~yR3llt_ywiiV3t9zb{dG%9$U>qo2Hrl#!wab9GTSve1h;>Oxn#1^t(J-2MOeE zu~FEH>A}(lo!v#?cNy`H4f$D$H`Ksc?*bH=JIDZxhxJQaP2VfYOD>R`X3%lnwrpk+XK{NbO`S~h>`kx=myIbBy_pZkMOF#CjE(KJ0VRR>FO&x(xu0j3d>E6$7d zL-nzYTufqlf#-REJF|vnN>lSWII!6GswXfRac=-aQ!R8?XI@8^cj3X> zvxbs_1NSb)_NMx+9Rt58YT>c-=rIYb1+W(Nhd2`zaR=MZr{$RlJ4?&~UU>rf6HKRI z2oIcfG)vo4ct%(mub-kg4!?P3882F)dZU!KVNeoUuy71G+xt}tNaAR)VKVvslRJ*4 zHV?hw6~!a-VAi|&2*9p{o_AEfzIWaha6@wUkQ6)Sls!zN{K4m2un}Cp=_ai~Lah#P zMB}bSJJ~S=u5deu_Nq*(Yc3zI3NsZIOhAO`;lTHdir6&E+AeVSk%o!A<-<@(6R4m~ z<7Kq|E(V;k^)du74QhH0{*f^TkmS2+;3$HDH1>on)Qv3A8o<>k3uyO*ZMcoZF){d( zxNPnB;Ji%Pa@C0El5jTSJ1(*8ur$m*pY)fEKV$$vkU9G%hctd#Xcjs= zgJJ}?IY=%@dm0^~8V3=an>lwj`eK+}T^`f0>DeY#zY62@F}7*=6(Z%F!^op&aPbb(9)BBAT#F zbT2!XD=J~_iN+#3x)9n#cVjzVCN!ZpIqZ?A!q?7ed|gK_6haXR(lXtjYMdDLfXpVk zxb1&WY~SbQdh}J+WmQhK?*_|?r0A7)YLDX3xi%Q8`>V5@LfJET$x_wc>Tn7~aHV^r zP)hmrY4BU5iC#jBc{9m9HFn^cQ9ThM{6YVf^j$R*XRFkJSx+AY3m;kL`tH5WW+Ugci0N$oBlbF`Em=3SM?+qo8Abi5JLcPmD0P`I z@2cMbT^ii1=Wt}a(T8}W_r1qt*mU$E{?G9#_4n>6z})qTY3QX!>GT2fD3xy%d+XP0 z*Q+z&qtW#ArS^R+gxt3yAx-M_RcMKCGd0EK!?&LFbxZ1g=*hCjKMV0$8;gRxT?!8s zpEi24&!rSlI}-T$7S#4|UyOg1cUUrcRBguN$_2mEP2|VheM<*gAEM9X#^Gpmjq%k% lr$F=R;z=Fb6wCP?xf=as@2v1Q)ZMR6{SS~W z?WIOzk18>uQiAKA_dVzRAKr7HbDrmWo^!rGeb4ut57N|Fhn0z+2><}F>ghtwFZ9Vj z%W&!9k{8gw005dLQ$tIwi}(EB`8R?8-vrQGedLRl9|oBlTL1vR(OjavOh?ba$i&Rb z#(sqZ$a$5En}?T=UqDbuSVRmYE+KhMO8R#hSvm0aKW@n1RJf(6r2MCf>TR_<5cRtn z_cWne+B&*=`UZwZ#wMm_<`$OstsYq0*xK1UJalw&fx%tf+&#U#eSG~8{sDnOkAp)( z!@?sXqoQMC5axW_|~A-AKYiOVh}+?4BvGz*;e3LAHk;!s{uGycTW7naaorL}{Oz(#mtZ z1?o|s=y5>+T)+%%Z`9|E`q_bY(!pH*Hl($o$a~m!dE^I~ji`n%wtZt&{l)9ue`V%8 zA~k`O)}S7_xU&jsYi~OoX~K7|O@oM+_hv=Hw;Ud>PUJ#PumWjV0>TAPIgvd}PsLL_ zi1N4ijU|X#HBEvm`vZ_$!FJt9>bEszZd)+@N8zyV^S;#t1kIZ_(j76{CCxYE)+Yv9VC2(4@Hf!i{e94t0$LoJ403 zBm$muo%^r}HBC`VdTDi9!0eJ(CDaHhIJ%jao}KJ2PcL^(89=^3U_39bJiwmCLo zITWu+tCNhCXw;&0324#R#HOSzQ*g>E)`;@jcqL?E9IE23^Xp~Gw`Hep=bi0SK^z9%OXM_;8iXiWxN#(Pl$mLOyc)!nR31bd&t^VQzt2t2#FiyHsMmK@rrWYs zW72X_F|;c-t{2|g2M@4alMcEfJGdgladRLLf9Z1K=Euzmf`pl;7s$dh`ATJy;3okg z>43a@xk|`5`$YRVYhxFg1O7tqZTzoq%)<{O&o=+?Yn2Shv)4$m6rCu+J~MWc3J0Cbo$9AeA>lTN z;X3La;cz02I=QKG=&=XdF=gp-+!;ZsGh-)hS^;~OU0+$p}^?A8V`Q@8|aF-P%XY)GASUj(F z9U^DFh;g-&%QExG8bnHZRQ1UiS!hTqR+G-5Sx(>6ZsS(uD#3`4AR$#Ia}Ea|_~i+f z7He#3PJYK}6s?8(q^t4m;Zj%bLW1E&@{lXkHi>45K_l6B2_Efje7rl!~CKNjW~JNNHasmpS;Doh49IN9*bvmi0h_$%UL_xa^Zp;+f& zl5gTv*i*!ZFoU_pTPbVe!vR6!E4Gd0c`4|88FRQ#wo@?iAPv!dWSczi8LL%kqhx|! zlU^G~k8_Rda`2orrE!MZHBZiu;k=%?4$H+$)&z|s37Hc~svC3?tl7St+n@F3Id}Hy z)@|N(*&IMCd2pCAU9^{&cga@`%&S|fx}fYnM*AeIj&FQcV06**fqk_x3F&~VE&Ar7 z7DF>KEp{`;B?9xSI~#&uduVcaaEiOvPwH2t(n`2f9GVg9V5o06^21RbdgHJM z-j(zCy^q4%(Jm!TI&BsdA3qG9>(G{mkskHhUa#ZGw~gSA+9LbNkHcy{Wpr}D#1n%3 zlu(Aev;7kNgQ$n09<1o9x=*lP)jM|NNA+a`g9hTTgbx@@;D_r9KS9A3sL{1y(!43s z@XjxZ@LpN+qX}hr$-v!Wu_#!=h3OjRXLGbGYC=w1B$Av^H3&ATaS4pcDtdhUo^QHh zpn_mP;1*avnX17psubPtL?l)o1#@?3^QiyY7#s#QMXt(HC|MCyqm$~$ozdc@gP7Al zO`<5@6>6!+mqb>TMb21a>TjN*V$NRBLweexw;hF#4Df`~B*Edsp_v%!q=oYT81o<0 b5ceG8%MLVVVS9}i;0New8AEIDImP`A!{qnj diff --git a/firefox-ios/Client/Assets/TopSites/southwest-com.png b/firefox-ios/Client/Assets/TopSites/southwest-com.png deleted file mode 100755 index ef14ad76828f82bbb5bcd88fd3903947f3ccc32d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5283 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 TE}?z?7y$INj5QlDcb@(OL>{%R diff --git a/firefox-ios/Client/Assets/TopSites/stackexchange-com.png b/firefox-ios/Client/Assets/TopSites/stackexchange-com.png deleted file mode 100755 index b5c50b5069f108ceadb5b336488fb538e4e16b5d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6432 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 U(^#3T&Hw-a07*qoM6N<$g6?SMIRF3v diff --git a/firefox-ios/Client/Assets/TopSites/strava-com.png b/firefox-ios/Client/Assets/TopSites/strava-com.png deleted file mode 100755 index 76bf33833931188225aa97d8c9d9af1c7b26a47e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2176 zcmeHH`BT$(8vcB95KIh*(0~FGu!s?DxdSCYK$5`fLPP|LnhjXP0&-YDh@kxvIY;pT z7l;ZT$QZ!QrqTk%KsXwe6eU9BR2l?f3CJN(6OORhzhQsuJM+HJywCg0yfe?d^A<1z z8F=gtEC2u>;O`f_iSXytMQ+w5<#i1Jh;Zhi5ZY$D@mKui!2jEUuf%6(HgD@$N^sy2 z03ZYsh1S97Zo%TV;`Q_m47V8>e?c%YGq9(9_w9{2?V5&_$Q_)Ck-3cI$>t|-EV-o_UYU8PM!0$Rtt}kj8E|{!?@+i|V**$vyk9dKGY$AXEt&X_E z+?F>0lS*mS{ynwu{(b+ha)o+xPf;5Z4drcYmtka=-?B!Oh!+_l8l?obtFYU%#ey0Y z2H;~Kzy#*?! zcYZL7Coua;F|Ak2&_7Mqc1udjP$6F~BGiYAVHeHx;zDpTtb)*RFv<{`KB}^#8Q|@w zc-vr0GI~G|dMD_z1G0=F&{euR!7pl-HRGm6aPuRNLu;Z3HZGm{K@h6%JQU+h=VAj868hX?UiObhdHenLDEFAj{ zDP1j%tJA+7#zy6U3MnMMKI}4xCpX`Pm|UHm=M#Kq3zC&WiQPLS>nSAO>w4t^JRB<3 zIpl`Z_i|!UKJFC%$MGv=YUsLFyE7rvVYl+;rTGExwmGhOoA=llG|~=Hvh<`MI!dD; zp(J}wt6bI68yhxi+~72vikFEaOSU1C#+W{DTc0R)F;U{HNZm~P`JcZ>#lll+);L?) zd(UH3n^hx#_0IsSZkZ(e&U}Pl>%QX~53j{!>8Q6y*H%LFcCy0Axw8xFzYY1rx!*bR z4^=fTthq~2bwGWlah z{%M>wzIb3l zJ(z=Nr*!Tf{iyuzEqwSyWQTE&po89nzgF?(gdg$BH^<8!SQ1@ikF6VNYsD=UOUMWG zZ~G_(ZYq0bJYsV|p9oO>`j7Uw=O}9Ijl!mpWP<_DUrdA~C1dyuH zqPv`l>!PaOWOSn^y6m73EJ03-Y2$iHW=@M1dXS=Rjr0rZjf~Pkg6k7)8{nZ^IK&!e X>4RR-WSx-1 zM!7YYgVR?vxs%danub+QFU=aTDm0$ufBs46X6cHH}9dqq^T>OoMq~w&Fw^Gw6 zRNBw!8JStPf1%&aW-xQ^<>nQzii%6_mzF(vSXouge*D{$n%cUj^}jbXa=6c)x3spk zcksHpd;aL_|MTU*>o@$tw?o4tqhsR}lhf}%%zXSy@M(7L^Zeq{^2+Mk`j?H(t*_g{ zzePK{-}b&A))U?b03=84y})EUZ0*UfE72HZSFZAe+$?9V1`7Z zesc27IjuVgSJbsbp*jf8qSDH@aL*$~S3<}vzsIdpE20X>eG8nP216c{mWtg>V%67UGLhZnVbLu20z~vKUVHMcuX@xzdMaL zY+qd}eBkLNKY^6f1NH{ZU6_`eO+AB&wWfpUvlg*uv>?{R9@u$0Xuw5lO%h^`(0ZpH z0-U?peYL(OTj}eGAHV_Qu0dyLNMR>~mp=VzOXH!{9XuLe=WjUCQ>cy5Mc_==De%Nm zriXM0koBM1l8$YgLo0qAg(e&*OP;_^+?ouIiy?J?f)LP*+fiQe`j1Dxzv@ov|5<~4 zu57%|lrwMwwF6w(7;8ef=!Yn31yW7DRxV2w^@y1=7?)?~?UAm{YS57fwtF19Kh? za!0J^L2;!7*vaN{O@1O`;A)|y45hJi-`LQ~v5UoXUnm>Mkss@1@|@o5g}4MOmw-x6 zhQP?PGzki=c#7qc-AS=AN|0^*jjKWu=Y|#%4Ik*a8Hh4{VQK(f%3C`F$)k(;9bV0w z3L{oU32Tf#Y%-C|1}SXFA_sr!W|UWyhN`LvXm_LS4CT{LQ>iwWE#=99RGra> z`bm@Cv*_3_LX4>lL_B>2<2I&hke8{%9hXi2_7zjF3ZW97@AIRss}1ioF-oFrPo$cx zbQNf^G$s&}s?VX=9qu()2~MSQx)H61ZpyvEjk)x0iu&+(&J>+MwVbslIeN*?i;hKZ z&+-`2`jOQ3r)uV;o?3WMHNl{bC(a+ zM0Hs;O4AXV*IaoYyExOe6u0FBt^mrlH}NO5V?JW7B9>_&F}H6LW~VZx&xyy4-joE0 zZCJPq>Sd#@R`-5~*rbiI8^Luo<*&zJKr(eWNw#jFax?~X$vpxYz(Uum<|~v{j^2D` zd?#6gsPlEMGcSd0;hK*O8k%}C6=tGdM=y7Y*(**_j{fClpJf?boXbg4tfN=GGUn|| z2{BYwhZGbs*_ceGK9$%O&?DX-?N)FcGU0fXL9w#hD zZrZ0+IFck^XKF58AaMi1ptO$KVLyOxQLLQt zm3ORM?4i0@f0EmnukD(7HiNeg(7CJ91F{ljK8+NFr`BAd&KVO1b_&6Zw^s2Oyx?!O zd7b&3ls$W{>-iuui)hBL>i{ZmzB$aF3vzLN>VY(?YS(ho}e zX*sySY!;FGqeXusHs2mqZkiFw8TLU~;Nfq4fVz~NRJg0Zr0C<{Imw+@O(an{~CHQpB@eqZygO8iLnL`5Knc?7shzP9XZQE9;=- V@rtm4H$3Km>(^MMTBKC5}l-Ngs#G z$)8j>rKogT1*WQYMqLB0sim!RR##8o;GCh6u?fP|%>2Sd3rnj@);5=I?d-2OI667I zxL&<>{f3+S&08L~J-zPSMS9=!@%6j!9}pN692)lMab#3<3_1>zkerg5mi{aw^LbWw z&Wqf<{DQ)wm&GO6(y~|OI6R@Evg&R1yBgyA+WLmZrVq_6A3wE{+CH~;bar+3^nUqD z?jIN&`ZoN1gfcodKJjC6YIe{dM-y56Mt?eD!?%w_Z{huSoAErqX zk30atS!-o(>JvpZ-IBa>sT1`9zgG-lPA|}>fBfg;Tjx@qG7im z`^<_PUIpS&FvT4F65dqEvNgRl82O$F#6y}j+&0gQ-e{|na3p8-Gn;w%OcE(yjkD5$ z>du~f4m)-JKzMx~t_X_HLTF1v7kE2Dg*=u+q-(f8x+D^9!8X8J)@Q?|oxl@p2?j+d zV|Fllq7feOL3`>cQ0mao3#*bb6<;s94A)rg=sE1Jy(xs!Bp7>UQy_k!4Sh9^rets9D2K0p^#7pPS3tL#es=!sAS&|n=?D&6P7 zen!IBt)*|!JN7@50evh-$tWPW(NNIRah7 z4q2r!qCrGb-dUD?(KSyQg-X+FM$ZZsoXa&6%9~|N2!F^N(rVi{5BgYBm49`tfehmA zqmK0UP+|1%)}KAzYG$fpM`MV5d=PfA=|O)2sOmr>3pB?(H$%EAaJI>8;9$ZEk{{`k z!h;TlIkmVs%|kO{f^RB2r~S}P(nNQP8_YI>?!Q4*q(ZOt*ZB8}OoPmRt)l3RR~53S zwWRZ0&X93H&q^MXl9$l_rWX;}aze`XKGEDo#Uo#PnoflxWT(L+`s?AJkXw+&)Dom| z_uV*0L{+&iH3X9n?Wlj@z9c%19cCyZqo>@f#X@`ZTH2aiB524$TU6@P-@vwjIUjFY zyVcyPq?Er~d$W(Z1<=nF3J|1b3L91rl3jj=DCr&cf7t(`QlNKUR0^N5qpsyHat>~V za=x>Y3({YY&s;9l>@aJmOjp0aSUqUCP(vey^iwL!sl?kl^S(`Q);P*9hTLVC=aDW5 z!?;|zN|SFt+wmkU$_;B@RpUhe`C)^Oy+!r-Nf_>fON|-TT9Bj^+8kAg*NI6E&?d@v7z5>EO&dnJQ@t%Sn9W(T&4q&c%0GpJH}-;G4yF z5f;hc99V>h^2EKjQH@VJdAC+ru*WRIh~R?R=h)!NtTaSAQMzGi@m8k{qejK^Q~S)C zUPYS0w1n@(TaTrKT@HnNoMG)RSNWMEQo&ufHsr2Za_T4^y(}apNm z6)`APjG5RzIgft|eQPY#qrE&>Usw5k=S*H-fwnF@4UiCwDVO> zE^i0ukVDKTp80^I@A9oz$>^H^f3q<9UsbR9Lnw$azAEv@)vCgMlu%sOPCN{O;bn5s zH($~GyiYsi?D3%*ZPr?_pSy0dd!0yQOaHe7$Otl6aJr z9WKxsJb14%g-tV^wOVnqa%c5jSrK5^mV>jT#;?J=A8Y5?8K1O89AuNetub5B`#zx8 z69Ge>Fb-PTeIOmRa_LD-Vxry5xq(gaqZ^7oD~+e#Q;XF{?<3}wwu+$PB4@EDAexvD zKSx2WBBI&wW0&<0CORi#zDf$K1;~MmRIhu|?Y`YX!yPE(DaJ9il_X7le(mi_rAp0~ za6XS{$JEiR!ylX5Y@W=< z)kd%;Y+VLxJul;o+pR5HGP_<&mt006vu)wH-vf%fm2{zf*h3xTldiY@Hfy6 z{2L{}CV=@BSe^)2DnIq0c&7|-$$#IV#17B}XEgTbNMuF>l@H6LNLS4xc(A3jj@w3W z5@e$|GVH{cT#2^@0zw!-E{@~zhmpW<9$Z+twXr06ALyi%47$}OQ$8&6hv&#h_F44J zCtnJyA)RJMxnqd}-^Mds*p4bE4vQFZaSR-BFmkAu#X_;vAG+mgEHxk3{`*h>Ru^o| JtIa&({s$-a0gV6v diff --git a/firefox-ios/Client/Assets/TopSites/t-mobile-com.png b/firefox-ios/Client/Assets/TopSites/t-mobile-com.png deleted file mode 100755 index 221e66c3594bb062e6a874985ab7d895eecf2183..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1756 zcmeHH|3A}t9Djed*=FplZH}czBrjAq;ebG<;r&}l-%iYcYnp*^YQxfcs(A^$Mc8hN#wuFR* z3%70GA=(+SD|+Al1M%X6l7vHtlakZEKXzOyJDr}9nU$TBnuMR_o7d3J1A9B*HE61W`7$+^Zf_ z6X2$MuSG0nc)biWNp;00(@_3ES)R_(E)}W-8bR}=hF2yQepwE__As%*l##HQkhdUd zUh8%;jRi>@ZoGVPXsMZ=Xtm~fVxPKuVk;MBt=WqXn>h-NjngA}U89T4*Q1f$`3KlA z5B3u^$!&|Ajz(ZcF1()5KvGM<8aK6oe;~*qbd?hutlpV+<|&Y4K+(&ht-*-S2RH#_ zd-TCN=n-urc^RP+JpAZ5T3^(So7`XL3d#w#S6UjN3>QIqVh%6@BC@B(Eq^|E)`XA& z$+IA!Q->6Ps>KN)p?~1p2p5Eaeg&MYT>=$|cgBnGC0w9B>2=)=syOv7Hp+!%P%5pe z+r0_3>Z3*x?tm!9N=lgm$v$R4VT#DPuVTS11#%h>TdVNs9QU{L>8i&ghOa9KJPU^Z zAPgOAOf>7lYNsV{x%9ZGb=$BeaEIjTL8g{h_1R$rzz3Xfn;C=}#z0wihrv!=`!G}M zDItqSAyiRA{j>?b#%^1s#W@#ZJvX7&Nmr88V6m=(LF#Y6a8d%b)&Im)IJG;cHyeQ% zwmq7|-(ekx9k?Y=xtxE0e==glMQVa?^b#JbaQ%C1E?NS12&DJLIAi9B%a#^f?yHPVOx=!}qUP zGhRf(h;rxO4K~EYpPxaU!-(44U0W2D?l?tHN!HjtQY_r^V4D$I+_B{mO{LZE2|tw@ z5K~%tGu=^mzg{`kkP~wGLt|+~Vb*TQ=XlS{pA!!c7pdd%h~o@$vC{F`q(vy^+~%Ao n15{PBgQ9V<@OlWm*%-A{m&B#G4~WmqCKT}Y@Y_(v5vKkH{u39} diff --git a/firefox-ios/Client/Assets/TopSites/taboola-com.png b/firefox-ios/Client/Assets/TopSites/taboola-com.png deleted file mode 100755 index f485c184c422ed49044ceb86db86b5395d8bf528..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2824 zcmeH|_ct2~8^@EF35pWCF?+46Mr!Yo8YPX?xKd9_+B&*=`UZwZ#-@lX<`$M# zSFLT3*HE_T>vr}Ij!u8waCUKZbNBG{^7iq)l>dow?6;p z%l23L&hFm+x9@%&NT`Q@>EaIc0)Cp@4#%f+{0uI}~_Itv$;{HHc)F#m)jnhmm=*JT^~( z6wdUCiSDi5m=%>{)7_J8{gv>((vxLsOui=nMUy0UUMaJ`cO`*S9*hKv`SxP0E49Uclgx8xi-CfkW?QKRps2DC3q?c1P^s|>>6HI7BaC~+o zXSt`e6bVPj%(^({;=(e8)rubp*J9G~={F3Ll-y(aOdpsO2-F{ldIr$t!hwBOc(DTA zFP&ge?O1#@$h#_?M{G7skfYq8Lxh9$Lde5O;Soa}TmjP%Xf|?>tzNG2szZf@76GEF zP_ouHE8V}C7HomgLNpY(W=DfvXknsCW}Kz#HPsZ& zNRgDW>Hg@Gm#_$6XC%hZ=Qj$Cls4Kx!G|T$Mf}7yL^ky)}Qh|Je4ZcJzW=zz}a9|I&6s2T!^uPAxr|?+ zAv>n#)wEElVLqPt^Q72#kOMCm2a6XZkE(fS#>1{j0HMsv9$Fr* zsXxn(v#MoUP@->OGhonq7(5LVjQ+xX_lP{3B5i!(KBe*E@i}iTXGJ53>qv&Q4MDB^ z%2ad?V`pedFhJ;2HE>!|IvCX==PvZdOTugBj-WlXI%n_&&X06Bg zLj5kcROuOxOwaXn>8_1)`TKBci^Ms>1IK0&X<}59E`*UGN0*p@M|~M0=ittoTR9hq z8o;cpO_YCJe;61zb5Cm4lIXZ{rHpE}j`YVH$(EkaZS-Zl$Y}v=c^V@zJ}N||)CDoW zg~lD}4Rx(&yB=ClFfWhia+CNE?v_lqV&~eOY`iuqVH_yjVaRJqGQfzty?z;8&`9F+OlCI z=`DnYXH5otK`GjOarcgR2c_)=cZu7h@SYm;kPciUqhV&ND?D@ew8~dhRX*s}+q~?U z%)HE<<(^Q?csW3JVp8yH$~a$Kmw)Z>+#E}amjRY?`85J8_o}t0p;Di=`u;`K?Q4a( zt(Nifc@{v<@0TMg2N(8So>HcBaR8;JxE;?opD%HQ{}5J50R%Udz#AUgmv<{^`7@Hk zAydS;`EZxTn5|DW8Rr5GfL*aP7mK(qV!|Rzu-)TxLn_RlQ4ul|E7Rmvq?gp>^Aizu zEaSaXtU#eUP@7FKl;k5~iy=Kf{bNeGhl9VxykT|0b|gEqNu=HDbcc}TV($@l0v zYv_32HrR}*Q_yV*rpZx#K?rm}2ODK2bk$RP?@s*=)cYd7ciZclU0>?2FkZ?370yka aGp1W&srgTRGUa~vJ-`xyG;1<(PxvpZ2(aG( diff --git a/firefox-ios/Client/Assets/TopSites/talkingpointsmemo-com.png b/firefox-ios/Client/Assets/TopSites/talkingpointsmemo-com.png deleted file mode 100755 index 781ab88f8c0be1bef1c296a6d6c608e219d0144c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3814 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 LrVlN7Y90JPQtp7- diff --git a/firefox-ios/Client/Assets/TopSites/taobao-com.png b/firefox-ios/Client/Assets/TopSites/taobao-com.png deleted file mode 100755 index 2fb36ef86f38a0725f66a5432613ce381f141d93..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3268 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 A$p8QV diff --git a/firefox-ios/Client/Assets/TopSites/thedailybeast-com.png b/firefox-ios/Client/Assets/TopSites/thedailybeast-com.png deleted file mode 100755 index eac04ef59855a4726d0b0421287e4590b685578b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6786 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 Yf83)ExhX4Qo diff --git a/firefox-ios/Client/Assets/TopSites/thesaurus-com.png b/firefox-ios/Client/Assets/TopSites/thesaurus-com.png deleted file mode 100755 index e204efc44c6bf19aa83f17d6bd16c28e9db10fff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5746 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 diff --git a/firefox-ios/Client/Assets/TopSites/ticketmaster-com.png b/firefox-ios/Client/Assets/TopSites/ticketmaster-com.png deleted file mode 100755 index 8924d6e2f8ef708e677ca4bc9350e69e2dc4b1c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7024 zcmV-$8;|6PP)&ePMk0pGmI-9lbcw`5Vs8Ncf}a z`#0J5^S_&3NS|N1%D1E&v0yXV?E2+D5DX?<3~{rXaEmOylbsH-=zq*G^bKanf_5 z%x3SzO2W!$D@Wvv&CQO>OnSH_^T*2xOOEC=FPt3|$l}Qsr*7eOupL}>R|a1&UfLI6 zgXixb=m7Bs$kYfc5zaf9O?i0P8xe%96MjNI-_lPQygL=q423vZ*g#>*O4z|E%W3A^ zrNV8V|D?nF5lAE(uBDR&QBIv8ZI|E8SSAaiE!4@vXPmq|q4>)mDRG^GkHN1ySvQC# z7B^AQe&-t4Qhgh)bZAorBFLrgN0K@6{kZ&UA(0g$&5==&myMFt60H=`X3b4EQjen1 zA#OM$t!`+l=7ePKcY(kWB`GlE^JW8HB<1LUi-*>mY*B=2#=*-X8`^qB@rcsWV#N^d zt-J_AlAY@r?q!4VWR5OW!sVWR7lpF40_L0ADlPBaVivOY9OkWrtX zWhXesL=JMd2q|qMd1dhhq`6?IP-nu1YTrRGRrK)D5s@}K72-&_S!~bPz;X}GH6y_x z-0iZ+v2wu8mK=LQZAvdx0cAWie~Euy@q|So4)LD|?S!0U;yl9{2UrF9q6lCRVS}5q(-wQ-vOl@z5PrCxxuE(Y$D6-9djy#9Z+qAb{A?R}{d{U?+uGM<6lQ6~fG z#Dn8f7kT)i3nn6fP}qi^aEw(epvP$0B#hnwP&%||MO(8boOi7A}lLqB- z1t4xXO%6J!J>V(Bdovd41Ma>WYzVgtHyP2SSn6aLiotQaJe)u%D~(so15sDQlZ20g zmEwp3Vnc-k54p&I4_1C01`gv2#61?h&h$L6fP?W2NJ?8NWJ@CBM~%rCe5yp7MD(ZP zT^tnxGG6fyY{V7`5qL!)5@5u51?m$0N#wG|K)Wacj3V#yf=T$DXa@`S6$#wBsMR%r z?;_uuAr8G$d?Eqsj{sI>xuHcs6#x;r)7o}66s$$iFN?f7S*T>72oy3!8iw4qAuhWJ zU^&5MMLRcMH(2mnB=lxA(8)%G-I3-H)tQ!FqMj9i2`;$=Tp)xXOgUC)r0Dk%VA4 z#w-4mXeDzJ2BAlY>=h0dhH5!B_&_Xubkcdm%0|S|coxW45ai;Z6DPnM6geOV#d?JlWAHx_OC!B?aHt*2 zA2o(!0N!8#WDoI3CtDo^#p85GgkK@!%~D1Ql#nh8<_oMKr<_O57$EWlIpW-p74110 zk$3RS5oS3G`zQvIivx}@aGhsI8xPb7Wpbk}kHnYgmqPluiwdA~I0Rz12*`4}R6(wf zh)WU{LHe>X1qv||tb~h+9Dii;BOAs5#em2x>W#?;I|8WF69+37Zo@-wzW6!$Q~i6MZq%(Qee=0oD)2wg|kqoS{@20UP% z#O2mMytnN~4MV4gCN9j*T}nM>=jYeH+71>Q<&lxNAWr6qbm&+>O*8gF4Jb63 z-Rpf9$O8P{zBVW;k)MUqk|OCLMgz#i;s9u_jg$e2A~W1wXI8NBIxH%sL|tt(+c}gzA>TK@K+oyGkUY61W~ezol{NBGkdBhbA*F z7=ctR$89`LZgExBrDu&3LIOI&Zt+_+i%*$&>tIGWN*@aM5RAIXPs z{_n=2on50l&WyfT82sAdGauR3SUPjqP+7dGWB?!B)Nt3%mM4y!dA@F7bH~Wu?orcv z?r)Fx{>rYFn>RK@_!esk1(rRy)f*wQ&t+?WePs&NnRY2DgA+A}^gGnYSk z$-fgf@a>_AZ@k&Pn&xdkcA#TN&sf)mndysy|1v!{-!eM=%<29ci)*jtjB>h^@c@bt ziCtI}+`qH=();&Frs>yrG^Z6^b=!IL;l15s3kz_^)~5CC=V#~V)$1o8+0i+2` z%Drrz|MZ^LV|^FqBL+EN6rmIMzS6wHI+`>ndBS3*V!(aO`PM8Q<7;npzmE&hJ2CU& z%?*`bsdmYJhlZ>hNIv$t10Bh(pI^?e)D2JGQj{d+{dBqUKlFp+S)@dL^iR%yVpmH< zXp=D5D$F=3G1_33QtAW$T0i(cF2IT5$Fk!hGmGK##vKrTgjs5rV zc>M60^q~LpXgAr#W{=IoQe8D*U~5}sVMsbTtO zyMYWqJ$I>UN&c9k0yx+^whX~CU$jytFU}PWn213Y&QFH3KVKY1a*^V7F2>2FH~Pj` z)Zhe74An>xF+*Y70P(nETjR5J{mJtOr~7}f@b`58e-_xGPEO1-r}|2tEdE{i?!raB zd!n~&R+fGuG5N>h6k{?^#|I{!JlgZ=eQo#eYJG5T+qaJObc{_eTc(fCJawx7k%Ju% z>~8(!uGYs6ok>h4bs47S=GSa)#6d$1!pauwKvus~5U$kG`{oiu)?m)^*7*32 zme~jqKQ=S>kEi-q*W`Wa+cwmn8lH@t`ec^3b&lM!6r*08sVj_szA&f`;-THGQZXr< zlbl-#fkdw&BnDDn6aR>e^*itMO4Uq+L;C1z9qRlig5t45oycXmYkSj7#1bYS`JwAC zG6W>o=_>0F_9&9@v#)jPh#O%A#1=vjvc~cYb5(7jnV$X6AL@if<+76Tn{W5dYZLb` zet=a=?4fUk3*cT6<;ppR;4^7Rkd=E`syncN> z;QUkuW}B5`w03W+ifFDq*g=4%2p8IJ1 zb9GFPz1BNc8H`?JLdq#q2v~@m8|>WVBobxSHadMdPs3Zh_$uoU_f3#{ezj*TFUlla z`_3(mWao~~%w12a=`4+~y6zCgyZ-*8iN?-i)p-wW;-Q8m= zA-_5!E^pb`&`BYtf2teMiu@D@{N$TVAsy`>zsz_A^tFCfjUSnY$0*SaiQyL!NXH4u z`FcU3e`~eU|D}Ka7u9&r76u{vC_4rBZf`z6%|M7RyxvK(dCTwrPYWB*3r)i-7)iAJ z&I7wzII?oXI+`A1Xz)3YhO*=kP(XEYtgCAa$A=~q_*bsFlDD!R+TTvBjzq|<+1vng zQ5LU!Wo_Y&0XCjLJJv(ft;!ShHz#`;z3lARl}m6muW}{#aB$fiF*WB#jM0}acl(yc z-iaA9Yxg8am1M%EM)|#yXURRkJ2a8VWl%-GvJ4;E)X+(N^80qQ;2J!YalX{Skd@~e zhghvzRJu0De3hx#YRRvxz4fu3EhMVfGd^<#PugC(evR8l@q?$|>5C{u=TbS&fIvvb%ob2e@(&Mn63=OS$N9YB2=WwH z8h;iuDiYCj|L#_WZdMxbqtqhU(mo=)gxN{BZDW1cI5P)+XM)HywN2bQX$>f-?Oc07B6J7b8k!oXHeR@|7#v1F5#04io z=O@W{?%CM_)7esE`_9oGGMJZ(5p2wii>cO_DqZa9?C88#q5u-3{?<+PTF0^SoxIq@ zY{%NJ(UrXYN$H;-+Eh=1y=Nz8)@*8EmB$wy`@LPG#H@JyNSEH92o?%=0V{&AfI<#% z_MY$B+Q@l072u4PQCnT>U&kjYdHlnvKAOu`o`ui8%All^!xI&1u!Urt)$0oVlTZOn zT%7ymP57@9%5JWuYop ze!8xoT*P*qUm<6cXXfQsx3LVL}*y_ zke4p|Z0s@8ldhOW(*BKy>9VCye(5kf0g3Vc-4kakb7v})=Bf;v z!99Dbk6h=)`aw|mGb4X*+SqUo!)N`IvsW(UrdbA=U1kgWXe|D#hr5)bBCvp)*vgQk zu8~mX;>XtRX;ow2&$)p+wl=KURR7`44IkOo_?dm}KWP|zGVvr+@spF-?M!y=BL_NS zYQR3Yr18kw29dux-NDw{o>&%Vo!(cisu7FUv}T<7ME z^~A7F)&^H2@k;J-DD7b}IExEy=7d^J-M;Q+&#rV&?#;oerv6-vGD3}-z zuv+P;Oro{{RSHq@OLPy_b>BPDJ2Z818YKQCGJ5Lb{PBT_>z9CK<5$=E#6U{EB|eYz zU8s7w4(zy$3f<8;iY}5oKb11NNJ91#Z}*am)V7}oJq)}qg+zoO*1e6Yr7Myci>S`p z{cT@A+Vh+r*wA(^acW-e9oyJ`F4=>R9Xa!XUC3|86Lhp7o1= z>wj(mI}6)G2Y$&7rOy|yQ@+%~i^9S?w4+C5Qj!h6c!ff0RORP2>k6#ouEiaB5$h14 zQA#yt)K(?5e-l%ux~?3%h=`>K3W-#0GZCf68Ee7ChQwL_E)QF|Amls~6GpXB)OMvx zzfs3gd)OkzpuF(7GMpx&^jlOxWe@Qj)JT$-G&X>?PAyhYvBqfiOJV&j2X0=X0E>MU zNGW$z6O)ztCD~iFMwwhcv}&4$XHhk&nWVSchHi$E}|CNq-d|ng(O9KI%@A_Xlr%UJDwK< zv9v`nFQ;eYDr^~0=oPhSjBJo7wbjUSlLsIffc3@ty&CDv=`*F~<-O8}~H0mOJ6g$5gxxdqi+X6vuFo zv7{!M@?fvpvmIGkta%@6s_7WO66p%WMtB^Cj~r~<7SlRUsSzBhc;g&QIZ7jD$cU{) zO++bbT{mEBn)DRW+wM8NVYbn*WfimIy;k`_F}ML|oQ;f{e>hym*)c{K>ope9iB7ll zeUw{Annj?FV4QEl@iftWgMB!NMzY+r06WxZs1{EUS6aJ8Sjm=Fzd-SD6vL2j9HUPt z6hTjx106DPQE;R1?j!1+?>3^InAyWft{TkZ;lgFD#g@t@$bK0BM(6%l_7uvWjg5x1BsvCt$N8la(NYvg^xR_VN zkYfO92YDyQ!U$$%y^;aIIT^-RK`tUn(6A8}p^a<_?J!~-(OyrrbYW*T&6%>e8@W;Y zg{q!fcD-pNQ$<`IZaYZzwuun^vL1^G{Ax|82xW%UKtruM3~uHq3R034($H=bdtDyTqYi^5%{U1m+3)6cp2 z7So&z=nG2l!4SArTER&-9&}p8d{ERV(Z)0z*Q#0rrl#yk5{ekPkEm}WZMxyzwj#xrP^qm3#7P{)HVyOFE@ z4iA!W${T6;&7)wJ_F4x}1V{#sZJ{j^b#U1&gL`jVjfQT;F1BC;8I96PtH{blvsvuV zD`g9Em(_L_vG@+GUrX(xLzxX3ZH5Kzk-6Xymacn*>z zImg25F>0B>>Gd@3dwo) zoFQ0=!2*AY(HQ08mq^D#{rI zt{hq5zo#9d3+ovF0M8du$CLBHQ`&z1H~*TAOt=JF_Hs%w4c%<2CD#pltvPzSwqRbEg` zt_D=NaEuWonad3Ii61ioz1D2=c-V9X-D)iNLJ4828Zy>1aMgF9>%76)dWoCNBvp41 zPHw0@*-99Q28hZZ;{lE5hW;oOhlOg$pMSl=@6#X>+8c-Rz^Zj${;cv@{Kl-1mt{|7 zMqc2{={OTTCJ%az?bmyROXn;OBh#4KXKz*!2C+<w7qjae@^?wEP=zI(p=2`P0mkx?Mk=A*&3huY#C$JcEXi&#|q{T}wieSG->SUu#xV;f#9?YY<^-cAW zSD|DuSwkzW8BXs?o1?XtzM+N^&Go+DNWZ5_wa#UHulG=5y%136TGFGULUhJTL4_aQ zp{Vt8MIMrnDQ|K>Snu4eaz*)EmC*v1#Jh4WO%x)-hOa`2mF!y`sdR+ke#t|n^f0r= z0PH))GsP&5hd%0_bP!2A$Kt0B}4jPt~ z4fbF7_x;6nFT(@5f-BrW&$X-#h^TCBC>=UnHEib9=%*m+-F2S1GZ4nW*wRVHPC0Me zgh3kr#`u7K`?ng1x0@5N8J*bOr&p|tEyXB%k&%}!!9r6(yu-hhGt|= zfP`k%E~y7Z$~{kphGl#TP)KN*O4gEFlfjS+i5JmVv!Yzb77r>{HjDETUk^T$N@9@| z&E~iGC=qb1K@HL<%I1ALvrucc*Bga%{%=ZlHl0P%Y4YQ%mm!yK`-}CgkLmR7LEQ?& z%wN~{Q0*SlyCdH)lDhse$v1^E(yyF;M&gk?fy`EDS16^>F`U>8CDRV~JlFiFcz=to zV0`7Gv+~XPJ`bT~LqCF9q))Q}Fuih7RL|ir3qc=ezIZAV`sQGL zIi8$VtHooT!wL%-NuS51PS>^!7iDKzy7Md~eQ02n)C&ZOb7{cA3|*LqTffUglfnzk z)!EKmnL2$kt8Dk`$5<~D(UV9QoU`qr5^b65*r!r~kca-lhzC^>hY3N;#`S-tngzYj ze{79)6>$3w59-|~1fk2eLw1nayu-po2ip*=g{q%z>joZ{Z9eul7mHRrRbKZu?_4%I z+m3wM9Zwv@BbTQbKM#IqxdQ7hW4c1ndVSGAL)xMwm-*T`i3AhO-L-ErS?KkDIo};9 zzoBZIy0Y;xKdxmA$`$ceA2OK5g-vfBYqs0p=;~0T)w7*1{h=!fYYDyfN%lBgZJAnd zRkoBf#FA*?g$7M2CQ(iA&sUdpVSNAoDEs+SM-sSHEOEtEOC++D?Ya6r4I5aYRe&I2 zsBt{#+-okyk2rgK0Y1s*RHa(!iHPVukC?AA^tTZKLnxQ~R4Drit8>F=%Qb17#C(1e zlxgJYT~R^StTl7Se)UCt(|eE(xx_Wc*rW-H(y5&i!^DJ%1n1Ol>G{of_vKDDx?FRQ z?8o5@xCGE~IG^9ezTu*P&0?JeTmWl~Q4;91*%+yW!`t+fyKT${umNJuk{A!QQ% znJ40CeoN*1XQIK32ycZnT)8@W(qp|{JXnx|y)gWShnC-bNjP>aU%ZL(4}?A6_Hlsv zZ(~|EyNc7iP6IsM?8c5F?#@QiKkxmS{G@zk+F+|R5I|*G`Fo5MMFQK|o2^J+aoOzd zVxi96P{VRa49}O12v-O(^m@1pa#?SG^*GAv;vRgKovm`@)!RcU^mqj?+6Aftl!$b? zd_=cS)UvqcranvS2h#}_;oy^%#uCn}j}8nBq%qXG(Dn}ep2(Zs-_Tc#DKz>fj#KV= zdwHZrE^LpaQG3r8<$6PP_D~=hkhOwG>`43c*m!n7yKl3jvbJFaqUbu{R&BlB{w|B( zLSpeApSA`m)T`1|l);*UoRX!N#&u{wGA=gSs~3WVil&X98Afuc`1O=uSX}@&-1$I8 z!RNchbE2(LzkXR4Ua;zp45u+=e=hdk88$*Q?@M1Tt%N282u-~12QT;48&<=ugiV}h zN;AXB07f_h=>hev-nP^8cIz0%yMu~gy=cMie^2P>lphI$d7xv+Wlq>WcI^u%YP^ zmD;;n^{4emhlWa|El$(&?Yhuo@arH>O&4RBXV3jYB5tp{ox=dMuMe3cQ25_TljD?! zm_g$cVQAv1r7y?`qmJdE{pAmAS=My{JpMO>>2;luNYBHK>&;$8;V$aG@%X~nUEq%c z$&*gIyz7C+@_yO5daKR-Af$>>q%(rpUK-`ueLalolf64tSp6o*EEcP@+?Z4#3eMv$fx+5T!!Yj$fOp=?FoA|^4luSot(Xi2!(El=2f5ZHLQzSa|AwV(IZ&6vCQ z_b8E<5} z`@j{4Bu}ZpR%Cj^lX8q;ba-*nx8pU46F6(%-d2;<*x91 zFb|UGo5@eFeNQszpAjokbcPgFwJ4Qz${T4pTuTO_I3qCF2RXawUq@Rc@@>SlFBA(T z-XW~Quj4|F%G7gO^YJt~CjQ-@jj$S}bA2ymsxb6gj9_@_x{xY)8w4VXF|RQevf;@d z-2$6^2ft?F9iJ!`%~%9o{@t3R*w{Q}Vkq*+K!;e4#{Z2I;U;QnFh7ed%SAJZeHMnC zbLvEL^`itPbQmIgBH}!1_2OKAY=qysj|&p!iGHpCn~qSbjR7wF)^3KfY?SZWPCT#D zNP5@*)!=K3o4I!2UIn^g#jfdn%FgS?TfppHKDhq{T}8zu5;m!yx_rbgn)o zuRxnKXpV_zCwe0UamgPtv7>5vZC5B0R{BA@bCUy(j(5AJ^4ybiNDbf{rDg~{8=^-} ztWM;Ku-wvz-Cl9KPg&R*mn*&EIHTt_ph$8vfvwRvDk4BNJC3C^M}}-49z&b{R5Xe0B-5J_ z$z}le8tu0Pkx!}bdNZkGqqcNwJNpR(uY?5vt0kRSj@tf}TQ+O0-bf<0YV%H%o0!E$ zYuN2~gJ9;ZX9B?xJ>;#aTZym2oDvvoL@6kc;WRL0ZtR~GQu)l}B{W81$!3f2y6mZ3k(HJNlj(H8;C+AhwOlEu2k zYq0ARv6yB1)h$CF_ZSg_Pwun&OB_Pb4Bh($()`HH8|g-8K!f17?962%vRgpiF}#=N zNWnuSF5+F1Ba1?>QHXGl1nkfu>FVb;@;v2)EdSki+l{2l2UBZt5KtNu83T375hV27 zRvY)aejLObH_p%5YM@@nYvRYk#zhb;cHKAwF$70xM1wgAi-f`G(Ie3x&CpZ-vK7C6 zfe$NNYe&2`7xVveDjXHa^LUwk@l<$=f2%4v-M zNzk)#cn6xNB$s#~t+^pw)4-)B{+P$@^^PE)l=R+?E%{+bN~_lzN33pAL9nszOiPBM z5QdypIUVGx?XNH)vIO&0ElYcGzE7E)Q^r9)<032|Ql3UxJ@o$-=vQdDGvgIw`)Os3 zBz&10DMpM`Vp{{&7Fc>4V5B_HsI4qI{Ap!!4iE9cE;xmGjzGpGkZ?@T{pBYEg`a-9 z3xsI7t{w|Arabw>chvSLZ0@VyvyY{Y6aEq9zkn>%n3VC6HbxuSSatvCu3pc z{8(cPjQ#BaH_Nsq6Lq7sa`%d)9Px1AuAL;jKKNoEj~A~g=_(w3ydIAxt{AOLW$f&5 z6Q_xstoBF|G9;4t>WZu?Cl99t1AVAZZ742!+3y~1PtvklEi^g%)#qN1_QzwM(3xP( zB*C$ux6pt}>+gv(1s=dA-RAb)+LjHUb$)>cyPQDORwjRh8CqB13$}rl$(l$`fb*5< z^pN0qBgAc^$x*w|zuRdVfegXl3b;bJPnee48Ah^5i!!~+R^K*!UAki2!y3e-z(_1R z^IoU~C8s?aUiK!l|6*JPsqa6TQWLvm`llM}Js(*TN!Gyf1cayWLuJ+7FIG1=Yyt6X zL%Y)JTzEr@>Y3Ej)l0w|x+v=~KWw+b^JYSSpC@?o%MErTrV`B@QO^=_KTsEGri56X z8Hdi)rO^s)pX(6Jm9h7bxzhz96Z35L8=92i+rP1xG!4?T^~L{^-+N&j3kp8|5Ybot zw$*%I1emX(W6G=>fD>Do-@Ze$q}bqoO#~Q7z_-?DR;2AM#wlgu zUSD*JLV_iC6ylV&i+_(_5#4~2wgYdm7rXx@XPaO0?(%v0QWObzcqvSE%4%f`t zfOgC@DFx56SSaPp;?djQ;PG5VPUkgc0$~7q9OG-%a(9i=U5AQjY{iFls*VFne~yU@ zrC2uDuYN+#4{OMmR$)XQMH7pPUI1LZZ0_Hu32h43v}z-q_>>9kK&5>JkEwA1-etXYpK7S1Tc$vIpr5Sa?6_E1VIWM8J>9th!J5 zcNJJwXHQ7E`#6>_b-zZtn^h&4okh-$=nCgN*M2%b)pzZ8`b=jW%mojB;shpQmn(|~ zG>X8AGBRJp=LJCaf8o}Ui7MvI>j}zu_+cu4Co(LS*jw0Mi0#|oC^`N1 zzA8{UJW=>SRG2Qen|w#~0{)epdW|UgZNYC%4(~f!Y28?{^1QI^r2eZ_+mKl>D2e8C zkAUMJnzvWd-JK2WfSad5p90jhUjmeXOeGCFqh?v&r)wMPeQ)s5y^O09`9ah3m{|>% zU~GVx&tU@h;T3yRcwbrxbps7^rnHh-q+nC&u_?_Zt7Ndm7^gpi(KyDjN+S6KYVdrp z`s(MvQLWQWEdW!@0t*XgzMA};Qy5Nofh#6hvi}L`HKUXeAresk4V7Cck-1N&3b2szy@>Sce_lBc&+} zg(aH_(gITsozDC$j*lWyBk~^#pwd|}!=D2p{XZjZkq(2uqk=@>)nG3_YGeRaB`w7| IdF$x^0mXiBcK`qY diff --git a/firefox-ios/Client/Assets/TopSites/trulia-com.png b/firefox-ios/Client/Assets/TopSites/trulia-com.png deleted file mode 100755 index 386dce71020ec37cb55945f9dbd1c555955d37d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2062 zcmeHH`#;lr9R7TFX|qwIkt8;zTynpxR2rLGE}KhQaaeRjNl@=nEO)13Dj`Kg9AA4TU`*~i^ug~lKdU9C)o*Fnk8~{MW+lvvn zr{BAOsSHUWUP{;qdA! z2%0O2+B&OrSL?0OHy|4sQ%u&InOj&|S=-q=I67@|-n?b2%Ql*;8=c|hz1_#x&!5Q( z4BoMmy*o7Qr|<~Qo~XV1Vheb^OFhe$J_UK|x_raY?CAbh@hg z%-M4_7k|I>hq%7svZS%;%GKsSTUxK*xOwaL9ckNN?H%_!WnB**K6>2!q^Gxk@Wsnl zL$Bq-BcpG}-%Wh@IH^!hefm88b!K+%+x)^mi{JNWT9*NUYVc;b1}6``dNC227eEA4 zqE3oKKY<)bY&zZ-)2QM2bgy60R-Z(2sgB!>W0TT{vW|WF0P zrzff+9zVF5bd2uSqAANmCGC1u@_21FFEwrV&M||BkJO9QT1KTWqbw<;A^nGIYt;%_ z3Nj~I))5ORI~TC_sg9kephoSgnQX$aShqn-(o~JgpDB}pfN?&nDmM@*oDyO0eNZz8 zmElJEL%ylBM5--e>+=CP&nnXNx;+=_43D(A*(n4ao{<}OM}7k3x$TUX>U1PgGbkVr z%~#rC-U&Pr4up~?F!Db6H)9OCd#^!vHpJD+;Ti#}t|cOeQ|-WOuUP3iBkj{QP=T;{ zVNI^x$b}0d_PKfsmEHwEL$-BHX^`_rC4X~W-`#ojND5@-@uozOzCKM*lE&}HwOE+CR}t=L3aPChTKoJh*I61F2L zPrk+82TW7yZE`v$5XRuC3L_P6xHhFZm1g-Bv)qh^+M#qX!F&x)d!7*Q9Q?}i@5VhgFxndMbWKEQq zKqIxM4DUW)ynE?b_9Lhm;BVQth%`*k6(90uc1;`)5LfrV9>V#BQy`NsQ-Pg`;GWhi zHBc{qim!gKCONJLmMD3<(#d^yx|#bz$aMnoxymtv{oyedS)a?vpgikC{+O9+h8eev z>N|;r-?^~lmy>p@c-NdiEOL6#rIsR#y0SwrDkCd;C(K=X@5%1dA);_df6i7HP3Vu( zVP#xpvZHhg1t>PBNrkb{l0J=IE$M|u#nE6FA5`RgSJw04 zsgMy^tB)?8Jh3pl+#Q|wo{FnwxKQhyaKa3AFY175_571bpD5UkC)JBW##5Y0pHFH^ z_n^a1G_zaoZi-?Lp)ggfl(XDWt~Bf-Tq-Zv zb9&IC`f?`ZZ+1IK?@RnmmMzKAOV!}@H|RQAbi>E|@>c^n@~IhS?=<8sgXk@xA(na# zi4oKp<919b_OXXHv@T(O!7~Q1?=(Ty&0)&%kD&(75b~EcmfZ;9qh*x+5aUbJyz1)v zBORk;JU6u0$LhhQi8Mbj7Tt;SgB^58J64iJhmXYb8&*}jw82S(Lsug|mWA~!+o+X# zz}FIv?@!8dk{apSFxPOj)P=Pg1U&M@ek5D^rq=T{zTmw4{b;?1^ca@QG(MMcWEX9v zy!4%jrp+-#4Tv=*l?fsBXbFU3qS&P&2Hx)ej0QJO=D$IR(uM#4 diff --git a/firefox-ios/Client/Assets/TopSites/tumblr-com.png b/firefox-ios/Client/Assets/TopSites/tumblr-com.png deleted file mode 100755 index 01b2e8daa1bd094ac7ca9c8f9c5d68defacbea79..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1274 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H3?#oinD~={fpJ5CPlzj!`+pP+oe+qAxvvBm zXZ>QlDfmO8iAl*BnYnrS1x4i*mDM#3%`I*19i3g>J-z)CCQY6)ZRV`mbLY)pxM=C> zwHtTr+_i82!6QeHpE!By^qI5gE?&BF?bhu(4<0^x{N&m5H*ep)|M2lG{{Hj# z-xhAq&p;<-dAc};RNQ)d`((JVqX63n6X64*0tK8(C)Talq0q$0dNa`Fz}yE+T^T*n zT6#MeCT%$OYr5@^dH#woXTA*C|30C1yQR;o@4rmuuHs_3Ur_D7wSuQ5LV((wEm zqx;u}l!>_xC!WT?RJ`2~^H)W5t=R2(s@2bnSo&p8HxzEa=5S;qcSdQhpU>O-U%cXO zbGkWnR#&II_4_(M_(pNfhofw^k7P3byjkkH*+f=yZ&A6@t}nj}Yt5A(%7lW*}t++g}q?f_Z)TCS`a zjIVs|$Uk5*cW90KxzhgK2Ii0r#W%Bm%Ab8R`?{CrQm*&vd#Cir-&^{IVG398&c40% zZ=U^8yEAL9c=D`QpOf7;z0ukKf9|5s{QH+{%$xCQW!akC`}ux_&d=YToT=aKx#-CD l@8{o@noqNe%Xiz)aQ6{|=7aAI>c9-a;OXk;vd$@?2>=`s7kvN# diff --git a/firefox-ios/Client/Assets/TopSites/twitch-tv.png b/firefox-ios/Client/Assets/TopSites/twitch-tv.png deleted file mode 100755 index 2021463da9ae3a4f3f7d9a0449335b9898895240..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 975 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H3?#oinD`S&{R!|1aRt)OYC|KO4! zzhDLiRyHmkJ^>*SF$p<&B^6CAZ9RP(J8z$WkeJxG|Wfox2a7K6~@_!^h8GzJCAt>yHC(`5XoYCVfvA$B>F! zZ*QjuA94_2doX8jw~|(wPR9)ak%N7_BHUH~|L_0d$nH_(=~K4Z`plcUCm!D_cPbxG zX-bWJwf&ga@-L~8VbU8GNv@JEIKd-Pk;tZ#nRbBFIAPCGo`|bw8kmd|Ud)x;uy7`0 z`nT)vxec!^W;FPk%KjvzXR0~Frdg5!DQrD^44I99tTZ;C?K2o7&+=#(F}uw^(_ji@ z6*A|sDljl|I56yGKM}M2^&x{jS0(qo>}H+tde7&}279iTE~^8{G6^&=us{?-m<WLu~nOq_ZuVy{F;J_B7Tdvu24J+}`kYWiWHlx93N*IFlNT z>zyt#1@XGqxpEggU(PD=X)=?{&-ub#VhLybISkI)s~%9cmpq_tFM6Q#Z}66eEw%qG z=Z9=z`2BD7`F2s=0~`NeQ@dKvu$$%edGUbtVSBWa?GHO0-M(u5JfOgX;L6*alNQRg zl|E}{em3urOx5#O{H!YRi9Z)M6#UF?`)9ylW6v|8F)n8sfPXs}8-M<1 zIDLEHSAiQZZqz*RE2zKvx7>cc7VB4i9=HEzyBIB)z8q(8_>|1x@KcZ>HKN{Nfz84Q z#;1u#xfq_aGc~;C=h0C3(#~M;$(cdpCnLk0KNlH2e*R~-*im?uF|0l{(*B$GN&S;y S{sq94$>8bg=d#Wzp$P!NfiemJ diff --git a/firefox-ios/Client/Assets/TopSites/twitter-com.png b/firefox-ios/Client/Assets/TopSites/twitter-com.png deleted file mode 100644 index 8ec01bec302273cebdf5e733b24fdb499a16712a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6108 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 diff --git a/firefox-ios/Client/Assets/TopSites/ups-com.png b/firefox-ios/Client/Assets/TopSites/ups-com.png deleted file mode 100755 index 62b0ff38b54af7275b4038c3cf5415018d4c9b24..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3244 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 Kt5>R76aEWLE-)tm diff --git a/firefox-ios/Client/Assets/TopSites/usaa-com.png b/firefox-ios/Client/Assets/TopSites/usaa-com.png deleted file mode 100755 index 3f175e6946c5f8690aa42bb8bfd7e4232ac218df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4880 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 diff --git a/firefox-ios/Client/Assets/TopSites/usbank-com.png b/firefox-ios/Client/Assets/TopSites/usbank-com.png deleted file mode 100755 index f1f254d3bfa658e43d75177bf1e66a9d85f9d674..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2253 zcmeH|`8(7J9LK+NFphC;xhH2i)5vaZEn|mfoVm%7)?||y?1*yY_$J3V8X2^9l1Pro zv1}>Clw6TxM2;~{A=EI=8H}2>`$z0g`+A=D=l#5YeLwH#`J_8LT1!c&NB{sJWov_T z-E;6CiNW^n20LdP0H86>r`_>;QTRXqH}Ib~u$+$7*c%@s($&!o03c8pTtpNhCN3d~ zl$MeGZlAn@qLQ+TD(Zlmx`w8f_Q6BCdin;2Mn}*l-yb{v;|WtUbF78sDIDI~#@5dM zw1cCQi>tfG8E+robHDfz{C~X|cqu42B1S0iQx6*l+-kGdPWu{`&JG$ zH!uJ8?*)I*?i3c?D=xWT`k<`5;$c%RVh!J%Qs$mrO+iODJE^n3P)k2ACL3yYt>aF)0$YwH`EJpR`9j$rreHzLlh7XU<# z+TtwSqbHZ{2>skVl)48e6urbIv^p61TJE5qjjf&>KB+L^`gK2ph7_t_k8_fejz4a| zSk6F8yn^zB(J(UbMLqplYDoQbyWW$$`q0HO>XQj5TFUh`_CMLhJQ*kO6gDw$kb5nbei$J_6pRa|A)E{Hwx;$LaWoHT-m`YfI+x5UA66j?fmZex^=`c_T`+Q~oZp z61KvRV@4Q%wZZ07IjT}Tm)6||gF_SMyZ%_eQahKO5(V`Vvq~#()=8OrY>dYdozk#EA?T>DJwP1Qn8eh5NE7f5Cx~1Y3cc zde)-ATM6;vx-N;PZKWr9l3T0=JoB~`jR=ib3v0o`uC)9^Zlh9j8 zx{;p!dC&((kIok%$*yAk;8+4B4kY%dMi2I<)=RE_Ti{wf367Y9880le*JPTHNEM!J z?j%cmT954XjsmWw4J`qDI?xc1V)3?> zQ2MHBn~2*G1gT;d29x-VDK|Jrp{7a3ygW=i_nm?mO< z9P<*MdesUAo^P{z(R|z8k=&n^@LlsK+Q3mN(0?E^@@PSncig49Bi83g9}PQ<4(J1^ z$`eMh_QzT;JH`g{8c#NG1*A@PyJir$h*_L!=pJ5<82gd(;pS48w4&}HbK(1_$gJD} zj;M;ACrO$xlflSF?ZZWM5kV1bsxJNKKkyoW@|(#=g%H-?)LOH=qhxJGy!x^nlZiXf9qJBS1$ z#T&;jF_R@dlH%DuBda+o5K z#wCTp-)x7kne@WN@?}zL_$`N{&Pqx(jPxM(a%cB*)=a1P@GMz^;FF&2qEnnWV~PKV aO_?H*UpFh?5Kw!s0kFk8;%Y4kNq+-(4S1XY diff --git a/firefox-ios/Client/Assets/TopSites/usps-com.png b/firefox-ios/Client/Assets/TopSites/usps-com.png deleted file mode 100755 index d709c6e72f8215f8891a7ce75aa32dff3057ac50..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2591 zcmeHJi#OAa8~>VN?wdfuYeUV-r&} z25V++VTrRkV{L0^@8IZ!cRuIp=6>O#$0biMUqAnVK*HsqE5RY5Vc}OJBCkb7Uyq5s z5f`6ui

    1O1_;!PQ7zC?OytWM;Vz}kDpMob8`R8%YRBOc=o)gxTN$2?d7Yo^1mux zzj;fqtg5c5t*dWnWHd3~y>D)5{m}NQy`!_MyQjCWpEdA#@XOHf$S8Ykd}8wNsp*-o z-)86LzjGEAm$=I-tGpj;Ki4-lx3>S;`DGVvKL`NAB35Q-XSl-RyIr45p#vhzJvXX- ze8TXaShZBDwwhl!QN!{k3*+ble~S^iDvzs>u|XCQa(Nw(*m4f0RALS?EfeFbs=**T zlzs+_qWvSTgw@~J6&ZUn8?zJ>(zBR9%UHJV;iyWbH2)oTQjrftxDwY~_Z+lYJ0`x_ z(L*O;FGazaqd#iD>g}pR4jKx+R(86xVl&bBtG&Bx)3c0hZS(`z-CU)yhNg_{F#gzw zqKDt)1!RYCO+7!Bu6{-B+$A_m6N9m8nnUdF9~4Qn6I(W(U9%3t>j@{$e6^!AeXDqS zWTR6EedkmLO^+U>Wsm>{6C7`@(;8<3-E|ST+=YJm`g(%30Rne)z3o%PKIyH%KKWY+ zL18<$hVP*QYLTE@2z)u^ZB<@e5D3vmZ7|A-9ZFFJz_CgA6VS$c-_g6hL zjkqcnWfl)i1N2!7Ow$%Px1?AGorsJ+%qo+3tyJQFDiQ4Hp+*m>IGuc#CNCa(1cUoE z>l`_Yz(LP`BH7h@SuR;vtm#OZ_8P0ZK@X8*(^GAeuf4brNg)r9M|F-{^4Q(w;}nz(S$74hEdF zpV0c{VQShqRogP+UBe^5aXD8euFP`Cz zlsgY;H^zLHrJ;RXyaOaT(FUD!p`s$ zufj>Wvnf<4atv}~UcUMROTMoNr01=r+Vl4^XpG+~()y3Iy0*)_Uj zX*nXv2ybL?DajxAb<}yYY77sFz^bqJF~#}3aPW{otL^@}7lu`(&~TgJ@5PQTCP*-> z>A55WM6#K{X6NzKp7wOZ-JbUA~j%!wH$QH*f8xh+9v??T`l9lcv z#xX1%;q6?Y9Nql9t>Yq)g?L4(`qRX^wblaFSsTFkRCA|5hScTnWOz=F$<~#wI?m8O z?;!d<-(P0r@t*es%R-t9EWJRm*A2p`iN9ZS8pqvsFNJwE5PVSZCVjr~MucZ^;Jiup zkOZHRCD`)@G$?I34ZlETaN&E1nG*VR*$IlmkBnyeH>{Z`Mz6na@G50RFS4I@k1Ru? z_tElLo>TqG4D9|r2hTtw4Kxj1)5kB!y5v36l!d86)Js$~wJ*-Ky7NLu2By)Oh&h;B z?}ghQ!Y&7j;duqT!!$o zmmH&Pn%kV{18&KYU2#>dw){5*DKEB<{Qy%ic+@44Bo4<;OSAlTK43kRyIbTmcklWn zoHZjS0Umnqdhw_w_HcFKa1VW0Oi;kM*fDy{ulGpIf&`18AOTh(Oa>_uOWEg*1a1DB z*MhRqdEHyyW?2LI{v(pfMC#+53~4#cboNdOz~aWiMWgWHKYtM&YSr}V+A4$ZaO{f` z+uS>7hpYj`fMN~O!|MvGPgRqsZ7;8DGdpVqES#)X7kYS9IIl&)|4}HA=Bs-jg)%kk z)=YqCy>)|O-InH4DqeAvb~6>KWsbK9nlskDkr;{a|6k+ZM|pSsmq_5tPf?fp#e{x; OdRFFkX5|>q#Qy=zMK56h diff --git a/firefox-ios/Client/Assets/TopSites/verizon-com.png b/firefox-ios/Client/Assets/TopSites/verizon-com.png deleted file mode 100755 index 001bc86f039557b4432ebab6aed6889aba58965a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1887 zcmeH{`#+Rf7{K56or%#H25Sr{J8P#!V`x;0nx=8Tgh80t^@cIEeK1ndCSEjcN*8^` zC0oc;Qfc*3F6A4`m<8Me_0sjvYU7^3>@w#pgt& z<>xDYx>$8de5JPT`i+~n8g4h|eu zOiZfYPEF6us^4qpKK?nc`|Iz8e-<0qGfDu!1_gL;i_98rAJfG~@@$t027|Asu&1Bc@Mls#GdLqPFX}miOV#*hSh){Sg1I{zo zFjdX9B?#U)#()BEP`&DP0G*9v2o#v1%H)?IO5^7M1J$k)2CasKf<$!02SrqY*$Lv%N}7YBwE7&5 z(Z)Vxkb)i2-gql>qRRa`5N9Iv&~kpq9FHm|#!F0aVB#uHPR?cXhB6n}?kJ)-lw)~h zyV3IjD*=|xnq^K{O^FaRfURCQ@=zBN5QwbBR~;k5{nADekVs-0QX~~Zl@s`ow%`|t zYe-g5iO^(vP7i)bFxQwODHo z6=m#tTIYQN+-=;4~Bp;PUwbFTAN8B;A>r9v=0BOZ#9O@8>u|Oz^Ad< z2*)?$t0&U-*2{pnD8#2+*vU>nRc_PgXcuy+n{tt4%mvtKOa3WJZTXJCVwz>cl(95fR6(O z#U@)x38czd6A3T!nzJXqD$f)3;P9gXsd^(8^{Q-*8$SM65IQ&g_=yyM5h`L#J;Dx1 zqlZ&LU+eV-1JX5e5-fVAtLC=2DQ!?1LAY6jIE+BZK3!TVOykQirCLp7#6HqE?i2DT z^~4J!pj@hJ_u2wHjZAP|o2*FDfaKr!Cacl2PP=P`?zD1G25FqI6^(x~wo#zp9g5QE zP40Z`JVfTLE8{DA?vA6m+X4@N(iqAauWRS8`k`tIGSX($z1QldHt4!`;zO*$5-FGf z2$kT0ZuE(1j3srj1X3f-812~bIO_ctElrrq3bU5=;(%?uJ2nuDWqp88MTU5HKyy|f z<6bls5;=+MiD01US?;S8BOoJKLhl9Y4%+MAWyV54l!-xh^A#ZJFw`*?4it4hb@y6c g&G=#Reti=1O(u^$UNa*Rp# zi$v+^Z!tt08Jn15%(h$Xu*6zf+t}LKJ2>JAPT%cxc6D_DA}&55F)8^JCnYuQbb3Z+)|u>_+=4=GQ8Djq z$@x-#S-GI{()U%>m#v)ej%nH$Hv- z^3T_qB+&v4rv5p|-w!Z0xj9@~T%~S?SjZIBm>RGkyyf-28u@%(MY{jEc2m#DN!tBN zpo}^p9zHyX-?NJq?HrjoIqNie*v1 zCUJ=_)x&Uq6nF3hPsBc}L%ij~Acnb!0G%vCvV2L&bZSv{a0RoH z2A;sR+pxy3^PLx@)0uLt7MqD?dr{VG*}Q&@12UzC5bNV zs4(bdu~t~Q5+#doksI*@lYrjv*k)jGc4#aKC}S>uz>`ksv%Lb=u?HAzU4k zBtegiUBr`?Vr2&@Yg^g8X~Vv>7-6;Yq)gMivEPt*f{_QuaJ>N*lZ6Ox)3D7=0qbIf zrAkj<_Ne%6k-!-kgfm%IkX0uwtQzDBARug*9DNy^rp>-Vlj>p=Zlt$SvV;C>C^qjS zBN~CZF79dUm6w9sTQ#l4W6izPOV}wRo2wM)_1WUhz$E9f9VOkho~K72m2zhM*Q6E| zaYT(WUEh_E>nwv9w<7dMa-$h4cn ztAQ$o!~Pq^&pB|C%2GskrxErs75fbPR;doB>ap(nn+Yx1My++^HDhfp8;L2kKVOUg zq6@c>4-#phs`t3osO8IOjh!Qse5(6q13DC}GfN|8)DZp`x zVI5p)QqCX6xor8cf`{70AqLP^GeYh~Y^IOHv>m0=v`~m|RPJdNF($|Vtq7*OH`2Lq zQn&BdGz%yKNG68se1$yx(g_Ym^02Na7Yf`Md9O*^(6rFuXDXzs9Lvqf0EdAr7az}&>Xo2n8TU@$tJO!%#SjRZ;LEa3YsFh z_n7>N1dd-h)-}rn((YC42HovJ-26h>G)-gPxwwKnWX|#MAyD_$)H<6%ItCxw4vy^Z-bGGPC!{nsc{2I+DBi0c| z#qFR8NA2}b8O|5hW0O)A^ih%u5Vw?afomIxc=5{Fafa;8mNgpC~K zh+6CDxSVckE~`;;DYmhhvWk?B^W!=H!FirO&*$_0Jnvs$&--~_@b~kAK@m^@0AP3= zhPd`A|D2lgnkptPEdv0k-G6TocFlhKKHmxauLxvf-bbwkcP5qS7YG1KAZ4(M>JMrV z=sIma4X69Rdw6NT2z0JnfZu?L6C7#OrKcz?)&(6EEy5s^{RM`B{*j>ab@9Zx=)aw;|LOnS!I z%xp3xC->a>y!?W~qT-U$UoKuMqn1}xR?(_2(-~KotgChP4UKG0Q}gwf)|+j=w|8{j zzQeuCyVrHUr?>B~2M-@Te$xMxKQK5nEO`DxI5PV3)!6ItiOH!qZ>MKOV#(~BR5mYP zc=vu$@!{jArRC2nU%sxkUTY@+0Qe;yvnNPzlkEO7no0sx7v%Pi$ORiT8q%w5KNNGc zOs6{D2v=A)qlLSgPKCrECb!XI&oopz)tgs_hFCQ=BGW1RA${#4`B6Fd22U>J1}uk- zKl8$snc@GnU|wnP##L&ivM0fZ=IpHAZ^qQJV^O3q^vu0?7fho^@8ceyhxIzTmN(n8 z=9Xx*E7LPGv9@95uCWtsv1d#sqBGv8%liJLq(`aj>-dmARs?cl*eDVaebl3CV{b%nF4-gE&t-dlX*$TKJa{|O!>Io zf~4L`s&ddlxy9V1UaPI3$*u347^GUCj~ettwB#*cCADxx~suAWC0f z+~0azB#x-TBMV$1z~&L_<=9_|^8-zT08{j8^XFT=Agx0LMhkGK&84N?ON2(X-j!Ya zU7F=2E|wj(M?Mb})j%lIT3_3EMQ>M7Dc5RN;XLS$01TtnpI%3H$=S*#QNNv+t>ASm zFxsRPrqD|>O~UScd@|us2*%i`*wnn?c zZV}pE)SWg|AUFz-_VxB9NOL@=K&1R`o6?LJ!vJsIVh5XK;RC2=`+qf%(zxZ{~iJ$ky=XfKFLwOX&@Q6Cs48b*4VeT4B z zsunY%X&Z*aWQEZ-rk>9@NB4&=JkZ@3fM(qE^M6v$;@F`EGAy$!b~$&L9t1~zrg`hs5 z5+`%}G?FI@4x+FxhL6cK3mB-6jt4#B!lME=va}-^X=0Oo75-|%k~$~ttV#Z?R*5#a z+vI&MG^0)C;+)r0C+E~XHnIT2$8WOB=99hapZ+#%NjG?X$45%9g`raZh>V-p-SOV` zML?Vz98@&#ph%TkqDHaTr#>x(&{1d;W+;Z2zjqyiX2o`pVcj)i7|ad+2ePj|pMEi+ z<9od+r~Z^eLNx!nL!hkz(y&ZzI)DI`oE)x(sNWa}>1}2BJ*R?;Hk0x zZ}#{A@s5a2szAr0fuQ?B9ZD&tTqS7h8|r~I9}b5o_0Cm^`$rU&tt-{}EyrsNlnj-y zTMSo6S2t9vaeb;D*)>{I?;T@?FIVRz7rOb{CS)J1Feu#uhTm`d!-W(*-T+CO@a^yw z1PKhKu&M<~n0I23KqrYHKb%_}-<8YTFCmg;4@T2gRQ}wWGoyB^kATM`_)sH{+UAq! x=0l)KEbiH_ol8CEosWrjFCqU^H)ayD`~-Gl)>ngb=Nu+9VyVQliYQB!W7FqN?J)A}H0M?l_0Elxfv{rqs}xmN6s^ zb=6!+4MmKpq_&!B9d*q9iv66)kNYT|IrHtEO0-8Q$E&(#qP#)}G+t z=ycuL#r1}p2hr2p$Im|?FesQ5LJqqf5qT$y5*-tJFCj50Ifa^JwJfL%l?{)`mqyAp4ckJlP$vQMo8iPZX-CZ`n$Int#sKJN_K+X~Pn zepT{^AIu~kUg%ylVTsRGbO&9r5Vd923?9XCxkn3m>bA^zN~xq4Vf-&K8Vo@XKPWqY zbtzUq0Tk0S7QrjO;azM>*;@%JZcLObQ+kxl2(BC(gi+Cvq<|iamWJ*Snu4$*Yz_ zjZAHG)b&1g`E5^@;(86@KFC0BCFCUaQjMm6ot#%;<{OSrPAd+5!W>e>gpG^ot(N(! zv)0MwK;)jxp>dvv4T9w;@VajZv1ry(PFp52>w0J_wke?l$7?C$@}9AAgXGEy4*3qp z1ToGT`jU9|Xr;Ljvr*C>Ga%bGkQ6SOL_s=Dd965%rM1|adt zZjoN%DUAZ}BGi+nV#YfC1q2op;G0}o(UWtF~1jS@)l;7q%AHZT>N z?dz{FgPV>$=U^l# zWlSJbwB}SYmgS7^T=imK9=Hb_7}Y)iNF`y3f)-#IGAUMi+1jvy-^u_}eTAVSQY{a< z+&z#J33%cXKK)50osU;hhXuc!dJaORD)U|azBi3hfc9B_7vC7KN_7O9cy8TB2GE?z*3nSA^^RO9t@~-D)LNM1G-FLiMLhS zjBOSw^X;nU?N|o>H!T((W)CS(G}kXH`tOfeJ)6qSH>)bO8cm>G3a<$lzat8{tZkI% z_=0^H1w1jgNb8lkQXd)(V~n@JkdDbVk@wBk*E`Pcfiep`-QW5Q^^o}Tz*V^0m+7gW zfQ)*=bVPzY4y?v$=PVtsM#@hWfzLlz;|}}{!ilP3MKm&FoWM$$p8j0!DkL3V{I)HE zXN`vy2ew7@naNO_GcxAj$Q*_%3;3c4UBGZ1cvaS7s!eUKdn|NQAcMh7I{mw5Fi7I8 zkH8|hN=na-v3s=wQpCVcFgv?Os^Oin*_!o_Um+uYe4yE!WzO|Iz0ydv;?`wEvPCeW zWo%65YtiSTWzLgJ)x#0Uhynw9uSyS5S)gum)lmqDD> zci&HvAOIyf+GV@y38F?ca!tt6-B|c;F=se9Q6Yy*;08pVtNle+G7^071K+RVFR%M% zYCwW&d~s{?;NAXjHeYNaqPE#ZC>?6Yl*x`3Yfyn+3rIzbyga*--y*26cEJILRU4iy n8f^+MDZ(@T-xO;e?;Hs#r7LW!FO3bKd^3QRxjnuG=bicw@>;*w diff --git a/firefox-ios/Client/Assets/TopSites/walmart-com.png b/firefox-ios/Client/Assets/TopSites/walmart-com.png deleted file mode 100755 index ac9400b1f7cadb30e378ed6afcdab5370c9a717f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2267 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ℜUd!hBky}_FKc1agh!#oDG@y^|hhJ~{ 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 diff --git a/firefox-ios/Client/Assets/TopSites/wikia-com.png b/firefox-ios/Client/Assets/TopSites/wikia-com.png deleted file mode 100755 index 7630eeb18736173f18b62910303b9a4488076a2d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2512 zcmX9=X+Tp)7tKP*BVid5h!9yOPz4n*2r2^NdqI>-?bYx~-$)8?;WdAtpq$AE zZ7k%`vA|ys1z(7`?`b`gF!-C>@KhDgIzx)_ddVYONYV7uw zLFKE!x8JNQEvQba-}#7CpRzC}yma9u)3`gbU)T1z0(T?}YglqG&3J9I@3XiRXM{@{ z-igrSMy4qB&kpI#)Aqy>JYiGKzlIlP38;O{RyuaxtqD3!^kub1Enl8kHmD}y`q&KM zq76QOr5Ovoe0lXRcIYAprHZokHiz?5E5-RyM;LlWI0tYsS$@TGx84(2?ja}!bu`f~ zq3z+^sA%t~DleuE=TFqbK=t_a#Infv+ZGoO&u~eeo`0i`Yi_o0IeWUKOH9TxN)I7j z6xA+}?K5$@@cGh=tcr1CgsZ2cJy7|}!)b%JD=kRY);@$iG?Rw$UBKx zzBL1#A|np0Z2r|lW4i|$f3^Rt+(fgGWcXu0u0T;SS#+w-WqtgOo8i$9z6d-HZ{_vl zd33?g(y;!jtkwsc-o}&c42|%AdA%8VFS_cXH%V}wEH@{L-@ks{yRi0k@1>6j-YuHa z)j`%-jk2PpftbQuy~aON|dx72n>saGxa|RYS3@DiK`I zURq$zVv}hs1vJnLK@ri7>A;E=L>a#IY|aSdCdcsT$`Aj!VN5MLlM}D=&6zl4EKPL6|Lt zL)LVaDPSlU8=wtVM3r!y)V7bVXHC7DHpx!c?f~5e$R`SXSX_(}YeA(E60)^2`l+-u z25vNe6bMxk;HgJs1~``ALGSLF`eRh@Tw|vdNHQe6s2dGdO(|(|_w@24ZcIU#*LxGG zJO(Oh0=@zAdxqKt<~x+;+jQK1dSxG()^>a%)P-~{JulyLHt{VaXv9y;9m{=tjazfV z{XEk{8%;dnsD~+Mu7RkUrg5djD2mJ9z__dx*IdfUvWZikx)cgF*}iwUrLXZNi;k1A z`Q`KoFOQ?braMwVi+nEC9d=8ojKds5S*l=AL?aIP=v~M^JRBC7f@`hYkKk;_#HVLy#>?hdZ^$T^ZUKy55H)dM0hTKu=Uf z6S*N54ED6sFpn|cyw83qL6eKN(;fIslI}Li-St&*Ou+#bn2)JlfnDyUDB)vPd)7J! z{{2mlq@_lP`Q;T1BFhN1m~p+I`PKFeaA~PZjCjRgh#FR zj_g(+HM_@9S&i6%Kvc{Dl`&8~#YTlC`=kC7U3!N&dJ0VjD{J&oV&1TN!AQ6~{JshKm zq%_R}Si%OIsXY7sk4dH3qv+3zJ_j`TMy(F60K&%`j;hZTm}a9Mb6_tHYTzxp+!w8& zV()JT)8n|-6>dk5jqf^do5d|@#2&|Dp4iSwZOk@V@`1fg#WS*Sb_l>yYaymbB zFhi!T$g`V`He4+ph#+1;34~*G-hG@;Cpcue4Y6_Bc)z%%j?1kPfjzZl9bXHwy~%=Y zw-?}i4lzPek-)-BYALr{6F%(rZ+_(#q z=~{{{-kW2Xkx-iuJI_D3!mQir1C`jVY`h_`psB*i8a_hf5XB?n_DrlHz@ygetGV7T zB^#!_kh51BZ>(}8X^u$~%!t1@#H15a1#fY>ooL?~>?YiTUXuAe#rLC;chHIjPGs== zwa&cE#8u)J38He++!6w*gU%}pv(R*n#}gW8Wd=f|>cyz^3#~aN8$1y_;hXc5ru(ppSs)}s z(KR4>1&UA^uVe#*#qMYBJoWJ!=-Km-w>?9#1y%oHXe(fou8-6zjj?U2JA&+sbl#uE zX}|HdfCwLErKH`9)nbUbhWw+PmlJ9(1jU~@-f{Hmd&(Kvl9AaE) zJjrHn<_I4LLBw|Rw28nIX&$+uyO^^uVAJx6SC+0gI~!>x1E2EAy+nK>93x?S&b`@B zbfR~+VHITT;8YM@_wfAB5V@U^P^cLDVP(a0Jj@7JA81N46{3+Qs#q{RruoD)yz>0V UC#kmX<3V{S=uu6^EZl02B}3)_51Z4arV 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 QS>UhKP+H1(C5xbc0jN@>H~;_u diff --git a/firefox-ios/Client/Assets/TopSites/wikipedia-org.png b/firefox-ios/Client/Assets/TopSites/wikipedia-org.png deleted file mode 100755 index de6627270eb831deb9e2ecdbd99d2d2ab35a09cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2597 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 diff --git a/firefox-ios/Client/Assets/TopSites/wittyfeed-com.png b/firefox-ios/Client/Assets/TopSites/wittyfeed-com.png deleted file mode 100755 index 6f3a98183dcdad4fb63b909923cc664dee91d150..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3402 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 JR=9Kge*v0=$Q%Fw diff --git a/firefox-ios/Client/Assets/TopSites/wordpress-com.png b/firefox-ios/Client/Assets/TopSites/wordpress-com.png deleted file mode 100755 index 5403f48a70661f38ff04db0935c76eaa03074cea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4149 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 DujPef diff --git a/firefox-ios/Client/Assets/TopSites/wunderground-com.png b/firefox-ios/Client/Assets/TopSites/wunderground-com.png deleted file mode 100755 index d444c58b90c1613e92bb6f7ec63f3455348a1e28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9949 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 X(TiYE0qx%_`!{4Il_aXgAc6k_bzv{H diff --git a/firefox-ios/Client/Assets/TopSites/xfinity-com.png b/firefox-ios/Client/Assets/TopSites/xfinity-com.png deleted file mode 100755 index 1b8c732868ca3c1de4478c65ad44f580461ea8c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2336 zcmeH|`8U-2AIIOH`OH`bccigR#uCDCam7W%B+E=8$zCy(t#Y%KAu=>dS{S5j`G&rP zL0Jm0{}w6NE8n*A3s_^ zQ0N!o10n~pqT&*gxI=hp8Cki*@(PMal$2Ens%q*Qnp#J-b#(QQ85kZnBAzfgX-*=a zI&EoXedes4y@R8(%SBg;yT_%=o?hO*et%r|4+sppaWgdRR(QniNLmy<=3Z>vgNKh2 z7>P;APg0(yrln^*%Y2@bo0tEx@KsUq>ypy4H|3RY-&NPt)i*RYFmL{#9vS`g`OEkOYjSF4c5Z%QacTMMx9=-!Kh`%kf3mkYe{XYlc8i7$Y5_nclTA<9 zQO9aOExU=DN${?&8%WI%WR>$#j3*4A6Dg9jiigYkEITdVCluI?nGpumdM#Bt^3}A~ zMV^R1)V_~Bs$$yEG@J2Pfo{0)4Et->_pXn1$B%Z0ce}GkQ$z3CC}YtvCPdqy4A*<| zHt*uXLfM2;3!ecLAqHQ{;i{wuU-2&Xkj= z`{k}IF#Nc(+@*3U+E8Ahc!L54R;%15sF!Bf4^_U#LQs2a6>GG&v(c(%^cWJAwS{{W z&Ph32d)(5RhU#69R+rsT$k@Oz8sn>C0NQ z?Je)t#2bhbM&ySO+QtOu*JH2?H2wHT`<&FZ$#R_@f%k7;Ubc2+(Via$z7^)hcuj~HY8k-opY8-DR({;5QB5StAQwr6Uw|s5mzui_(;!f@ zWOSRYErBEzRvZ`({1X{lSTR`$c|lH7hPxc8e(*H_XZ$;+1v)r}2P;j6z%$U~8o2^W zaJafg4HkO^at70yyh>bw*ZSHSg%QL6GnbQ!C*}rYxD0ocCMR(VJ1`39?B(=04&v3# z4!ZdILpUx>Y69gJBLpYj4hTJD{XVdv>BPTHTJ|IWJkP9Q5Sey@E~tiX_5?(GZld2)kBzo%Qs zECW7XNe=;w3YX=bnK%MbFKIQqZ|>~;Ks^oZE_!p?%Lj_ItrOx!&g^!w+vZ=+#pyJF zzNjNVVaj6-!FP=g(K)5?kg8vL;6Fu;LAS(eYu|ZNR6X;t>F+odJS`6<^7^~Pz0bShK6Kc zQg&bJS-{Im;rzeQghi%Ky#|XT&AP?!Y8x!@F~C*W`h|5s#ETgE0#$*kM!D;+O)WL? zaH~H!#iIdy4XRxizqu}RNc|GD61j=r&hpD9i$|V5$3s%Qk7lYo^Dn19AP@;1`76kE zx*f>nJ;1Lh@kNKxhuh0^Nmvuzdu*IHS$M7*6kraE8GXxGAPs z=YfixgELG~MO{#>%#2fO1r1R94vwkf^s7S z?$F41Lf(!bq9j47dAADT;QCFYK_uIh#Y!VFAf~KfZ37c;o}czF12U^pU13F zGR`oGzqAnt-1PQ%6GQi%v7KSofoH;wPVheGGttOHR5p-`8$o21XQGGB!+g1Ubs|@3 zZSDlUCszb$zJ_u`E-)n~Sa?VbY|{~0I`s;>8t7a1%y(t-_b~mkRuZ`V&jZM2)~3ZK Hl<5BfgpPjS diff --git a/firefox-ios/Client/Assets/TopSites/yahoo-com.png b/firefox-ios/Client/Assets/TopSites/yahoo-com.png deleted file mode 100755 index 50320c7a16cbe8f4011ec34e163bf5554e9f2d51..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2266 zcmeHI`8(8k0RGJ3Hq&8Jj*%nEkexLwVR8*6H<6M|G)yB$u8v84cg$iCB_y@RQAt~l zLNn`VTE{qIMu}a88MTZiqEyC_wg1Kbu*(s~8|*MN+PTZv#B{gW4|sEeg{77C9vfRb;$C}4XOfGno4bdn zm$#3vpZ~#tLx+zX4LKG{J{}f+f)Wu)JxPl?6&({B7oU)reCF(VdJ4oyW&V<$!OG0a zzMPYLb-)d^>9@jTK;c$O%YH5AS`=hPBqm$p& z-P7CGFAxsAcsclL_|K8oqhsSD@xUWDo zsulopI&LJ#gJ(x(Zmv12QMCEqtvjc0mFmkVlN(`4BoeN4(a_C1u}|4V#m9IMZ|-Zc zIWCM8c9j+C5b1Lz56U;5P;Q^Z1V%-LzX?@iGzp@g&-Bx0OP0kYp&X(hL9qO#R*+I6 znBo$db!MSzPGn=f;uRYM$IFG6s`K-3z70F85_*as<~Hy_XC`;v-`p&Sd5%AoubD}E1&V$rfQEzo71$26aD4h~ zJcafsUgN9SdzQkJMcHovQifumW^~Ng%x#RtA{AZ}sVmFG&D_M&%yg`C%7kOVIyRv{ zTRZ%b(S=*Y*=wCuQ$L(Xbg+5TaJ_QV-prrtR8M^o@Q5_6@yb#idG{0C{?}U_s9~bD zZPf}4TryA)qp@&%a`x@?tn*#2m&mvj=LG~NC*#L5_)p-7Bs8^M%|_kXZve}o6YRJr z4X8&?tEh6#MOXUoh~PFp59L%N<8VIX@sj1ek2)ld7$WsS$ED$?y16%g%!siZY^zsZ z{Wj<*pfP*vOm5u4HZr))c8rY>E%oP@tEzU-YkA4_Fjh_hHqfyKn_-}zMyHFblBsZ& zZ1W0qH~MjHTeNUruANb$X}Q9N8MLG}FGQ01!nJ5jnVl^0D7Qt1sOjS_VijpA4c8s% z)w;*Ir_Fccd(*E;Z#r3d6O^uP{g7^a5nq=?s4rB?FZy#b^`?yCw4%C{rR_v<%_b8% zdY{kGs8JX*%U~3aPYga#N_hxz#eF_;Njl;&EM7Pl>||8gL@tjdNQa$PbsQhReMVK3 z1(z+EO87xcPl1MX)X&Ddu0M68206Ap&IlTsn(b*p4&#}8dAYae*ylg8PNubedttPK z?v8S(r8FC*y5l;xivo)dwO%Nmx7XMho_kODa{5S^_;Y0WDL+&n=s@UHA1@2RfcMt> zT{UerVw3wb>OHNRkrr0BpCzSHmznbHA83pw7ewi!6xfH-c7#NUeNSMBev5M0;)%3& zVkwbX^Fz4_8Oja;bi}QScDcCSp9e!dS*i|}^w!O5o{1py1pJ-v1Y*Gz`kqLT2ej=V z-`^U159EBA+EWL75=KE4CITXPfB_B+lLsrxQqtA70(u(2PzPG0uFo6Nn+8k~4Br;U zRN(E>16t}(6Tma&L}^Um!GUE5fs5@ZAsi4nuoyCo18Ir0LE?lw^%;B)8w2@ohFj;# ziQK=xHdq1ocOd6b>QFrT>BCJ(5yS*uWY{k83cGn!9AHm2as6m|2UCo?%e<$od}uHy1Bb IwG)}~57&5lga7~l diff --git a/firefox-ios/Client/Assets/TopSites/yelp-com.png b/firefox-ios/Client/Assets/TopSites/yelp-com.png deleted file mode 100755 index 74214d9832225c8577829ac9b8063136bd39ad01..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2705 zcmeH|`8U*k8^=H28G8s#$dV;QmWD9d!q}ILY@yWHhKaK8;;Y+Q*6fVjqd|qS6xkp5 zWSOEw)SZmTU6vTTNb-38jOU#DI_G*{=XKt{z0docE6vu%jE75v3jn}lVQy@9c;Wvo z2l7xir*n1zKy=$$JD42e!N2ow0{@>0jEo|(4;#D?YG-2)0E9rYu(GjpaB>~t=HWfc z$1iXUbzD$L_=Je4nD|KvNvTsZvT~>870xIsDW65Fs-08U#GKdC*3s3wpl@J^H8M6a zH8Z!cw6eCr*iv<+I76Uho=|8$Cr4+&;RDFz@Xre(6I1`$f)R;*xPaN zoj;OO)9&6&&&bTmxu2VtUr<<7TuLf?Q2r;m;vuE7s`}C6CpEQo)cS_Trl-%ETb{SJ zwRd!O|EGucqPMS~{_@q}>o+5#@5aX8fB5_3#HUHd=joX*v;TbkHaEYp_8BO)`+EJ*nz(!9{|HuR#l;Iz;U z^xzI!pD68k2-3>GNjEr3^#jcj4Y4UmUvh8x_~k3(X6E-7syzHOBq|PytoDPi<;j$- zUKHzblL@GYqAFEgc|nU)DR%u@{c$yHC4ha?orMio%TjjUPaKl;WjK;{r6$*LP_Gi; zN1vWvtGBM43TQ?F>*!=0hf~{5n7%wKSQ^KXl5RU|yRA4f&V5jSY;Hr?<(NSLepD>(o)k(U)=@SWjw=93iQ;Dt`b*c1 zhVb?5me6V)8R1`@r@CSefkxM@B}E4QOkK90s3I%4G~7Zq$}N4=x2dfKG+*B(Wu)(r zsua)g7*PNmg?!Q%>V-dL8`VlKE&Qjt?KRq=oU(-kG=f=)EG>KZU9yCc~GN(yGhok;%j5cjKB0PW?8~gq@CR z6&|BsU+)bI0siiYbZj+|!QXe{^ESrp*G7Uh`0%3r3Ac(e(=mKUvDCClsKR3?>Ef01 zy$#6CX=SruALq#M7uVN5NZ>ZSL97+;RIEIvzx15Kmh4?s9@fos?GbB*8u{IVU%#3X z1xf$J$Us~;Y-4wjYBC_p``=Ksr+eweU-%-X%G46|+ zBOa_*qVE|d$&}A}UpSwaT~8n_FAyingR)YM?R!H!I6<-!Ics?jkYn{sLc3Ihdb1^Yw@0nV+B1msiL0x3z)?eA#LRe*=!g0RWYiPN~9 zwMmAVhJwXjLZ7B5yI^!uW4HX&y_JQg`O%l#e+*CX07>zybDuN+3AlV@fW$0R;S3e( z32r@DEZ?9J*RY;U)0z8g;%welNQO>>aC;3qt>qOdZLGf3?ub+;srt4iA$O|$&H9{K ztL%pqnb+Gszb5zVWUJM2B^jgp?_F}3*$z#H0$4U&(KRv_Im8M;LkC!x*cel>_&fgv55PoG diff --git a/firefox-ios/Client/Assets/TopSites/youtube-com.png b/firefox-ios/Client/Assets/TopSites/youtube-com.png deleted file mode 100755 index 9e54c0a698c2074684de93814c36a1f98a63d3b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1470 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H3?#oinD~={fpK$yPlzj!`+pP+sSx0w{>&B_ zZ4*j@{DOhe$i%|N!O6qR$1f-(EGi~0Atf!NprWd#sjXvZWMOG#@95<0=I-g`?Hdpn z6dW269g~=xlA4yCS5R0~TvA$AQC;8A*xc6MF=67Q$)^8`^kYa$Iq9q3E25GXvIpyyR%QlDtDflRV8v;>(iMD z>1))ad^ZIgD*N|DE|}}_*ISmyKYu-3`G42k>-X00op<{CCq);fi5@CKoi0thOVoC+ zIFq#5+`?+EUg`n!C98yIiOrikx3}hY+SFwUrauE+{s%=|RtqUTVZLC;oVk5$yUzxN zO{qP>|5o_KX4Bnle}gabYR&0=F{S>()tuATF$()@b^QA0{)niq^J*;K`}&H)wd!Ji zt~*gn*fv$9&u>_1?Z~ToG5418gJo@x|HU706fF27ydfuvBPZ$~S4x`(*TOUQOr;{7 zzhoJMCA<}KytpDXrLKB5+SxSjTXH~V-hn&Y928xb1c>iw(=3P;&p0Ylv4Za zOp9kQF~%my1t-XLSoUcOm`@Js^3vS+h%01bR7_*krAgmrt_^Ku(tVP7D?N#IuYD`$ z7Xj5;#)e1F_p@+n967DT5b!C;NA{(vat;%NIJ>Kjqnk%VD8qtBruF8+3c+uf7^dI* z#Kq#-;qH*H8FKE@9G4#~4C~k`Sd>!cg)d5`d|5n(vElOC?j1}Fk+R-EGJRgnanTF$QvyR8*Bn1R zJVbEV5%?*R#luQ~Tb6ecWDghSOFgv3#0u_?=TJ?zm;F_8V2f zddH$wU$xzRcO286@KeF5vg4!Z(q*^hEq*t#uG@6y*Sy`vT?Hm;)9-V>;B`K;_9pB4 z38vu_Hd@;Lce*f5{lJxZ^Gp8;m?}yt?%Q&HO^Hr$VuhreiBq6NTZq%kM2X9sOIhm! zI_*}u%7-oPe|=G0?1#4Wm!+b=Zt>L?cJABd8Xxy~{rlA)SXNC`mNB*#LKb9{( zUJ#$>w*2qB#mRfC+5C?_oof2+*fzc8(I0=bg_Z_gPAh9Zo2_}=cK5+&lD@M;t|rcR xFSOo$OX{uZ)Tc)++gWF;0uwYSUElb_Hs!}=!{t+q8h|;P!PC{xWt~$(69BC=fP(-4 diff --git a/firefox-ios/Client/Assets/TopSites/zillow-com.png b/firefox-ios/Client/Assets/TopSites/zillow-com.png deleted file mode 100755 index 930abb4bc702b75f0571c01e532aed036f3b890f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2234 zcmeH{`#%%Jeao&%|`~7;ne|UPq@)64tR>9gnj&tD9NJnDaFGYQLCxl}NJ~?RV;z5u(f{N=80)lRM>85P_uf0`x9uR#A38MKGBa+i^(&m# zCkH^wVZ15GIZ3IVvzH~h4(5_8+LYLw^5cjLJYxr(24>S{*bxM8$K_vcm1aLklxmD$ zj!3cuoAb#P8|iy{A<2H_Rj?1|z<#CO`vuRW7tc8OBy?C4r;XW^=>}Q0WMy?*2uBDwM%dpw3B$fx?f2T%?Z%spcl;5SG3w{4qIZEweE-%By5W|{ zD7b#@>>;s@D`3gR0tR=-N`J@j*P26gtQ0_*A%Q6@hySoR$F7bv?Y+l5L_J{9t0XSs z`u?<*;pgUB#g$4B>Xn;Ok|UBjlaooNME=L=-iW+2qTGKFi=|t!sC^%pd!LT|@u11M z`lnQC8Dw}l2Ei1o3ZSQMwgL*4P^78*oL?!He}7bg)>H&v)yDl{4-QzTL;MM|{d(;Z z{dm)m#IPyF%8d1!Cj=e`Zds_%R^}(X@rX55^-0mbkDpv(fqTR4_{bf)XII8DE(Lai z)#w_Q=0qg9PYVPa>VZ;)-h>;vaAg5BpA~OZ;n2vkYPTqZClPsMIB|4|+N^tBD^}ui ztrMj~ykSf4r6P?tTNJPT{UJLDs+l+&^k%;xcSOhQWAwvvoXkKrl!j5;B_LB#$6wDw zigWX298B7D*%8R|V$ho@5B3c3C`W8l6a`S*Wt*MfEUanIei4JySg>x;FK)W()_f*S z$PZm|LhqF$po$Hnokoyvp6`kYqH{JP&%EYOa69dstkkFpV%2(4MbbXR3?s?@(s1fi z?qMi%dFH;vqZtz1fLtu~Eo>jGl_PQ`g|1_p^sqG;L7a>d>S|4GB7TQFSsXa;)Ft*K zh)eQiz#XoZvTtyaIG1K9Q`F@ez*(b6d|87-^>Cu4*zn1U06H<;cF8vBOkq+BHQ&8E zp#~7dzCA+zm_lI%#BxCA^b@@`1r7iB@C!)c5JRkC$xx0o(TKge0Jr5DS9(%H!r}6qZPd-#oe< z60lDLucM-`@Z!^Uai_QBTf(X|+W88I99c~XVwz^TD+WT zU0I67q95YIpB}-l_BYhN(z-O_g@ETlHZCK^zTm^no16yIn^JFuv>)-N&aN29)6?ME zsdi{$X#^lX=@@J(>Ds5Q8Hh?eK2v+>G4p<@UJ*)%_PJ3!nqC1~n_X3;g!(_@obHtS zS#^YOa0a@WcP-XuTE^CBL}4mWo45K(N>o#GDjYp{_1w1*vfZJqS+}+2}9MMI)m*LE PinnedSite? { + var suggestedSiteData: PinnedSite? { guard let url = self.url else { return nil } - let pinnedSite = PinnedSite(site: Site(url: url, title: "Google")) + let pinnedSite = PinnedSite( + site: Site(url: url, title: "Google"), + faviconURL: Constants.faviconUrl + ) pinnedSite.guid = Constants.googleGUID return pinnedSite } @@ -72,7 +80,7 @@ class GoogleTopSiteManager { // Once Google top site is added, we don't remove unless it's explicitly unpinned // Add it when pinned websites are less than max pinned sites func shouldAddGoogleTopSite(hasSpace: Bool) -> Bool { - let shouldShow = !isHidden && suggestedSiteData() != nil + let shouldShow = !isHidden && suggestedSiteData != nil return shouldShow && (hasAdded || hasSpace) } @@ -82,7 +90,7 @@ class GoogleTopSiteManager { } func addGoogleTopSite(sites: inout [Site]) { - guard let googleSite = suggestedSiteData() else { return } + guard let googleSite = suggestedSiteData else { return } sites.insert(googleSite, at: 0) hasAdded = true } diff --git a/firefox-ios/Client/Frontend/Home/TopSites/PinnedSite.swift b/firefox-ios/Client/Frontend/Home/TopSites/PinnedSite.swift index 7845fdc2f411..c05c23ee66ff 100644 --- a/firefox-ios/Client/Frontend/Home/TopSites/PinnedSite.swift +++ b/firefox-ios/Client/Frontend/Home/TopSites/PinnedSite.swift @@ -7,8 +7,10 @@ import Storage open class PinnedSite: Site { let isPinnedSite = true + let faviconURL: String? - init(site: Site) { + init(site: Site, faviconURL: String?) { + self.faviconURL = faviconURL super.init(url: site.url, title: site.title, bookmarked: site.bookmarked) self.metadata = site.metadata } diff --git a/firefox-ios/Client/TabManagement/Tab.swift b/firefox-ios/Client/TabManagement/Tab.swift index b88eb258b107..11223178cc95 100644 --- a/firefox-ios/Client/TabManagement/Tab.swift +++ b/firefox-ios/Client/TabManagement/Tab.swift @@ -258,9 +258,11 @@ class Tab: NSObject, ThemeApplicable { private let faviconHelper: SiteImageHandler var faviconURL: String? { didSet { + guard let faviconURL = faviconURL else { return } + faviconHelper.cacheFaviconURL( siteURL: url, - faviconURL: URL(string: faviconURL ?? "", invalidCharacters: false) + faviconURL: URL(string: faviconURL, invalidCharacters: false) ) } } diff --git a/firefox-ios/Providers/TopSitesProvider.swift b/firefox-ios/Providers/TopSitesProvider.swift index b83780c3435a..d3b1fb90c043 100644 --- a/firefox-ios/Providers/TopSitesProvider.swift +++ b/firefox-ios/Providers/TopSitesProvider.swift @@ -129,7 +129,7 @@ private extension TopSitesProviderImplementation { // Fetch the default sites let defaultSites = defaultTopSites(prefs) // Create PinnedSite objects. Used by the view layer to tell topsites apart - let pinnedSites: [Site] = pinnedSites.map({ PinnedSite(site: $0) }) + let pinnedSites: [Site] = pinnedSites.map({ PinnedSite(site: $0, faviconURL: nil) }) // Merge default topsites with a user's topsites. let mergedSites = sites.union(defaultSites, f: unionOnURL) // Filter out duplicates in merged sites, but do not remove duplicates within pinned sites diff --git a/firefox-ios/Storage/DefaultSuggestedSites.swift b/firefox-ios/Storage/DefaultSuggestedSites.swift index cec47fcb189e..c7746469f579 100644 --- a/firefox-ios/Storage/DefaultSuggestedSites.swift +++ b/firefox-ios/Storage/DefaultSuggestedSites.swift @@ -37,83 +37,65 @@ open class DefaultSuggestedSites { "default": [ SuggestedSiteData( url: "https://m.facebook.com/", - bgColor: "0x385185", - imageUrl: "asset://suggestedsites_facebook", - faviconUrl: "asset://defaultFavicon", + faviconUrl: "https://static.xx.fbcdn.net/rsrc.php/v3/yi/r/4Kv5U5b1o3f.png", trackingId: 632, title: .DefaultSuggestedFacebook ), SuggestedSiteData( url: "https://m.youtube.com/", - bgColor: "0xcd201f", - imageUrl: "asset://suggestedsites_youtube", - faviconUrl: "asset://defaultFavicon", + faviconUrl: "https://m.youtube.com/static/apple-touch-icon-180x180-precomposed.png", trackingId: 631, title: .DefaultSuggestedYouTube ), SuggestedSiteData( url: "https://www.amazon.com/", - bgColor: "0x000000", - imageUrl: "asset://suggestedsites_amazon", - faviconUrl: "asset://defaultFavicon", + // NOTE: Amazon does not host a high quality favicon. We are falling back to the one hosted in our + // ContileProvider.contileProdResourceEndpoint (https://ads.mozilla.org/v1/tiles). + faviconUrl: "https://tiles-cdn.prod.ads.prod.webservices.mozgcp.net/CAP5k4gWqcBGwir7bEEmBWveLMtvldFu-y_kyO3txFA=.9991.jpg", trackingId: 630, title: .DefaultSuggestedAmazon ), SuggestedSiteData( url: "https://www.wikipedia.org/", - bgColor: "0x000000", - imageUrl: "asset://suggestedsites_wikipedia", - faviconUrl: "asset://defaultFavicon", + faviconUrl: "https://www.wikipedia.org/static/apple-touch/wikipedia.png", trackingId: 629, title: .DefaultSuggestedWikipedia ), SuggestedSiteData( - url: "https://mobile.twitter.com/", - bgColor: "0x55acee", - imageUrl: "asset://suggestedsites_twitter", - faviconUrl: "asset://defaultFavicon", + url: "https://x.com/", + faviconUrl: "https://abs.twimg.com/responsive-web/client-web/icon-ios.77d25eba.png", trackingId: 628, title: .DefaultSuggestedX ) ], - "zh_CN": [ + "zh_CN": [ // FIXME Do we still want this as a special case localization? Android doesn't compile this vers. anymore SuggestedSiteData( url: "http://mozilla.com.cn", - bgColor: "0xbc3326", - imageUrl: "asset://suggestedsites_mozchina", - faviconUrl: "asset://mozChinaLogo", + faviconUrl: "http://mozilla.com.cn/favicon.ico", // FIXME We need a higher quality favicon link trackingId: 700, title: "火狐社区" ), SuggestedSiteData( url: "https://m.baidu.com/", - bgColor: "0x00479d", - imageUrl: "asset://suggestedsites_baidu", - faviconUrl: "asset://baiduLogo", + faviconUrl: "https://psstatic.cdn.bcebos.com/video/wiseindex/aa6eef91f8b5b1a33b454c401_1660835115000.png", trackingId: 701, title: "百度" ), SuggestedSiteData( url: "http://sina.cn", - bgColor: "0xe60012", - imageUrl: "asset://suggestedsites_sina", - faviconUrl: "asset://sinaLogo", + faviconUrl: "https://mjs.sinaimg.cn/wap/online/public/images/addToHome/sina_114x114_v1.png", trackingId: 702, title: "新浪" ), SuggestedSiteData( url: "http://info.3g.qq.com/g/s?aid=index&g_f=23946&g_ut=3", - bgColor: "0x028cca", - imageUrl: "asset://suggestedsites_qq", - faviconUrl: "asset://qqLogo", + faviconUrl: "https://mat1.gtimg.com/qqcdn/qqindex2021/favicon.ico", trackingId: 703, title: "腾讯" ), SuggestedSiteData( url: "http://m.taobao.com", - bgColor: "0xee5900", - imageUrl: "asset://suggestedsites_taobao", - faviconUrl: "asset://taobaoLogo", + faviconUrl: "https://gw.alicdn.com/tps/i2/TB1nmqyFFXXXXcQbFXXE5jB3XXX-114-114.png", trackingId: 704, title: "淘宝" ), @@ -124,9 +106,7 @@ open class DefaultSuggestedSites { QIHUV9bCUkQAF8LGFoRXgcAXVttOEsSMyRmGmsXXAcAXFdaAEwVM28PH10TVAMHVVpbDE8\ nBG8BKydLFl5fCQ5eCUsSM184GGsSXQ8WUiwcWl8RcV84G1slXTZdEAMAOEkWAmsBK2s """, - bgColor: "0xc71622", - imageUrl: "asset://suggestedsites_jd", - faviconUrl: "asset://jdLogo", + faviconUrl: "https://corporate.jd.com/favicon.ico", // FIXME We need a higher quality favicon link trackingId: 705, title: "京东" ) diff --git a/firefox-ios/Storage/SuggestedSites.swift b/firefox-ios/Storage/SuggestedSites.swift index 2597c4e5a5eb..d2e6ee5ef9f1 100644 --- a/firefox-ios/Storage/SuggestedSites.swift +++ b/firefox-ios/Storage/SuggestedSites.swift @@ -9,10 +9,11 @@ open class SuggestedSite: Site { override open var tileURL: URL { return URL(string: url as String, invalidCharacters: false) ?? URL(string: "about:blank")! } - + public let faviconUrl: String let trackingId: Int init(data: SuggestedSiteData) { self.trackingId = data.trackingId + self.faviconUrl = data.faviconUrl super.init(url: data.url, title: data.title, bookmarked: nil) self.guid = "default" + data.title // A guid is required in the case the site might become a pinned site } @@ -38,8 +39,6 @@ open class SuggestedSitesCursor: ArrayCursor { public struct SuggestedSiteData { var url: String - var bgColor: String - var imageUrl: String var faviconUrl: String var trackingId: Int var title: String diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Browser/TopSitesHelperTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Browser/TopSitesHelperTests.swift index 769930f1499f..14852e75f05c 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Browser/TopSitesHelperTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Browser/TopSitesHelperTests.swift @@ -162,7 +162,10 @@ class TopSitesHelperTests: XCTestCase { let expectation = expectation(description: "Expect top sites to be fetched") let subject = createSubject( mockPinnedSites: true, - pinnedSites: [PinnedSite(site: Site(url: "https://facebook.com", title: "Facebook"))] + pinnedSites: [PinnedSite( + site: Site(url: "https://facebook.com", title: "Facebook"), + faviconURL: "url-does-not-matter" + )] ) subject.getTopSites { sites in @@ -182,8 +185,16 @@ class TopSitesHelperTests: XCTestCase { // MARK: - Tests data extension TopSitesHelperTests { var defaultPinnedSites: [PinnedSite] { - return [PinnedSite(site: Site(url: "https://apinnedsite.com/", title: "a pinned site title")), - PinnedSite(site: Site(url: "https://apinnedsite2.com/", title: "a pinned site title2"))] + return [ + PinnedSite( + site: Site(url: "https://apinnedsite.com/", title: "a pinned site title"), + faviconURL: "url-does-not-matter-1" + ), + PinnedSite( + site: Site(url: "https://apinnedsite2.com/", title: "a pinned site title2"), + faviconURL: "url-does-not-matter-2" + ) + ] } var defaultFrecencySites: [Site] { diff --git a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Home/TopSites/TopSitesDataAdaptorTests.swift b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Home/TopSites/TopSitesDataAdaptorTests.swift index 317ec29ceeb0..c898644fd067 100644 --- a/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Home/TopSites/TopSitesDataAdaptorTests.swift +++ b/firefox-ios/firefox-ios-tests/Tests/ClientTests/Frontend/Home/TopSites/TopSitesDataAdaptorTests.swift @@ -566,7 +566,7 @@ class TopSiteHistoryManagerStub: TopSiteHistoryManager { (0..

    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 diff --git a/firefox-ios/Client/Assets/TopSites/patch-com.png b/firefox-ios/Client/Assets/TopSites/patch-com.png deleted file mode 100755 index bdf24ac327fdaebc0be81de5e00c9efbc3c33d37..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3704 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 aLF!)yW4h3rJK#kC0000`h*|+3v@D}{v z0xmhde!~ zGCKl@wN)F9=)h-BfQKNnR3o*FXvBGwY+Es)12Pu+M$^p)KOh_EaRcbj=UVw6i8V%~e zROeC_U$R!OquFG4e`f0dGHGjyYpl;!4A#LxX@RlCwvr;cALi%ns}jKbh{7-Rg>h}+ z0MY<&*If8{7vs-9oxp>pP?I&7s%!38e|sZE7XQQvBp=U?16G|sPN_p==WQ{b?9D=L zNse9qCt^HAZkg#g%IUGuI#642$5f{56Tvb;tr_JTM?-nQQzBw4YKL=jQ`<4h!+M07 zFjduR(d?cVvLAWBRW7o9=Uh^7vcPooLj%HOnN^ukqV!q!9d%@i`bsNjgu>kMtg%BJ z^t2$!cM}4RDroM$)PC~yD=XuSv&Kf^$NV`3mvKb+R0yL5g(R}Kvh8;jBk^DIf8Qvz z$yN*xXOA#zJDRBAkMC!&{lna8Hrp{1b`@5lr+4SJ3V5Q3acOd8)uHlm`*~0tg4=bThS;)7%L&709O+~n9=V0Z~ zd1pl^+7GXs}NSKQtdmYjI4mm9v+WSr@)EwtLTd1`;!WKm1+o&gBsfHAwQ z>kr)gO@E!{yNkm#Pky`R^Q3R{505jbR=(>VG2JE8HwT(wGK(4cJmjg#&$8hIW z?s0L&v9}?JYKt3#3GhG&&)1eK8@Z~{h@~#5$LQRYvF)-6CS7o9t90qKdGQ3w&@vOb z8?as1pdZmIa8o7JA5HKLSi?*mx!r8gJUR`?2S(;py%6_AA4V4+Pl{j{+_v$qihV5& zrP;t1NY(5SRm)#fMVSe$;?91>vNG{1_98mzJI2{(1ORhD(Wv8x(is3=rm|4OG)RMC z7)^0|T9>+W{O(*OATz|ucY!%BPCt?j0_&&rR3Fc`Ew{AA$T6kfX+3yGWmI0C`PBr$}Ms2 zx-?^hm$|CR+Yx)pWBbvp<~b4al`ruxnES)`)WxA_j-T8&gNoZ~t{YLIEuBE}<;*QfxZ6*zzDu!*yaYx`GO;g`E6 zu+v`GN|x{_WABiYU*yisWA%mtU29^nldUSXIon6eDg+FNl8di{{oHrInpkCoteFpt|~j9Q9@I2jAx;rAk!SI~g$B|E3`f(u=|dv%cCVa^u)Hes?$s#P-=GXw|yf0PH@N`}TAb~?2LOpEUG!X zMnYXiGYfCsct)Hgo9$foZp;yJ*+f?RaxR36gRdF-z1&c`ojFgUwjEaOCb#^GBx#?c z%;PxI;rl431B(UPLhj${5GQQjkAyEy(j1Ea#CQC-!>7L+ttVST7GvMlYC=Oh0GtM5+h diff --git a/firefox-ios/Client/Assets/TopSites/pinterest-com.png b/firefox-ios/Client/Assets/TopSites/pinterest-com.png deleted file mode 100755 index 5b4a427ff71c99cfbcac70955b247af6f6e74841..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2941 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 diff --git a/firefox-ios/Client/Assets/TopSites/qq-com.png b/firefox-ios/Client/Assets/TopSites/qq-com.png deleted file mode 100755 index 764c93cfb2acc07cfe07d848cae3f5ecd8ecc97d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3259 zcmeHJ`8yMi1D>N;Nuq%JOC5|9Rv$Qps+)55z)h9 z2yqEXX&K}ZSvh$H#iL5fDynLzW5-XZpVZJqYiaA8(mk!GZ*bwV3NSV&md( z-l8VlrX}7!y|3TA?du<4u?L5SM@GjupwPrZfs(yVY;CrPP}u4vguP5aAWG)V`R4avmW@^SIyE>cIp>QdzA1d zXu%_-&c*MKu<7~Hvr(N}GKq1R+e(qf@8)cNL?NpUMz}_ypWc3?MqJ(DMP=%REhL%( z_oXnDLjK)z%`;le0LYZ%4BaLEVsTHETxYp<;89HYNLAb{#v%%PJ>>o__k;jv!NE3h z0^v1sr;22P>|R+%j6*`gD7gZQGv@{X5yAfQskOVq#h56bM(8YB5k6qHVQ|CnOp)Y%PfF zCI>YxSRW+MEL#iCxiy>E9Qm4o%sgNbh z3&HrI`)YLC;#V@mI`fCWe-_b2RPzbLs zJ7fz-4>Ej9+BADPE82g9I^4^OL?>P6s`i=XBbmL3c6y{de`hXn!AVGP6CLFRNnTo%VPr$)tWNg7I9TR+_0ZT*(Paq}o$AzMy{qWQ1bw`v>x3niO%()* zf*D$%MSTZCIT{w0_Kr{)1`*5hs^`p^MSRxE&)x*I4325ZyzEJ46*qQ6XmdO2s=($cmfc@kchL+Jh>U>E3@y@M3Z zJ3WkxHNY_})Yd=+kdhe_OR-@mv{H<0869A^;25NXYbN$k(pxt44g{R(`ujqE8J3wW zZA4>n-N5EApSEKeZZd*~()6xJkbE>yK>hZcN7>WDBSg-+QfZNIvEsE8B{S`CN=a@_ zddf^UpcV#5L2VrZ`H&f9x3nnJK?|-30O~Vgld1GlPqrbGPzc2W;u=HAP!Lh_B*EiQWsh^TfBZ8&chtE3ttcE~4Jw#wnZ1_nBzAa%9isM5x za0jAuojssAE#^&@uceQr-l{v{)&#PiZ7{Pq>p(lW`tz9jF3h^>{R$*R1EJD2F~npo z!E#W6&fpnin)~+B06aC(TIJ!sP*R1-$s1=`D!`ia2XmBkuOE3ils!O8)8Eka?7Zvd zyk}D9hffaV>JtGkELz>SEq5x{SPKx6&?#inm-Q9zFb6rcoV7w*01ZkcKdhG0igs9WFLs5!uXNN5@yN4ATGYXozUrlUmBWr>TtmVFk zCpvX+aR>#1hY=eO0CIx?X^pN{x=scxdZ~u*?uXbQFAqCRj`k;#Vy*T@C!iXvgsF{dwxKaM+Y-u6+wiL{i2;CQ@FYGO9I9u$FzA4iu0{6?fp)AS^ z>5FIhYydnL?xauJuKTJ^v2DaNl_=EX@sK)U9o5vFU48}<*e}ixH z(aK|)-YUx(b@X5ZR>X%l&fjXXGK4Xu+I> zsf{&CV4u*kvG#1D%~?g*pNnF zm!3>|FQh6KRZk9t_NZdS-~B}SJkYUiR1gzM8`nhMhndm|82{;-6jPbh8qzef6-t>a zJl8Wk&JHbRw`p8O>wJqqf$lP&|6~sCzw-kLVWG(w5^A3v`g-ZkS!eOkioeUyr>tBbFzU)}#% ijmO=KV z$vTM0Iz=W|vSiCzS#IyY@jmxF&pGEgzn*U&txrLA*L53g@<-q6VS zf{Cda!Q8^~qSf!#Hnw*54vv>DI}x2-TuE;3SFUX zBBIEYm^*i43mj38*#-EwgCr|(SJNsE~UVcGgQE|zO(h6E-RrSl7 z+PeCN#-`?$)>p6F+B-VCx*0vaZ~6z`4i3E=9vK}QpJ0BNoccJ;`ZV*;?B}^J^9zeh zUzb-_*VeynY;JAu?0*08b8r6uRgyIh0LOb%Lw(!O_bpl9UG0oS?oslcr9GXvp{-HQlR)6!cmR+KYK zC8{b8j<0!%!uU2fUf-X5&>k5X$>F6K!&K=mM_4pZ-~v#;odnN(E}Kbw91Lg)Xs0^IdmGhl1rBwF&~?*nH63bkzp z<+b^=+GcFIQ0@gPp$6-?2DSySef0X&-O~m|$2!f*zWJ&9Fx5H%s>hz9U(VO&+aa|~ ziQwf8bPP}7&!j1xeGSy}Y2>6>YYLTtDZ35Dpm);aHOM;XPM8QuZ>IHkWl(I0i;@7{ z;T;jl0hD8g0T=`tYxU_2GuW_-6K10SG^n;0Izr+b9Y@ofVe1OEANAJTK^rgBJhUu> z0wLzNvL)%(Z#1ZIdI=Z5f}JSHa|cVBfU~ih*#}rMb6VLPEM$Qgj-BS!LDc&MF* zJHTpggifmtctt7^b*GR7=?NSpo`P_FBu#*A{xzI-!ln!j_cnsGz5)3Q9%@*MZc!l{ zAKk!q+lQa7Jd$2Wj*P{y$Af`ZUkaZQa8T;LP6Req6fP{dWz(3(LxORmWnuOEjnKLL zeV$zqQ*;mrflJ#umZImneX(Z;km|bJi=a-!4PKjSlvez1&8T~~*Q zHSYzxgl}&Coinb4lwdb`TiJh?Y{%Z{@?t}*!*>U>*S~Omh9BS&bMoPuP2azuyR~0v z-v>0|C8{(S~m41*i7YdW{E{Q!TreaW1p)U z4jQ;#4yk2eEOD^$M7K=*9sjH+?&OTke6ViXiF{0#BpOwmAAIxVb8wqsd$nH+QGsf7 zpucjqe+Eht0wh(J(VVV(tBK~0!?=OOF1kguRM~l}2&FTsByYdn0jw!SOJM=-F#6QS z^!SH;C|l&^m@CqAsv=bJnSD$SJy>P0-J~b*{9CPz^GC;#TrsoU??+pvh7_731)bce z7uBxZaCn@6r1(G+zUoH;JjJUa`3zlMaRj?eNU3tnxfI7Ade71nNsbo+2XId7G4kW5 z1%(7}DxE9$zrfYCRP6Or#%eTGQYKD?Qo^4J>6C-UUHs`2MGLmLepDyY7_7tf@}nrmRn92-u4AU~9IgCtlh4bgYl zHe9SW3}=id03%@SpWbCQuOdsr4tY4121{LFW!W8F2JwlHq7QLAL$v4iuL^S}hBf^J zlT9|We{*(9%-Cv_nyx!=oX|#QRsB%=?KzS%v20+sT4>xa@^!9ACL?(&3g)mUAGD6W zFUux@duh$8tE$5sQrJN%wIgm@KV#L_m~u{#fy3D>Ivfk?>{`H9{|}#GEfo z+L}ZpAU&MYQhB~P=uFx?(S*eGR79A2bJNMg#DK7ny5w{`F=g!X=~R43f45rgBR)5$ zChJt?viuK(8;V*?%l@LzlCmP>XC$eLzUgG7d;Q{PrH#Qr)ZGNvmPt{+OB36aqTcxB zsw^3abHXP$_mgIsA3lrR4=eTXuAph<3sB^f_({UbXYgO#3l6sS6M6Ani^uvJnRDS8o(p%kUdkyegYc~t58SbG85s_VyrqyewvKm28lD)8OEqc$U8wHSbjN32 xMM^5OGnJMnHBRVV>LZkAn-JAUU?%+s@U^(kIPu!vv|k?wm>O9cmK%^_{sm&Z1=0Wj diff --git a/firefox-ios/Client/Assets/TopSites/realtor-com.png b/firefox-ios/Client/Assets/TopSites/realtor-com.png deleted file mode 100755 index 4c4948cd579e3612d3bb825fe91803106e8d84fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8979 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

  • )f zoYEUcMxRhHqIVT80^mC)5-erl{fWNo>}}^SuONUFFfT+Fw1I~T*q*%OnW;2q0;8En zc^*Wmo6_+kg$jK!CZ?Q#s#=!%yX5Y(-$%2Hr#b)J8qtA(a%8j6VS|i?W%CQAQ;nG1 z5i=-YY32JWB_f&RDPj>=CZ&u7H$y%w4+9z9>oVUYYbX=() zL6pM4vU=NfJywcD`$I$j@Jo>CBJqjCpDvg;5?xb^y^aqg0ajFEKp;}CmFsY-#CzHe zJa5PChnUjv{<&}!;$txaE3fl^&b+=OP2)a2RXqI!l+QTT%)2x~Mk9icaG6`LIDt(^ z$R@YS=llN13W7H?sAOHUo-N{i(8@Id1I_bdOm|2{?eOEjTcH zDU#f0Y)I9$TvQ*Dmyq3Oo$W%e_8ocXJPLRP|%Y}+Pgk&H} zC+Bfs{d)3)x(gsUGDQ%8wktX$t6SQ}@-Qm4S84eL1h1rms$KdC2W#%u?FOJcCs1NA z0E)-(KVgM2jMX{?(xB7Bv4qI}R*`8qFmF>hx(vcpbRik$->v{smvpB0?xB>5h*2R0;Ea(1^sa55 z`EG+7kylR)IJrH6t4Hk}9)}ox9X48m;$<42`>b6F-vZ+5tqUfa#BGJ9K{C3Ijkt^O zmCcFac1bnbke5eAQ@U0=l~oy2d4*@0Hn#2BC7f1v9`NM9>*Hw)E#)`^GTsyxc<+lTB0SUyN&3gZ1Lqp)<803v`5W`fMn_r zQ|WzY>g-x&^JA$Q38Z#>Y_**o*aiz1dO8jVj7hEuwWv7}KtD%1%abJOq9mqTB~y+` znnr2SK^oobxDF{*(nKtzMrb|oyydAV9Jb6v$6x~5#wCv(6{h>al zMBjuZy&kor+H6?JHN;+>8>x$^P_8^AAR?FyW8Ai7?sL%nMw)!tWQ?$~afci)*}T-- zvfdzhh)LX0OG!6R7%O4>M_`MmXx=K0N(b6$2XsgJI2D}A^2PsiO{ze6>yeIx)xw>& ztOZdPC_eN(b~vWwzB5PKDpApc=$7as$>Q4KOO3_~(t@s)#-Y=gwr0*;qx)ZUo$oQa zJv5RI#dbQj2v}*J0a(n{J#-?U9KW_k8Bc&3U}%eS-!8Uc=a z6KO=W5!_Lo4bCQ;^zoJX{mgs^&rdE#h0B8o(mD8UuImoRNl6m-B8?-4wnE1vR6Y4> z(oPwDA`H(}sw~zmnDLNl$*+>sRuJ^8b3s;@ZeiCikq%$k=*to(G}%JI3z; zFpB?Hr)B5)Qgwat-M-fTj<4oLkc=h?SC$Pxdb-!f@*|p;6es4U?)ID+_#D83jE3O9 z2qvW0T(-Y3DTJAu%2E2Jh#}t+gXeN{Vl`SW(rc-`3m9omz?TzR$az!FQ6F# zw``!u6ZWYvp51;cM?Umf!0odbSgV$T)?Q%LgKe;+$OCRg)4l#Y`4Ab4r?VquFR%l` zoSx2g1j+_2XI`q`nR26%1a>De3pFCQg;^Xfqg;*eLGJ_U*CrlY;sM$cg@zBZ>!>uA z5NesF;HiD$_K955`y}P&3j8CG@svC=`Q>882K#rWKRoE)e#+y6RqJV z?lk#~)T*QqrPmI5VRo-q%}xy7bXDiegL1;pqru6QGI71ni)oMPp&B=IQbFv>$|+)1 zL-KY8=MV)UEEE*=i^mK|*JO`FkG=G8*=dgUo^Xe+57-^kYiFuKCYVIP;M++ z2U1m&4-w;%Kh9Op#-tyca8>+nxTfjwwIF0=+d!&&WU<$}4k>oe*YK&8CQvrpu8iMx z<(hizm$s$EWKdM_d#q#pCWS~vbrStvSvCDxJ$D25z)VJG4HvLd>3X}$eeGlkCf6s% z|E!c)9eU+Kz((|wxAhox+?2^NE(JAltC(FbdihG>;EeY&7e>E*QZ(p;h5wcFGA)0g wr>lX1`VYN>?aP&r{1<=U<7=U@tp0eSp@mu6ONmdX{(U9j2F6gkRLd^xza?rulK=n! diff --git a/firefox-ios/Client/Assets/TopSites/dailybeast-com.png b/firefox-ios/Client/Assets/TopSites/dailybeast-com.png deleted file mode 100755 index 5102bef549c90972c512481e5b7fdcf3de90d911..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3035 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 De$EI0 diff --git a/firefox-ios/Client/Assets/TopSites/deviantart-com.png b/firefox-ios/Client/Assets/TopSites/deviantart-com.png deleted file mode 100755 index 41347d31adef71bb302e80842ce10564a0ebe340..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1048 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 diff --git a/firefox-ios/Client/Assets/TopSites/discovercard-com.png b/firefox-ios/Client/Assets/TopSites/discovercard-com.png deleted file mode 100755 index b9feba07c056ff84b3e1be948f8338ca12a7cb2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6251 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 VI70%LCh!0N002ovPDHLkV1iyB3akJC diff --git a/firefox-ios/Client/Assets/TopSites/dropbox-com.png b/firefox-ios/Client/Assets/TopSites/dropbox-com.png deleted file mode 100755 index 22fd13b491446d3ce1725c110b1a82cab0774bf6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3406 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 GzyBW?9OV%J diff --git a/firefox-ios/Client/Assets/TopSites/drudgereport-com.png b/firefox-ios/Client/Assets/TopSites/drudgereport-com.png deleted file mode 100755 index fbdd4ef0f13bc2116523a41d4f9165e23ee58ed0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5752 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 diff --git a/firefox-ios/Client/Assets/TopSites/ebates-com.png b/firefox-ios/Client/Assets/TopSites/ebates-com.png deleted file mode 100755 index 4fe8c7ead51b894d57decebb0e334e50a01f84c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7035 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 diff --git a/firefox-ios/Client/Assets/TopSites/ebay-com.png b/firefox-ios/Client/Assets/TopSites/ebay-com.png deleted file mode 100755 index d6f8e6acb2d8d924a60190655e311b5129db9c00..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 929 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H3?#oinD~={fsr-9C&U%V9ibrQQriykr$!cE z*E79*P#pmbg`kokzhGdvu(9*-3J3{{O3TQ~DJiSy=owr2_yvcAh9x9sWas3TR94m2 zx3qV3_Vo5oSh950>b2VsA31UI^qH&IZ``{5;NjyZPhY)$^Y+8XPhY?N{Qc*z*QEpX zz~KJr>EaktaqI2O>tRfe0xr`P4l;Bpty?4{5)c^Jv_e8qMPdQ(|Nol%zUiDeXSDfK z!qwvNud!-h<}@ezEM+a;U-I*Yx{}f>`?zV}&ayr}za=c^f`n;TcKt=$2|Jg?m(Jzf zamQ}P>kBTWMULXPt0(1d3blS&xca|W?~;({vgQBN`cVaafzS332qI?-#vaep}_buap&01{w#GL2whxRaYF7d+`rE=31Z*6rm z|E_dx(TTXrQCEAjZZU+uj-CFgfA#0(Yrdz1o;UM|N;-dde`woz-KDpqp80#9kXfQG zy8K@2qiKC7rwA*>3r}8sJ-+4BoT~qpiU0V7%D#3s8qB?VpI!1{_oZ)bTM|xa$TvpI zm8&INKJK%=+AQ!q^ZaL{X%jYNKki~UZj%#!Zu4PV^)7}#e}6xi`nf`W#!I)g|CRpF zShGg^bgcKSV;2IfvO4{j>8du^c&|Er`_-9g;Y=Evmo)8JdmtxOwLyDYir@C4a4!ab z9Zj|TZo}Jqg&gLqwm!{GtgF^!{P6k7gPE_Bx0$o+rYXYngF$tJzI5%47q{K!n=!#f m@h}Xk8U7T5@*D#Escw+(o$#(v;lD~INYvBS&t;ucLK6VCVkKq( diff --git a/firefox-ios/Client/Assets/TopSites/espn-go-com.png b/firefox-ios/Client/Assets/TopSites/espn-go-com.png deleted file mode 100755 index 0322d3d1345b9be155cc8d80f89054ba4a4c0c91..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1521 zcmX|B4K$N$9Dm-~h9M=&t>kT8-Kq8&X0NZwR-9$GBSlKuW+ApQW6KS%l<0%Hom3}o zyKW-nrkk!S)jD=mS45XgP3TsZtT=V054kUOdd_+N&;RTEe&_%HKhIOJUbxndw15Nv zunP(1g<&T;y{(9tZ1xwm0ssjT!Xs6Yq3aNdLPitCD#TKnMwX1l0q_mbB#R`8QWY$g z#wE!8$gi*7Aj1iPns81!d&GIvpF=TC&!!Ru@Yu6 zm|k=ShtBk%GMEU1gD{xz*G2Xx!M@7a9Y`2&%~vwa@*~HqRLKaPu2!pQ>Qyv_GLFvV za5!`Zi_T(Eu?%YJF1bpip~_R2PD6ab;7L;@%7kQ9fi9{r zD{w8Iv>H=w^PXBb&`L_nFKP`PwAZXJw;dCgL&2U^v)Nk+S_L0!AQ)>m7Bo)ZGtz`uG^p2mF`khr^}aL72WAC9E5xCGF~;}HtG{^Z8~m_skC_eLOexg1H{_#v^nM}et@Mhor1@|?*^5);DQfI=L;vlZ zWBI6={UEC>8{ZUBF)t-~*F?+a!JxA5y`y_xm*6@$1Z^sbJLHJAyMxjV0I2{fA!Pa* z5YUO4hh7m5jkpe&q-V;Z3DQJk6i3;Ywc}~P=zTXXdyjsH#HW}DZ*&i8G8kqNwD$8c z8$aMOAiox+&pB+4bU^VX-BrA;218*vbi{C=7`QhOYL%fH8)#MtC~ZT=MbRxt-Gd6J>7Peq!OhbLs5_ z?pjcH4SYViKppsty*Tb^m_)X+%!s zq}|Ke|CnD=8TTfr#R8k$*o_Z^{nL zZrapNAG8=~m7RkHgerpD%H60TNzTB;(w(SHhHQVAw&8cK(l(H5mjYYbbo^!Doh!cOH0NLiu zoOJ^3mS1X08MZpvz+^^!es0;UnR}UJ-YWts2g>#Ch+ro)y@{9=<&)qH{G2?lRE!Am z7g)AvArQAVt_^d=JrZ$_Iil&2?PoKAyw1lSPI00_)9*yDT;>kUw;Kf+uAtN+-)u+X z_Rw-7ICJaqmzR7Lu!e!`qOkyzw?ChIo7eXayz0VcANfje*GTNZwU#ynnr{&J0&Z2r ze(ySC!9o>&c3~=|?^FXY*g~(%fM_EQ)lS0aR-GAY}?mW-=oO9lu=kuI+mi<8jRs{pdt!xf5ZSCxjvK$