From 6251b7018b472a795af0fc69610c79f0fbf18977 Mon Sep 17 00:00:00 2001 From: Alexandru Farcasanu Date: Wed, 25 Mar 2026 14:29:11 +0200 Subject: [PATCH 1/9] =?UTF-8?q?FXIOS-11802=20#25742=20=E2=81=83=20[Autofil?= =?UTF-8?q?l=20and=20Passwords]=20Saved=20Address=20bar=20in=20landscape?= =?UTF-8?q?=20mode=20displayed=20black=20margins?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- firefox-ios/Client.xcodeproj/project.pbxproj | 23 +++-- .../Autofill/Address/AddressListView.swift | 11 ++- .../Address/AddressSettingsCellView.swift | 98 +++++++++++++++++++ .../StylingViewModifiers.swift | 64 ++++++++++++ 4 files changed, 185 insertions(+), 11 deletions(-) create mode 100644 firefox-ios/Client/Frontend/Autofill/Address/AddressSettingsCellView.swift diff --git a/firefox-ios/Client.xcodeproj/project.pbxproj b/firefox-ios/Client.xcodeproj/project.pbxproj index 6bd562af0be8d..1b48164c58ff9 100644 --- a/firefox-ios/Client.xcodeproj/project.pbxproj +++ b/firefox-ios/Client.xcodeproj/project.pbxproj @@ -61,6 +61,8 @@ 0ABCD45B2D355260005D704A /* TermsOfServiceTelemetry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABCD45A2D355255005D704A /* TermsOfServiceTelemetry.swift */; }; 0ABCD45D2D356015005D704A /* TermsOfServiceTelemetryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABCD45C2D356006005D704A /* TermsOfServiceTelemetryTests.swift */; }; 0AC0F9482E3CA17900E826D8 /* MainMenuConfigurationUtilityTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AC0F9472E3CA17500E826D8 /* MainMenuConfigurationUtilityTests.swift */; }; + 0AC4BA3B2F7289F200ABEFDB /* LLMKit in Frameworks */ = {isa = PBXBuildFile; productRef = AA93B7142F6D95D6002E5E88 /* LLMKit */; }; + 0AC4BB712F73DFA400ABEFDB /* AddressSettingsCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AC4BB702F73DF9900ABEFDB /* AddressSettingsCellView.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 */; }; @@ -779,6 +781,7 @@ 74821FFE1DB6D3AC00EEEA72 /* MailSchemes.plist in Resources */ = {isa = PBXBuildFile; fileRef = 74821FFD1DB6D3AC00EEEA72 /* MailSchemes.plist */; }; 7482205C1DBAB56300EEEA72 /* MailProviders.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7482205B1DBAB56300EEEA72 /* MailProviders.swift */; }; 74B195441CF503FC007F36EF /* RecentlyClosedTabs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74B195431CF503FC007F36EF /* RecentlyClosedTabs.swift */; }; + 74B8478AACB3429E827FE642 /* TranslationSettingsDiffableDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0865C80F73A49F08E2B17E2 /* TranslationSettingsDiffableDataSource.swift */; }; 74E36D781B71323500D69DA1 /* SettingsContentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74E36D771B71323500D69DA1 /* SettingsContentViewController.swift */; }; 74F80D342A0A52D700013C3D /* PrivacyPolicyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74F80D332A0A52D700013C3D /* PrivacyPolicyViewController.swift */; }; 781C19CF2A780BEC0000DF46 /* Common in Frameworks */ = {isa = PBXBuildFile; productRef = 781C19CE2A780BEC0000DF46 /* Common */; }; @@ -1308,6 +1311,7 @@ 8C51ED702DE0A4D700B3E58A /* OnboardingKitCardInfoModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C51ED6F2DE0A4D700B3E58A /* OnboardingKitCardInfoModel.swift */; }; 8C51ED722DE0A5B500B3E58A /* OnboardingKitViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C51ED712DE0A5B500B3E58A /* OnboardingKitViewModel.swift */; }; 8C51ED742DE0A64D00B3E58A /* OnboardingKit in Frameworks */ = {isa = PBXBuildFile; productRef = 8C51ED732DE0A64D00B3E58A /* OnboardingKit */; }; + 8C5E7E932F6B3C3F00A3DD27 /* TranslationSettingsDiffableDataSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C5E7E922F6B3C3F00A3DD27 /* TranslationSettingsDiffableDataSourceTests.swift */; }; 8C61A2812F3371330021C88D /* BrowserViewControllerKVOTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C61A2802F3371330021C88D /* BrowserViewControllerKVOTests.swift */; }; 8C6AF26A2D38FB1500254698 /* GleanLifecycleObserverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C6AF2692D38FB1500254698 /* GleanLifecycleObserverTests.swift */; }; 8C77849F2DF33707001FB8B0 /* OnboardingService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C77849E2DF33707001FB8B0 /* OnboardingService.swift */; }; @@ -1400,10 +1404,6 @@ AAD1CD872EAABA8100BEC90A /* TranslationsConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAD1CD862EAABA7C00BEC90A /* TranslationsConfiguration.swift */; }; AAD861A82E9E748700F6E0E0 /* TranslationSetting.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAD861A72E9E748100F6E0E0 /* TranslationSetting.swift */; }; AAD861AB2E9E75AB00F6E0E0 /* TranslationSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAD861AA2E9E75A100F6E0E0 /* TranslationSettingsViewController.swift */; }; - B326EA470451415F90D8F722 /* TranslationPickerSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F84988A6047D42DBB38FFAC1 /* TranslationPickerSettingsViewController.swift */; }; - 74B8478AACB3429E827FE642 /* TranslationSettingsDiffableDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0865C80F73A49F08E2B17E2 /* TranslationSettingsDiffableDataSource.swift */; }; - B63BC8D134524B98B781AE4F /* TranslationPickerSettingsViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BD90845183467AA5B28FDD /* TranslationPickerSettingsViewControllerTests.swift */; }; - 8C5E7E932F6B3C3F00A3DD27 /* TranslationSettingsDiffableDataSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C5E7E922F6B3C3F00A3DD27 /* TranslationSettingsDiffableDataSourceTests.swift */; }; AAD861AC2E9E75C000F6E0E0 /* TranslationSettingsAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAD861AD2E9E75C000F6E0E0 /* TranslationSettingsAction.swift */; }; AAD861AE2E9E75C000F6E0E0 /* TranslationSettingsState.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAD861AF2E9E75C000F6E0E0 /* TranslationSettingsState.swift */; }; AAD861B02E9E75C000F6E0E0 /* TranslationSettingsMiddleware.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAD861B12E9E75C000F6E0E0 /* TranslationSettingsMiddleware.swift */; }; @@ -1469,9 +1469,11 @@ B2FEA68D2B460D390058E616 /* AddressAutofillSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2FEA68C2B460D390058E616 /* AddressAutofillSettingsViewController.swift */; }; B2FEA68F2B460D9E0058E616 /* AddressAutofillSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2FEA68E2B460D9E0058E616 /* AddressAutofillSettingsViewModel.swift */; }; B2FEA6912B4661BE0058E616 /* AddressAutofillToggle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2FEA6902B4661BE0058E616 /* AddressAutofillToggle.swift */; }; + B326EA470451415F90D8F722 /* TranslationPickerSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F84988A6047D42DBB38FFAC1 /* TranslationPickerSettingsViewController.swift */; }; B63BC8CE34524B98B781AE4C /* TranslationSettingsStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BD90815183467AA5B28FDA /* TranslationSettingsStateTests.swift */; }; B63BC8CF34524B98B781AE4D /* TranslationSettingsMiddlewareTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BD90825183467AA5B28FDB /* TranslationSettingsMiddlewareTests.swift */; }; B63BC8D034524B98B781AE4E /* TranslationSettingsViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BD90835183467AA5B28FDC /* TranslationSettingsViewControllerTests.swift */; }; + B63BC8D134524B98B781AE4F /* TranslationPickerSettingsViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5BD90845183467AA5B28FDD /* TranslationPickerSettingsViewControllerTests.swift */; }; BA1237BA2DAE55EA00BB6333 /* NightModeAllFramesAtDocumentStart.js in Resources */ = {isa = PBXBuildFile; fileRef = BA1237B72DAE54BB00BB6333 /* NightModeAllFramesAtDocumentStart.js */; }; BA1237BC2DAE608100BB6333 /* GenericSectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA1237BB2DAE607B00BB6333 /* GenericSectionView.swift */; }; BA1237BF2DAE675B00BB6333 /* GenericImageOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA1237BE2DAE675400BB6333 /* GenericImageOption.swift */; }; @@ -2683,6 +2685,7 @@ 0ABCD45A2D355255005D704A /* TermsOfServiceTelemetry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TermsOfServiceTelemetry.swift; sourceTree = ""; }; 0ABCD45C2D356006005D704A /* TermsOfServiceTelemetryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TermsOfServiceTelemetryTests.swift; sourceTree = ""; }; 0AC0F9472E3CA17500E826D8 /* MainMenuConfigurationUtilityTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainMenuConfigurationUtilityTests.swift; sourceTree = ""; }; + 0AC4BB702F73DF9900ABEFDB /* AddressSettingsCellView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressSettingsCellView.swift; 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 = ""; }; 0AD3EEAB2C2485A7001044E5 /* ThemedCenteredTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemedCenteredTableViewCell.swift; sourceTree = ""; }; @@ -9456,6 +9459,7 @@ 8C51ED6B2DE0A49800B3E58A /* NimbusOnboardingKitFeatureLayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NimbusOnboardingKitFeatureLayer.swift; sourceTree = ""; }; 8C51ED6F2DE0A4D700B3E58A /* OnboardingKitCardInfoModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingKitCardInfoModel.swift; sourceTree = ""; }; 8C51ED712DE0A5B500B3E58A /* OnboardingKitViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingKitViewModel.swift; sourceTree = ""; }; + 8C5E7E922F6B3C3F00A3DD27 /* TranslationSettingsDiffableDataSourceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranslationSettingsDiffableDataSourceTests.swift; sourceTree = ""; }; 8C61A2802F3371330021C88D /* BrowserViewControllerKVOTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserViewControllerKVOTests.swift; sourceTree = ""; }; 8C6AF2692D38FB1500254698 /* GleanLifecycleObserverTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GleanLifecycleObserverTests.swift; sourceTree = ""; }; 8C77849E2DF33707001FB8B0 /* OnboardingService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingService.swift; sourceTree = ""; }; @@ -9788,10 +9792,6 @@ AAD1CD862EAABA7C00BEC90A /* TranslationsConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranslationsConfiguration.swift; sourceTree = ""; }; AAD861A72E9E748100F6E0E0 /* TranslationSetting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranslationSetting.swift; sourceTree = ""; }; AAD861AA2E9E75A100F6E0E0 /* TranslationSettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranslationSettingsViewController.swift; sourceTree = ""; }; - F84988A6047D42DBB38FFAC1 /* TranslationPickerSettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranslationPickerSettingsViewController.swift; sourceTree = ""; }; - E0865C80F73A49F08E2B17E2 /* TranslationSettingsDiffableDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranslationSettingsDiffableDataSource.swift; sourceTree = ""; }; - B5BD90845183467AA5B28FDD /* TranslationPickerSettingsViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranslationPickerSettingsViewControllerTests.swift; sourceTree = ""; }; - 8C5E7E922F6B3C3F00A3DD27 /* TranslationSettingsDiffableDataSourceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranslationSettingsDiffableDataSourceTests.swift; sourceTree = ""; }; AAD861AD2E9E75C000F6E0E0 /* TranslationSettingsAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranslationSettingsAction.swift; sourceTree = ""; }; AAD861AF2E9E75C000F6E0E0 /* TranslationSettingsState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranslationSettingsState.swift; sourceTree = ""; }; AAD861B12E9E75C000F6E0E0 /* TranslationSettingsMiddleware.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranslationSettingsMiddleware.swift; sourceTree = ""; }; @@ -9933,6 +9933,7 @@ B5BD90815183467AA5B28FDA /* TranslationSettingsStateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranslationSettingsStateTests.swift; sourceTree = ""; }; B5BD90825183467AA5B28FDB /* TranslationSettingsMiddlewareTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranslationSettingsMiddlewareTests.swift; sourceTree = ""; }; B5BD90835183467AA5B28FDC /* TranslationSettingsViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranslationSettingsViewControllerTests.swift; sourceTree = ""; }; + B5BD90845183467AA5B28FDD /* TranslationPickerSettingsViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranslationPickerSettingsViewControllerTests.swift; sourceTree = ""; }; B5E444C0B04A67882844A6C6 /* ga */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ga; path = ga.lproj/ClearPrivateData.strings; sourceTree = ""; }; B60B46D4BD055D52822BF77D /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/ClearHistoryConfirm.strings; sourceTree = ""; }; B621470BA1595932CE4DE6D6 /* sq */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sq; path = sq.lproj/Storage.strings; sourceTree = ""; }; @@ -10942,6 +10943,7 @@ E03840168BAE1794B6A53697 /* en-CA */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "en-CA"; path = "en-CA.lproj/Shared.strings"; sourceTree = ""; }; E0734D3F86AB560D72B1CA4C /* br */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = br; path = br.lproj/Today.strings; sourceTree = ""; }; E07B402E89A647D70FDE7AE9 /* su */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = su; path = su.lproj/ClearPrivateDataConfirm.strings; sourceTree = ""; }; + E0865C80F73A49F08E2B17E2 /* TranslationSettingsDiffableDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranslationSettingsDiffableDataSource.swift; sourceTree = ""; }; E09E4F50BC35F97B31C74197 /* su */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = su; path = su.lproj/Storage.strings; sourceTree = ""; }; E0C04912B4FBCF45DBE8B00D /* lo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = lo; path = lo.lproj/HistoryPanel.strings; sourceTree = ""; }; E0FA43418E1B0DC4B8E7D818 /* eo */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eo; path = eo.lproj/FindInPage.strings; sourceTree = ""; }; @@ -11372,6 +11374,7 @@ F8324EB3B9CEED437A3D68A6 /* rm */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = rm; path = rm.lproj/ClearPrivateData.strings; sourceTree = ""; }; F83869BC2D5EAC8F00E8B999 /* RustKeychain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RustKeychain.swift; sourceTree = ""; }; F83869BE2D5EB74C00E8B999 /* MockRustKeychain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockRustKeychain.swift; sourceTree = ""; }; + F84988A6047D42DBB38FFAC1 /* TranslationPickerSettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TranslationPickerSettingsViewController.swift; sourceTree = ""; }; F84B21BE1A090F8100AAB793 /* Client.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Client.app; sourceTree = BUILT_PRODUCTS_DIR; }; F84B21D31A090F8100AAB793 /* ClientTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ClientTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; F84B21D81A090F8100AAB793 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -11535,10 +11538,10 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 0AC4BA3B2F7289F200ABEFDB /* LLMKit in Frameworks */, 5A70EF0E295DFCCF00790249 /* Common in Frameworks */, 8A08EC6427EBDCAD00E119C7 /* AdServices.framework in Frameworks */, 0BF802E22CFF0937005633E5 /* Shared in Frameworks */, - AA93B7152F6D95D6002E5E88 /* LLMKit in Frameworks */, 8A08EC6227EBDCA400E119C7 /* iAd.framework in Frameworks */, 43BE580E278BABCF00491291 /* RustMozillaAppServices.framework in Frameworks */, C82043852523DBF600740B71 /* Sync.framework in Frameworks */, @@ -14591,6 +14594,7 @@ B2FEA6892B460CEC0058E616 /* Address */ = { isa = PBXGroup; children = ( + 0AC4BB702F73DF9900ABEFDB /* AddressSettingsCellView.swift */, 8A97E6EC2C58489C00F94793 /* AddressUtility */, 8C2937732BF79F0C00146613 /* Edit */, B2FEA68C2B460D390058E616 /* AddressAutofillSettingsViewController.swift */, @@ -19265,6 +19269,7 @@ 8A1E93EA2A3CDC6100DD540A /* BaseCoordinator.swift in Sources */, E1442FD6294782D9003680B0 /* UIView+Extension.swift in Sources */, 8A89046F2D52977E00A5BB29 /* RemoteTabsManagerAction.swift in Sources */, + 0AC4BB712F73DFA400ABEFDB /* AddressSettingsCellView.swift in Sources */, AB936A692C05F2B100600F82 /* TrackingProtectionButton.swift in Sources */, 74F80D342A0A52D700013C3D /* PrivacyPolicyViewController.swift in Sources */, 274A36CE239EB9EC00A21587 /* LibraryViewController+LibraryPanelDelegate.swift in Sources */, diff --git a/firefox-ios/Client/Frontend/Autofill/Address/AddressListView.swift b/firefox-ios/Client/Frontend/Autofill/Address/AddressListView.swift index 54068b21eec56..34574dfae09b7 100644 --- a/firefox-ios/Client/Frontend/Autofill/Address/AddressListView.swift +++ b/firefox-ios/Client/Frontend/Autofill/Address/AddressListView.swift @@ -19,6 +19,7 @@ struct AddressListView: View { static let titleFontSize: CGFloat = 22 static let subtitleFontSize: CGFloat = 16 static let contentUnavailableViewTopPadding: CGFloat = 125 + static let listPadding: CGFloat = -8 } // MARK: - Properties @@ -34,16 +35,21 @@ struct AddressListView: View { @State var imageColor: Color = .clear @State var listColor: Color = .clear + @State private var isLandscape = false + // MARK: - Body var body: some View { Group { if viewModel.showSection { List { - Section(header: Text(String.Addresses.Settings.SavedAddressesSectionTitle)) { + Section(header: Text(String.Addresses.Settings.SavedAddressesSectionTitle) + .modifier(ListHeaderPadding(isLandscape: isLandscape, + paddingSize: UX.listPadding))) { ForEach(viewModel.addresses, id: \.self) { address in - AddressCellView( + AddressSettingsCellView( windowUUID: windowUUID, + isLandscape: isLandscape, address: address, onTap: { if viewModel.isEditingFeatureEnabled { @@ -65,6 +71,7 @@ struct AddressListView: View { Spacer() } } + .detectDeviceOrientation(isLandscape: $isLandscape) .sheet(item: $viewModel.destination, onDismiss: { viewModel.isEditMode = false }) { destination in diff --git a/firefox-ios/Client/Frontend/Autofill/Address/AddressSettingsCellView.swift b/firefox-ios/Client/Frontend/Autofill/Address/AddressSettingsCellView.swift new file mode 100644 index 0000000000000..c885d504ee67d --- /dev/null +++ b/firefox-ios/Client/Frontend/Autofill/Address/AddressSettingsCellView.swift @@ -0,0 +1,98 @@ +// 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 SwiftUI +import Common + +import struct MozillaAppServices.Address + +// MARK: - AddressCellView + +/// A view representing a cell displaying address information. +struct AddressSettingsCellView: View { + // MARK: - Constants + + private enum UX { + static let listIconPadding: CGFloat = -8 + static let hStackSpacing: CGFloat = 24 + static let vStackSpacing: CGFloat = 0 + static let spacerHeight: CGFloat = 0 + static let dividerHeight: CGFloat = 1 + } + + // MARK: - Properties + + let windowUUID: WindowUUID + @Environment(\.themeManager) + var themeManager + let isLandscape: Bool + + @State private var textColor: Color = .clear + @State private var customLightGray: Color = .clear + @State private var iconPrimary: Color = .clear + + private(set) var address: Address + private(set) var onTap: () -> Void + + // MARK: - Body + + var body: some View { + Button(action: onTap) { + VStack(alignment: .leading, spacing: UX.vStackSpacing) { + HStack(alignment: .midIconAndLabel, spacing: UX.hStackSpacing) { + Image(StandardImageIdentifiers.Large.location) + .renderingMode(.template) + .modifier(ListItemIconPadding(isLandscape: isLandscape, + paddingSize: UX.listIconPadding)) + .foregroundColor(iconPrimary) + .alignmentGuide(.midIconAndLabel) { $0[VerticalAlignment.center] } + VStack(alignment: .leading) { + if !address.name.isEmpty { + Text(address.name) + .font(.body) + .foregroundColor(textColor) + .alignmentGuide(.midIconAndLabel) { $0[VerticalAlignment.center] } + } + if !address.streetAddress.isEmpty { + Text(address.streetAddress) + .font(.subheadline) + .foregroundColor(customLightGray) + } + if !address.addressCityStateZipcode.isEmpty { + Text(address.addressCityStateZipcode) + .font(.subheadline) + .foregroundColor(customLightGray) + } + } + Spacer() + } + } + .padding() + Spacer().frame(height: UX.spacerHeight) + Divider().frame(height: UX.dividerHeight) + } + .listRowInsets(EdgeInsets()) + .listRowBackground(Color(themeManager.getCurrentTheme(for: windowUUID).colors.layer2)) + .listRowSeparator(.hidden) + .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)) + } + .accessibilityLabel(address.a11ySettingsRow) + } + + // MARK: - Theme Application + + /// Applies the theme to the view. + /// - Parameter theme: The theme to be applied. + func applyTheme(theme: Theme) { + let color = theme.colors + textColor = Color(color.textPrimary) + customLightGray = Color(color.textSecondary) + iconPrimary = Color(color.iconPrimary) + } +} diff --git a/firefox-ios/Client/Frontend/Settings/AppearanceSettings/StylingViewModifiers.swift b/firefox-ios/Client/Frontend/Settings/AppearanceSettings/StylingViewModifiers.swift index 92e67264d4046..ea65f21971129 100644 --- a/firefox-ios/Client/Frontend/Settings/AppearanceSettings/StylingViewModifiers.swift +++ b/firefox-ios/Client/Frontend/Settings/AppearanceSettings/StylingViewModifiers.swift @@ -55,6 +55,48 @@ struct ColoredListStyle: ViewModifier { } } +struct ListHeaderPadding: ViewModifier { + let isLandscape: Bool + let paddingSize: CGFloat + + func body(content: Content) -> some View { + let isPad = UIDevice().userInterfaceIdiom == .pad + let shouldAddPadding = !isLandscape || (isPad && isLandscape) + if #available(iOS 26.0, *) { + if shouldAddPadding { + content.padding(.leading, paddingSize) + } else { + content + } + } else { + if !isPad { + content.padding(.leading, paddingSize / 2) + } else { + content + } + } + } +} + +struct ListItemIconPadding: ViewModifier { + let isLandscape: Bool + let paddingSize: CGFloat + + func body(content: Content) -> some View { + let isPad = UIDevice().userInterfaceIdiom == .pad + let shouldAddPadding = !isLandscape || (isPad && isLandscape) + if #available(iOS 26.0, *) { + if shouldAddPadding { + content.padding(.leading, paddingSize) + } else { + content + } + } else { + content + } + } +} + struct ListStyle: ViewModifier { func body(content: Content) -> some View { if #available(iOS 26.0, *) { @@ -197,3 +239,25 @@ struct CreditCardViewButtonStyle: ViewModifier { : Color(theme.colors.textSecondary) } } + +struct DeviceOrientation: ViewModifier { + @Binding var isLandscape: Bool + + func body(content: Content) -> some View { + GeometryReader { geometryReader in + content + .onAppear { + isLandscape = geometryReader.size.width > geometryReader.size.height + } + .onChange(of: geometryReader.size) { newSize in + isLandscape = newSize.width > newSize.height + } + } + } +} + +extension View { + func detectDeviceOrientation(isLandscape: Binding) -> some View { + self.modifier(DeviceOrientation(isLandscape: isLandscape)) + } +} From b160cbee67e462e933302e7d08833c2c65a18eaf Mon Sep 17 00:00:00 2001 From: Alexandru Farcasanu Date: Fri, 27 Mar 2026 16:41:40 +0200 Subject: [PATCH 2/9] Quick code refactor Increased cells margins --- firefox-ios/Client.xcodeproj/project.pbxproj | 5 - .../Address/AddressAutofillSettingsView.swift | 38 +++++++ .../Autofill/Address/AddressCellView.swift | 37 ++++--- .../Autofill/Address/AddressListView.swift | 8 +- .../Address/AddressSettingsCellView.swift | 98 ------------------- .../StylingViewModifiers.swift | 65 +----------- 6 files changed, 59 insertions(+), 192 deletions(-) delete mode 100644 firefox-ios/Client/Frontend/Autofill/Address/AddressSettingsCellView.swift diff --git a/firefox-ios/Client.xcodeproj/project.pbxproj b/firefox-ios/Client.xcodeproj/project.pbxproj index f87b6849d77f4..c24a42b3db65e 100644 --- a/firefox-ios/Client.xcodeproj/project.pbxproj +++ b/firefox-ios/Client.xcodeproj/project.pbxproj @@ -61,8 +61,6 @@ 0ABCD45B2D355260005D704A /* TermsOfServiceTelemetry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABCD45A2D355255005D704A /* TermsOfServiceTelemetry.swift */; }; 0ABCD45D2D356015005D704A /* TermsOfServiceTelemetryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ABCD45C2D356006005D704A /* TermsOfServiceTelemetryTests.swift */; }; 0AC0F9482E3CA17900E826D8 /* MainMenuConfigurationUtilityTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AC0F9472E3CA17500E826D8 /* MainMenuConfigurationUtilityTests.swift */; }; - 0AC4BA3B2F7289F200ABEFDB /* LLMKit in Frameworks */ = {isa = PBXBuildFile; productRef = AA93B7142F6D95D6002E5E88 /* LLMKit */; }; - 0AC4BB712F73DFA400ABEFDB /* AddressSettingsCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AC4BB702F73DF9900ABEFDB /* AddressSettingsCellView.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 */; }; @@ -2685,7 +2683,6 @@ 0ABCD45A2D355255005D704A /* TermsOfServiceTelemetry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TermsOfServiceTelemetry.swift; sourceTree = ""; }; 0ABCD45C2D356006005D704A /* TermsOfServiceTelemetryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TermsOfServiceTelemetryTests.swift; sourceTree = ""; }; 0AC0F9472E3CA17500E826D8 /* MainMenuConfigurationUtilityTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainMenuConfigurationUtilityTests.swift; sourceTree = ""; }; - 0AC4BB702F73DF9900ABEFDB /* AddressSettingsCellView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressSettingsCellView.swift; 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 = ""; }; 0AD3EEAB2C2485A7001044E5 /* ThemedCenteredTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemedCenteredTableViewCell.swift; sourceTree = ""; }; @@ -14593,7 +14590,6 @@ B2FEA6892B460CEC0058E616 /* Address */ = { isa = PBXGroup; children = ( - 0AC4BB702F73DF9900ABEFDB /* AddressSettingsCellView.swift */, 8A97E6EC2C58489C00F94793 /* AddressUtility */, 8C2937732BF79F0C00146613 /* Edit */, B2FEA68C2B460D390058E616 /* AddressAutofillSettingsViewController.swift */, @@ -19267,7 +19263,6 @@ 8A1E93EA2A3CDC6100DD540A /* BaseCoordinator.swift in Sources */, E1442FD6294782D9003680B0 /* UIView+Extension.swift in Sources */, 8A89046F2D52977E00A5BB29 /* RemoteTabsManagerAction.swift in Sources */, - 0AC4BB712F73DFA400ABEFDB /* AddressSettingsCellView.swift in Sources */, AB936A692C05F2B100600F82 /* TrackingProtectionButton.swift in Sources */, 74F80D342A0A52D700013C3D /* PrivacyPolicyViewController.swift in Sources */, 274A36CE239EB9EC00A21587 /* LibraryViewController+LibraryPanelDelegate.swift in Sources */, diff --git a/firefox-ios/Client/Frontend/Autofill/Address/AddressAutofillSettingsView.swift b/firefox-ios/Client/Frontend/Autofill/Address/AddressAutofillSettingsView.swift index 18620d2805299..25f595b6f6b75 100644 --- a/firefox-ios/Client/Frontend/Autofill/Address/AddressAutofillSettingsView.swift +++ b/firefox-ios/Client/Frontend/Autofill/Address/AddressAutofillSettingsView.swift @@ -64,3 +64,41 @@ struct AddressAutofillSettingsView: View { viewBackground = Color(color.layer1) } } + +struct ListHeaderPadding: ViewModifier { + let isLandscape: Bool + let paddingSize: CGFloat + + func body(content: Content) -> some View { + let isPad = UIDevice().userInterfaceIdiom == .pad + let shouldAddPadding = !isLandscape || (isPad && isLandscape) + if #available(iOS 26.0, *) { + if shouldAddPadding { + content.padding(.leading, paddingSize) + } else { + content + } + } else { + if !isPad { + content.padding(.leading, paddingSize / 2) + } else { + content + } + } + } +} + +struct ListItemIconPadding: ViewModifier { + let isLandscape: Bool + let paddingSize: CGFloat + + func body(content: Content) -> some View { + let isPad = UIDevice().userInterfaceIdiom == .pad + let shouldAddPadding = !isLandscape || (isPad && isLandscape) + if #available(iOS 26.0, *), shouldAddPadding { + content.padding(.leading, paddingSize) + } else { + content + } + } +} diff --git a/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift b/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift index 50fa0a29e8cd9..79a39eb48657c 100644 --- a/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift +++ b/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift @@ -11,6 +11,16 @@ import struct MozillaAppServices.Address /// A view representing a cell displaying address information. struct AddressCellView: View { + // MARK: - Constants + + private enum UX { + static let listIconPadding: CGFloat = -8 + static let hStackSpacing: CGFloat = 24 + static let vStackSpacing: CGFloat = 0 + static let spacerHeight: CGFloat = 0 + static let dividerHeight: CGFloat = 1 + } + // MARK: - Properties let windowUUID: WindowUUID @@ -28,11 +38,12 @@ struct AddressCellView: View { var body: some View { Button(action: onTap) { - VStack(alignment: .leading, spacing: 0) { - HStack(alignment: .midIconAndLabel, spacing: 24) { + VStack(alignment: .leading, spacing: UX.vStackSpacing) { + HStack(alignment: .midIconAndLabel, spacing: UX.hStackSpacing) { Image(StandardImageIdentifiers.Large.location) .renderingMode(.template) - .padding(.leading, 16) + .modifier(ListItemIconPadding(isLandscape: UIDevice.current.orientation.isLandscape, + paddingSize: UX.listIconPadding)) .foregroundColor(iconPrimary) .alignmentGuide(.midIconAndLabel) { $0[VerticalAlignment.center] } VStack(alignment: .leading) { @@ -57,11 +68,12 @@ struct AddressCellView: View { } } .padding() - Spacer().frame(height: 0) - Divider().frame(height: 1) + Spacer().frame(height: UX.spacerHeight) + Divider().frame(height: UX.dividerHeight) } .listRowInsets(EdgeInsets()) - .buttonStyle(AddressButtonStyle(theme: themeManager.getCurrentTheme(for: windowUUID))) + .listRowBackground(Color(themeManager.getCurrentTheme(for: windowUUID).colors.layer2) + .edgesIgnoringSafeArea([.leading, .trailing])) .listRowSeparator(.hidden) .onAppear { applyTheme(theme: themeManager.getCurrentTheme(for: windowUUID)) @@ -84,16 +96,3 @@ struct AddressCellView: View { iconPrimary = Color(color.iconPrimary) } } - -// MARK: - CustomButtonStyle - -/// A address button style with a specific theme. -struct AddressButtonStyle: ButtonStyle { - let theme: Theme - - func makeBody(configuration: Configuration) -> some View { - configuration.label - .background(configuration.isPressed ? Color(theme.colors.layer1) : Color(theme.colors.layer2)) - .foregroundColor(.white) - } -} diff --git a/firefox-ios/Client/Frontend/Autofill/Address/AddressListView.swift b/firefox-ios/Client/Frontend/Autofill/Address/AddressListView.swift index 34574dfae09b7..496ae8cca8e31 100644 --- a/firefox-ios/Client/Frontend/Autofill/Address/AddressListView.swift +++ b/firefox-ios/Client/Frontend/Autofill/Address/AddressListView.swift @@ -35,8 +35,6 @@ struct AddressListView: View { @State var imageColor: Color = .clear @State var listColor: Color = .clear - @State private var isLandscape = false - // MARK: - Body var body: some View { @@ -44,12 +42,11 @@ struct AddressListView: View { if viewModel.showSection { List { Section(header: Text(String.Addresses.Settings.SavedAddressesSectionTitle) - .modifier(ListHeaderPadding(isLandscape: isLandscape, + .modifier(ListHeaderPadding(isLandscape: UIDevice.current.orientation.isLandscape, paddingSize: UX.listPadding))) { ForEach(viewModel.addresses, id: \.self) { address in - AddressSettingsCellView( + AddressCellView( windowUUID: windowUUID, - isLandscape: isLandscape, address: address, onTap: { if viewModel.isEditingFeatureEnabled { @@ -71,7 +68,6 @@ struct AddressListView: View { Spacer() } } - .detectDeviceOrientation(isLandscape: $isLandscape) .sheet(item: $viewModel.destination, onDismiss: { viewModel.isEditMode = false }) { destination in diff --git a/firefox-ios/Client/Frontend/Autofill/Address/AddressSettingsCellView.swift b/firefox-ios/Client/Frontend/Autofill/Address/AddressSettingsCellView.swift deleted file mode 100644 index c885d504ee67d..0000000000000 --- a/firefox-ios/Client/Frontend/Autofill/Address/AddressSettingsCellView.swift +++ /dev/null @@ -1,98 +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 SwiftUI -import Common - -import struct MozillaAppServices.Address - -// MARK: - AddressCellView - -/// A view representing a cell displaying address information. -struct AddressSettingsCellView: View { - // MARK: - Constants - - private enum UX { - static let listIconPadding: CGFloat = -8 - static let hStackSpacing: CGFloat = 24 - static let vStackSpacing: CGFloat = 0 - static let spacerHeight: CGFloat = 0 - static let dividerHeight: CGFloat = 1 - } - - // MARK: - Properties - - let windowUUID: WindowUUID - @Environment(\.themeManager) - var themeManager - let isLandscape: Bool - - @State private var textColor: Color = .clear - @State private var customLightGray: Color = .clear - @State private var iconPrimary: Color = .clear - - private(set) var address: Address - private(set) var onTap: () -> Void - - // MARK: - Body - - var body: some View { - Button(action: onTap) { - VStack(alignment: .leading, spacing: UX.vStackSpacing) { - HStack(alignment: .midIconAndLabel, spacing: UX.hStackSpacing) { - Image(StandardImageIdentifiers.Large.location) - .renderingMode(.template) - .modifier(ListItemIconPadding(isLandscape: isLandscape, - paddingSize: UX.listIconPadding)) - .foregroundColor(iconPrimary) - .alignmentGuide(.midIconAndLabel) { $0[VerticalAlignment.center] } - VStack(alignment: .leading) { - if !address.name.isEmpty { - Text(address.name) - .font(.body) - .foregroundColor(textColor) - .alignmentGuide(.midIconAndLabel) { $0[VerticalAlignment.center] } - } - if !address.streetAddress.isEmpty { - Text(address.streetAddress) - .font(.subheadline) - .foregroundColor(customLightGray) - } - if !address.addressCityStateZipcode.isEmpty { - Text(address.addressCityStateZipcode) - .font(.subheadline) - .foregroundColor(customLightGray) - } - } - Spacer() - } - } - .padding() - Spacer().frame(height: UX.spacerHeight) - Divider().frame(height: UX.dividerHeight) - } - .listRowInsets(EdgeInsets()) - .listRowBackground(Color(themeManager.getCurrentTheme(for: windowUUID).colors.layer2)) - .listRowSeparator(.hidden) - .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)) - } - .accessibilityLabel(address.a11ySettingsRow) - } - - // MARK: - Theme Application - - /// Applies the theme to the view. - /// - Parameter theme: The theme to be applied. - func applyTheme(theme: Theme) { - let color = theme.colors - textColor = Color(color.textPrimary) - customLightGray = Color(color.textSecondary) - iconPrimary = Color(color.iconPrimary) - } -} diff --git a/firefox-ios/Client/Frontend/Settings/AppearanceSettings/StylingViewModifiers.swift b/firefox-ios/Client/Frontend/Settings/AppearanceSettings/StylingViewModifiers.swift index ea65f21971129..879af016990c9 100644 --- a/firefox-ios/Client/Frontend/Settings/AppearanceSettings/StylingViewModifiers.swift +++ b/firefox-ios/Client/Frontend/Settings/AppearanceSettings/StylingViewModifiers.swift @@ -49,50 +49,9 @@ struct ColoredListStyle: ViewModifier { .listStyle(.insetGrouped) .scrollContentBackground(.hidden) .background(backgroundColor) - } else { - content.listStyle(.plain) - } - } -} - -struct ListHeaderPadding: ViewModifier { - let isLandscape: Bool - let paddingSize: CGFloat - - func body(content: Content) -> some View { - let isPad = UIDevice().userInterfaceIdiom == .pad - let shouldAddPadding = !isLandscape || (isPad && isLandscape) - if #available(iOS 26.0, *) { - if shouldAddPadding { - content.padding(.leading, paddingSize) - } else { - content - } - } else { - if !isPad { - content.padding(.leading, paddingSize / 2) - } else { - content - } - } - } -} - -struct ListItemIconPadding: ViewModifier { - let isLandscape: Bool - let paddingSize: CGFloat - - func body(content: Content) -> some View { - let isPad = UIDevice().userInterfaceIdiom == .pad - let shouldAddPadding = !isLandscape || (isPad && isLandscape) - if #available(iOS 26.0, *) { - if shouldAddPadding { - content.padding(.leading, paddingSize) - } else { - content - } } else { content + .listStyle(.plain) } } } @@ -239,25 +198,3 @@ struct CreditCardViewButtonStyle: ViewModifier { : Color(theme.colors.textSecondary) } } - -struct DeviceOrientation: ViewModifier { - @Binding var isLandscape: Bool - - func body(content: Content) -> some View { - GeometryReader { geometryReader in - content - .onAppear { - isLandscape = geometryReader.size.width > geometryReader.size.height - } - .onChange(of: geometryReader.size) { newSize in - isLandscape = newSize.width > newSize.height - } - } - } -} - -extension View { - func detectDeviceOrientation(isLandscape: Binding) -> some View { - self.modifier(DeviceOrientation(isLandscape: isLandscape)) - } -} From c184b90f770a077395ca34fc81f198efcd574adc Mon Sep 17 00:00:00 2001 From: Alexandru Farcasanu Date: Tue, 31 Mar 2026 11:58:50 +0300 Subject: [PATCH 3/9] Handle padding when screen is rotated --- .../Client/Frontend/Autofill/Address/AddressCellView.swift | 7 ++++++- .../Client/Frontend/Autofill/Address/AddressListView.swift | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift b/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift index 79a39eb48657c..f3b2c0ed01718 100644 --- a/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift +++ b/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift @@ -31,6 +31,8 @@ struct AddressCellView: View { @State private var customLightGray: Color = .clear @State private var iconPrimary: Color = .clear + @State private var isLandscape = false + private(set) var address: Address private(set) var onTap: () -> Void @@ -42,7 +44,7 @@ struct AddressCellView: View { HStack(alignment: .midIconAndLabel, spacing: UX.hStackSpacing) { Image(StandardImageIdentifiers.Large.location) .renderingMode(.template) - .modifier(ListItemIconPadding(isLandscape: UIDevice.current.orientation.isLandscape, + .modifier(ListItemIconPadding(isLandscape: isLandscape, paddingSize: UX.listIconPadding)) .foregroundColor(iconPrimary) .alignmentGuide(.midIconAndLabel) { $0[VerticalAlignment.center] } @@ -82,6 +84,9 @@ struct AddressCellView: View { guard let uuid = notification.windowUUID, uuid == windowUUID else { return } applyTheme(theme: themeManager.getCurrentTheme(for: windowUUID)) } + .onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in + isLandscape = UIDevice.current.orientation.isLandscape + } .accessibilityLabel(address.a11ySettingsRow) } diff --git a/firefox-ios/Client/Frontend/Autofill/Address/AddressListView.swift b/firefox-ios/Client/Frontend/Autofill/Address/AddressListView.swift index 496ae8cca8e31..4b159196d5c89 100644 --- a/firefox-ios/Client/Frontend/Autofill/Address/AddressListView.swift +++ b/firefox-ios/Client/Frontend/Autofill/Address/AddressListView.swift @@ -35,6 +35,8 @@ struct AddressListView: View { @State var imageColor: Color = .clear @State var listColor: Color = .clear + @State private var isLandscape = false + // MARK: - Body var body: some View { @@ -42,7 +44,7 @@ struct AddressListView: View { if viewModel.showSection { List { Section(header: Text(String.Addresses.Settings.SavedAddressesSectionTitle) - .modifier(ListHeaderPadding(isLandscape: UIDevice.current.orientation.isLandscape, + .modifier(ListHeaderPadding(isLandscape: isLandscape, paddingSize: UX.listPadding))) { ForEach(viewModel.addresses, id: \.self) { address in AddressCellView( @@ -89,6 +91,9 @@ struct AddressListView: View { guard let uuid = notification.windowUUID, uuid == windowUUID else { return } applyTheme(theme: themeManager.getCurrentTheme(for: windowUUID)) } + .onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in + isLandscape = UIDevice.current.orientation.isLandscape + } .onDisappear { viewModel.editAddressWebViewManager.teardownWebView() } From fe082acc128b0d3ff4ed22a8c4b35241e043d3a9 Mon Sep 17 00:00:00 2001 From: Alexandru Farcasanu Date: Tue, 31 Mar 2026 12:46:12 +0300 Subject: [PATCH 4/9] Fixed SwiftLint error --- .../Client/Frontend/Autofill/Address/AddressCellView.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift b/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift index f3b2c0ed01718..662521fdad1db 100644 --- a/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift +++ b/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift @@ -44,6 +44,7 @@ struct AddressCellView: View { HStack(alignment: .midIconAndLabel, spacing: UX.hStackSpacing) { Image(StandardImageIdentifiers.Large.location) .renderingMode(.template) + .accessibilityHidden(true) .modifier(ListItemIconPadding(isLandscape: isLandscape, paddingSize: UX.listIconPadding)) .foregroundColor(iconPrimary) From efd44c3a37c1a953408ec6b0e33ae3f271ec3fee Mon Sep 17 00:00:00 2001 From: Alexandru Farcasanu Date: Thu, 9 Apr 2026 11:01:01 +0300 Subject: [PATCH 5/9] Added cell selection feedback Adjusted padding for table header --- .../Address/AddressAutofillSettingsView.swift | 6 +----- .../Frontend/Autofill/Address/AddressCellView.swift | 12 ++++++++++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/firefox-ios/Client/Frontend/Autofill/Address/AddressAutofillSettingsView.swift b/firefox-ios/Client/Frontend/Autofill/Address/AddressAutofillSettingsView.swift index 25f595b6f6b75..f484aacbf57d7 100644 --- a/firefox-ios/Client/Frontend/Autofill/Address/AddressAutofillSettingsView.swift +++ b/firefox-ios/Client/Frontend/Autofill/Address/AddressAutofillSettingsView.swift @@ -79,11 +79,7 @@ struct ListHeaderPadding: ViewModifier { content } } else { - if !isPad { - content.padding(.leading, paddingSize / 2) - } else { - content - } + content } } } diff --git a/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift b/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift index 662521fdad1db..7ad8ec3b3b0f9 100644 --- a/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift +++ b/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift @@ -89,6 +89,7 @@ struct AddressCellView: View { isLandscape = UIDevice.current.orientation.isLandscape } .accessibilityLabel(address.a11ySettingsRow) + .buttonStyle(AddressButtonStyle(theme: themeManager.getCurrentTheme(for: windowUUID))) } // MARK: - Theme Application @@ -102,3 +103,14 @@ struct AddressCellView: View { iconPrimary = Color(color.iconPrimary) } } + +/// A address button style with a specific theme. +struct AddressButtonStyle: ButtonStyle { + let theme: Theme + + func makeBody(configuration: Configuration) -> some View { + configuration.label + .background(configuration.isPressed ? Color(theme.colors.layer1) : Color(theme.colors.layer2)) + .foregroundColor(.white) + } +} From 8a49eec993817b63e2fa4d1fbd4ea44b4fc735e6 Mon Sep 17 00:00:00 2001 From: Alexandru Farcasanu Date: Tue, 21 Apr 2026 16:45:05 +0300 Subject: [PATCH 6/9] Applied highlight color when tapping on cell --- .../Autofill/Address/AddressCellView.swift | 103 ++++++++++-------- 1 file changed, 59 insertions(+), 44 deletions(-) diff --git a/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift b/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift index 7ad8ec3b3b0f9..960cd86c756b0 100644 --- a/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift +++ b/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift @@ -17,7 +17,6 @@ struct AddressCellView: View { static let listIconPadding: CGFloat = -8 static let hStackSpacing: CGFloat = 24 static let vStackSpacing: CGFloat = 0 - static let spacerHeight: CGFloat = 0 static let dividerHeight: CGFloat = 1 } @@ -30,7 +29,11 @@ struct AddressCellView: View { @State private var textColor: Color = .clear @State private var customLightGray: Color = .clear @State private var iconPrimary: Color = .clear + @State private var backgroundColor: Color = .clear + @State private var highlightColor: Color = .clear + @State private var isHighlighted = false + @GestureState private var isPressing = false @State private var isLandscape = false private(set) var address: Address @@ -39,44 +42,64 @@ struct AddressCellView: View { // MARK: - Body var body: some View { - Button(action: onTap) { - VStack(alignment: .leading, spacing: UX.vStackSpacing) { - HStack(alignment: .midIconAndLabel, spacing: UX.hStackSpacing) { - Image(StandardImageIdentifiers.Large.location) - .renderingMode(.template) - .accessibilityHidden(true) - .modifier(ListItemIconPadding(isLandscape: isLandscape, - paddingSize: UX.listIconPadding)) - .foregroundColor(iconPrimary) - .alignmentGuide(.midIconAndLabel) { $0[VerticalAlignment.center] } - VStack(alignment: .leading) { - if !address.name.isEmpty { - Text(address.name) - .font(.body) - .foregroundColor(textColor) - .alignmentGuide(.midIconAndLabel) { $0[VerticalAlignment.center] } - } - if !address.streetAddress.isEmpty { - Text(address.streetAddress) - .font(.subheadline) - .foregroundColor(customLightGray) - } - if !address.addressCityStateZipcode.isEmpty { - Text(address.addressCityStateZipcode) - .font(.subheadline) - .foregroundColor(customLightGray) - } + VStack(spacing: UX.vStackSpacing) { + HStack(alignment: .midIconAndLabel, spacing: UX.hStackSpacing) { + Image(StandardImageIdentifiers.Large.location) + .renderingMode(.template) + .accessibilityHidden(true) + .modifier(ListItemIconPadding(isLandscape: isLandscape, + paddingSize: UX.listIconPadding)) + .foregroundColor(iconPrimary) + .alignmentGuide(.midIconAndLabel) { $0[VerticalAlignment.center] } + VStack(alignment: .leading) { + if !address.name.isEmpty { + Text(address.name) + .font(.body) + .foregroundColor(textColor) + .alignmentGuide(.midIconAndLabel) { $0[VerticalAlignment.center] } + } + if !address.streetAddress.isEmpty { + Text(address.streetAddress) + .font(.subheadline) + .foregroundColor(customLightGray) + } + if !address.addressCityStateZipcode.isEmpty { + Text(address.addressCityStateZipcode) + .font(.subheadline) + .foregroundColor(customLightGray) } - Spacer() } + Spacer() } .padding() - Spacer().frame(height: UX.spacerHeight) Divider().frame(height: UX.dividerHeight) } + .contentShape(Rectangle()) + .onChange(of: isPressing) { pressing in + if pressing { + isHighlighted = true + } else { + withAnimation(.easeOut(duration: 0.2)) { + isHighlighted = false + } + } + } + .gesture( + DragGesture(minimumDistance: 0) + .updating($isPressing) { _, state, _ in state = true } + .onEnded { value in + let isWithinTapBounds = abs(value.translation.width) < 20 + && abs(value.translation.height) < 20 + if isWithinTapBounds { + onTap() + } + } + ) .listRowInsets(EdgeInsets()) - .listRowBackground(Color(themeManager.getCurrentTheme(for: windowUUID).colors.layer2) - .edgesIgnoringSafeArea([.leading, .trailing])) + .listRowBackground( + (isHighlighted ? highlightColor : backgroundColor) + .edgesIgnoringSafeArea([.leading, .trailing]) + ) .listRowSeparator(.hidden) .onAppear { applyTheme(theme: themeManager.getCurrentTheme(for: windowUUID)) @@ -89,7 +112,8 @@ struct AddressCellView: View { isLandscape = UIDevice.current.orientation.isLandscape } .accessibilityLabel(address.a11ySettingsRow) - .buttonStyle(AddressButtonStyle(theme: themeManager.getCurrentTheme(for: windowUUID))) + .accessibilityAddTraits(.isButton) + .accessibilityAction { onTap() } } // MARK: - Theme Application @@ -101,16 +125,7 @@ struct AddressCellView: View { textColor = Color(color.textPrimary) customLightGray = Color(color.textSecondary) iconPrimary = Color(color.iconPrimary) - } -} - -/// A address button style with a specific theme. -struct AddressButtonStyle: ButtonStyle { - let theme: Theme - - func makeBody(configuration: Configuration) -> some View { - configuration.label - .background(configuration.isPressed ? Color(theme.colors.layer1) : Color(theme.colors.layer2)) - .foregroundColor(.white) + backgroundColor = Color(color.layer2) + highlightColor = Color(color.layer5Hover) } } From 933d472fdffad2c23d29c84d7e167bad0a076656 Mon Sep 17 00:00:00 2001 From: dicarobinho <61138287+dicarobinho@users.noreply.github.com> Date: Wed, 22 Apr 2026 15:43:17 +0300 Subject: [PATCH 7/9] Update firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift Co-authored-by: Winnie Teichmann <4530+thatswinnie@users.noreply.github.com> --- .../Client/Frontend/Autofill/Address/AddressCellView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift b/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift index 960cd86c756b0..69c5d8744f781 100644 --- a/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift +++ b/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift @@ -44,7 +44,7 @@ struct AddressCellView: View { var body: some View { VStack(spacing: UX.vStackSpacing) { HStack(alignment: .midIconAndLabel, spacing: UX.hStackSpacing) { - Image(StandardImageIdentifiers.Large.location) + Image(decorative: StandardImageIdentifiers.Large.location) .renderingMode(.template) .accessibilityHidden(true) .modifier(ListItemIconPadding(isLandscape: isLandscape, From 7e748311f46fc1c7112ad39984a0228dd22637af Mon Sep 17 00:00:00 2001 From: Alexandru Farcasanu Date: Wed, 22 Apr 2026 16:26:04 +0300 Subject: [PATCH 8/9] Removed accessibility for image --- .../Client/Frontend/Autofill/Address/AddressCellView.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift b/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift index 69c5d8744f781..769f5bb119495 100644 --- a/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift +++ b/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift @@ -46,7 +46,6 @@ struct AddressCellView: View { HStack(alignment: .midIconAndLabel, spacing: UX.hStackSpacing) { Image(decorative: StandardImageIdentifiers.Large.location) .renderingMode(.template) - .accessibilityHidden(true) .modifier(ListItemIconPadding(isLandscape: isLandscape, paddingSize: UX.listIconPadding)) .foregroundColor(iconPrimary) From 7f46e67d01a6dde770121a29012d338c34d0e234 Mon Sep 17 00:00:00 2001 From: Alexandru Farcasanu Date: Thu, 23 Apr 2026 14:07:03 +0300 Subject: [PATCH 9/9] Fixed testDeleteAddress test --- firefox-ios/Client/Application/AccessibilityIdentifiers.swift | 1 + .../Client/Frontend/Autofill/Address/AddressCellView.swift | 2 ++ .../Tests/XCUITests/PageScreens/AddressScreen.swift | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/firefox-ios/Client/Application/AccessibilityIdentifiers.swift b/firefox-ios/Client/Application/AccessibilityIdentifiers.swift index 5e29af128c1c5..1054ab38511a9 100644 --- a/firefox-ios/Client/Application/AccessibilityIdentifiers.swift +++ b/firefox-ios/Client/Application/AccessibilityIdentifiers.swift @@ -649,6 +649,7 @@ struct AccessibilityIdentifiers { struct Addresses { static let title = "Addresses" static let addAddress = "Add address" + static let addressCell = "AddressCell" } } diff --git a/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift b/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift index 769f5bb119495..ac3f07468eceb 100644 --- a/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift +++ b/firefox-ios/Client/Frontend/Autofill/Address/AddressCellView.swift @@ -110,6 +110,8 @@ struct AddressCellView: View { .onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in isLandscape = UIDevice.current.orientation.isLandscape } + .accessibilityElement(children: .ignore) + .accessibilityIdentifier(AccessibilityIdentifiers.Settings.Address.Addresses.addressCell) .accessibilityLabel(address.a11ySettingsRow) .accessibilityAddTraits(.isButton) .accessibilityAction { onTap() } diff --git a/firefox-ios/firefox-ios-tests/Tests/XCUITests/PageScreens/AddressScreen.swift b/firefox-ios/firefox-ios-tests/Tests/XCUITests/PageScreens/AddressScreen.swift index cc5f9eccb3f5c..06b14ffd5d1da 100644 --- a/firefox-ios/firefox-ios-tests/Tests/XCUITests/PageScreens/AddressScreen.swift +++ b/firefox-ios/firefox-ios-tests/Tests/XCUITests/PageScreens/AddressScreen.swift @@ -57,7 +57,7 @@ final class AddressScreen { } func reachEditAndRemoveAddress() { - app.collectionViews.cells.buttons.staticTexts.firstMatch.tapWithRetry() + app.collectionViews.cells.buttons[AccessibilityIdentifiers.Settings.Address.Addresses.addressCell].tapWithRetry() // Update the all addresses fields let buttonEdit = sel.BUTTON_EDIT.element(in: app) buttonEdit.waitAndTap()