From 984450af50e6f2f0d0943d3014150f77ceff2315 Mon Sep 17 00:00:00 2001 From: Brianna Birman Date: Wed, 8 Jan 2025 11:52:17 -0800 Subject: [PATCH 1/2] Add labels and resizing to fields for accessibility on add connection screen --- .../project.pbxproj | 12 +- .../Login/LoginHost/NewLoginHostView.swift | 110 +++++++++++++++ .../SFSDKLoginHostListViewController.m | 10 +- .../SFSDKNewLoginHostViewController.h | 56 -------- .../SFSDKNewLoginHostViewController.m | 133 ------------------ .../en.lproj/Localizable.strings | 6 +- 6 files changed, 124 insertions(+), 203 deletions(-) create mode 100644 libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Login/LoginHost/NewLoginHostView.swift delete mode 100644 libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Login/LoginHost/SFSDKNewLoginHostViewController.h delete mode 100644 libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Login/LoginHost/SFSDKNewLoginHostViewController.m diff --git a/libs/SalesforceSDKCore/SalesforceSDKCore.xcodeproj/project.pbxproj b/libs/SalesforceSDKCore/SalesforceSDKCore.xcodeproj/project.pbxproj index e217fbac22..d7b8812ae1 100644 --- a/libs/SalesforceSDKCore/SalesforceSDKCore.xcodeproj/project.pbxproj +++ b/libs/SalesforceSDKCore/SalesforceSDKCore.xcodeproj/project.pbxproj @@ -79,6 +79,7 @@ 6938392723C82F38008E8E9A /* SFSDKNullURLCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 6938392523C82F38008E8E9A /* SFSDKNullURLCache.m */; }; 693E623124A287DB0017B222 /* KeyValueEncryptedFileStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693E623024A287DB0017B222 /* KeyValueEncryptedFileStore.swift */; }; 693E623B24A29B6B0017B222 /* SFSDKKeyValueEncryptedFileStoreTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 693E623A24A29B6B0017B222 /* SFSDKKeyValueEncryptedFileStoreTests.m */; }; + 6941BE662D2F0E1B00CEC59B /* NewLoginHostView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6941BE652D2F0E1B00CEC59B /* NewLoginHostView.swift */; }; 694490D025B8F4C4007747CD /* SFSDKWindowManager+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 694490C725B8E567007747CD /* SFSDKWindowManager+Internal.h */; }; 695E86A829EE24D0002BDEA6 /* SPConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 695E86A729EE24D0002BDEA6 /* SPConfig.swift */; }; 695E86B929EF8D6E002BDEA6 /* SFSDKIDPAuthCodeLoginRequestCommand.h in Headers */ = {isa = PBXBuildFile; fileRef = 695E86B729EF8D6E002BDEA6 /* SFSDKIDPAuthCodeLoginRequestCommand.h */; }; @@ -399,8 +400,6 @@ E1C80CF01C5AEE31001B3A21 /* SFSDKLoginHostListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E1C80CE51C5AEE31001B3A21 /* SFSDKLoginHostListViewController.m */; }; E1C80CF11C5AEE31001B3A21 /* SFSDKLoginHostStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = E1C80CE61C5AEE31001B3A21 /* SFSDKLoginHostStorage.h */; settings = {ATTRIBUTES = (Public, ); }; }; E1C80CF21C5AEE31001B3A21 /* SFSDKLoginHostStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = E1C80CE71C5AEE31001B3A21 /* SFSDKLoginHostStorage.m */; }; - E1C80CF31C5AEE31001B3A21 /* SFSDKNewLoginHostViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = E1C80CE81C5AEE31001B3A21 /* SFSDKNewLoginHostViewController.h */; }; - E1C80CF41C5AEE31001B3A21 /* SFSDKNewLoginHostViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E1C80CE91C5AEE31001B3A21 /* SFSDKNewLoginHostViewController.m */; }; E1C80CF51C5AEE31001B3A21 /* SFSDKTextFieldTableViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = E1C80CEA1C5AEE31001B3A21 /* SFSDKTextFieldTableViewCell.h */; }; E1C80CF61C5AEE31001B3A21 /* SFSDKTextFieldTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E1C80CEB1C5AEE31001B3A21 /* SFSDKTextFieldTableViewCell.m */; }; E1C80D081C5AF029001B3A21 /* SalesforceSDKAssets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E1C80D071C5AF029001B3A21 /* SalesforceSDKAssets.xcassets */; }; @@ -663,6 +662,7 @@ 6938392523C82F38008E8E9A /* SFSDKNullURLCache.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SFSDKNullURLCache.m; sourceTree = ""; }; 693E623024A287DB0017B222 /* KeyValueEncryptedFileStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyValueEncryptedFileStore.swift; sourceTree = ""; }; 693E623A24A29B6B0017B222 /* SFSDKKeyValueEncryptedFileStoreTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SFSDKKeyValueEncryptedFileStoreTests.m; path = SalesforceSDKCoreTests/SFSDKKeyValueEncryptedFileStoreTests.m; sourceTree = SOURCE_ROOT; }; + 6941BE652D2F0E1B00CEC59B /* NewLoginHostView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = NewLoginHostView.swift; path = Login/LoginHost/NewLoginHostView.swift; sourceTree = ""; }; 694490C725B8E567007747CD /* SFSDKWindowManager+Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SFSDKWindowManager+Internal.h"; sourceTree = ""; }; 695E86A729EE24D0002BDEA6 /* SPConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPConfig.swift; sourceTree = ""; }; 695E86B729EF8D6E002BDEA6 /* SFSDKIDPAuthCodeLoginRequestCommand.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SFSDKIDPAuthCodeLoginRequestCommand.h; sourceTree = ""; }; @@ -905,8 +905,6 @@ E1C80CE51C5AEE31001B3A21 /* SFSDKLoginHostListViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SFSDKLoginHostListViewController.m; path = Login/LoginHost/SFSDKLoginHostListViewController.m; sourceTree = ""; }; E1C80CE61C5AEE31001B3A21 /* SFSDKLoginHostStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SFSDKLoginHostStorage.h; path = Login/LoginHost/SFSDKLoginHostStorage.h; sourceTree = ""; }; E1C80CE71C5AEE31001B3A21 /* SFSDKLoginHostStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SFSDKLoginHostStorage.m; path = Login/LoginHost/SFSDKLoginHostStorage.m; sourceTree = ""; }; - E1C80CE81C5AEE31001B3A21 /* SFSDKNewLoginHostViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SFSDKNewLoginHostViewController.h; path = Login/LoginHost/SFSDKNewLoginHostViewController.h; sourceTree = ""; }; - E1C80CE91C5AEE31001B3A21 /* SFSDKNewLoginHostViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SFSDKNewLoginHostViewController.m; path = Login/LoginHost/SFSDKNewLoginHostViewController.m; sourceTree = ""; }; E1C80CEA1C5AEE31001B3A21 /* SFSDKTextFieldTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SFSDKTextFieldTableViewCell.h; path = Login/LoginHost/SFSDKTextFieldTableViewCell.h; sourceTree = ""; }; E1C80CEB1C5AEE31001B3A21 /* SFSDKTextFieldTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SFSDKTextFieldTableViewCell.m; path = Login/LoginHost/SFSDKTextFieldTableViewCell.m; sourceTree = ""; }; E1C80D071C5AF029001B3A21 /* SalesforceSDKAssets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = SalesforceSDKAssets.xcassets; path = ../../shared/resources/SalesforceSDKAssets.xcassets; sourceTree = ""; }; @@ -1648,6 +1646,7 @@ E13950A21C53620B00575C03 /* LoginHost */ = { isa = PBXGroup; children = ( + 6941BE652D2F0E1B00CEC59B /* NewLoginHostView.swift */, E1C80CE11C5AEE31001B3A21 /* SFSDKLoginHost.h */, E1C80CE21C5AEE31001B3A21 /* SFSDKLoginHost.m */, E1C80CE31C5AEE31001B3A21 /* SFSDKLoginHostDelegate.h */, @@ -1655,8 +1654,6 @@ E1C80CE51C5AEE31001B3A21 /* SFSDKLoginHostListViewController.m */, E1C80CE61C5AEE31001B3A21 /* SFSDKLoginHostStorage.h */, E1C80CE71C5AEE31001B3A21 /* SFSDKLoginHostStorage.m */, - E1C80CE81C5AEE31001B3A21 /* SFSDKNewLoginHostViewController.h */, - E1C80CE91C5AEE31001B3A21 /* SFSDKNewLoginHostViewController.m */, E1C80CEA1C5AEE31001B3A21 /* SFSDKTextFieldTableViewCell.h */, E1C80CEB1C5AEE31001B3A21 /* SFSDKTextFieldTableViewCell.m */, ); @@ -1698,7 +1695,6 @@ CE4CE3991C0E5272009F6029 /* SFSDKAsyncProcessListener.h in Headers */, CE4CE3251C0E523B009F6029 /* UIScreen+SFAdditions.h in Headers */, CE4CE38E1C0E526A009F6029 /* SFUserAccount.h in Headers */, - E1C80CF31C5AEE31001B3A21 /* SFSDKNewLoginHostViewController.h in Headers */, B7FB26C71F78094A00FB25A2 /* SFSDKUserSelectionTableViewController.h in Headers */, B72171562353BFF20022510F /* SFSDKAuthRequest.h in Headers */, CE4CE33E1C0E524B009F6029 /* SFInstrumentation.h in Headers */, @@ -2269,7 +2265,6 @@ B7A6ED32236A3F8600DBA451 /* UserAccountManager.swift in Sources */, CE4CE3241C0E523B009F6029 /* UIDevice+SFHardware.m in Sources */, CE675A381E0B2CC6002DBF5A /* SFSDKSoslReturningBuilder.m in Sources */, - E1C80CF41C5AEE31001B3A21 /* SFSDKNewLoginHostViewController.m in Sources */, CE4CE3281C0E523B009F6029 /* NSData+SFSDKUtils.m in Sources */, CED452BD1D808D0C009266EB /* SFRestAPI+QueryBuilder.m in Sources */, B71129111F8A780800436CFB /* SFSDKAlertMessageBuilder.m in Sources */, @@ -2295,6 +2290,7 @@ B7460C1C2347E1A100C7512E /* SFSDKBatchResponse.m in Sources */, A3C7476129F709EB00D72B7F /* BiometricAuthenticationManagerInternal.swift in Sources */, B7FB26DB1F78096300FB25A2 /* SFSDKIDPErrorHandler.m in Sources */, + 6941BE662D2F0E1B00CEC59B /* NewLoginHostView.swift in Sources */, B7677051223AE5E400545C90 /* SFUserAccountManager+Instrumentation.m in Sources */, E1C80CF01C5AEE31001B3A21 /* SFSDKLoginHostListViewController.m in Sources */, B773CCF81F8200BD00D2D1B2 /* SFSDKIDPLoginRequestCommand.m in Sources */, diff --git a/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Login/LoginHost/NewLoginHostView.swift b/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Login/LoginHost/NewLoginHostView.swift new file mode 100644 index 0000000000..eddf2efa70 --- /dev/null +++ b/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Login/LoginHost/NewLoginHostView.swift @@ -0,0 +1,110 @@ +// +// NewLoginHostView.swift +// SalesforceSDKCore +// +// Created by Brianna Birman on 12/19/24. +// Copyright (c) 2024-present, salesforce.com, inc. All rights reserved. +// +// Redistribution and use of this software in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright notice, this list of conditions +// and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, this list of +// conditions and the following disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of salesforce.com, inc. nor the names of its contributors may be used to +// endorse or promote products derived from this software without specific prior written +// permission of salesforce.com, inc. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY +// WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import SwiftUI + + +@objc(SFSDKNewLoginHostViewController) +class NewLoginHostViewController: NSObject { + @objc public static func viewController(saveAction: @escaping ((String, String?) -> Void)) -> UIViewController { + let view = NewLoginHostView(saveAction: saveAction) + return UIHostingController(rootView: view) + } +} + +struct NewLoginHostField: View { + let fieldLabel: String + let fieldPlaceholder: String + @Binding var fieldValue: String + + var body: some View { + VStack(alignment: .leading, spacing: 5) { + Text(fieldLabel) + TextField(fieldPlaceholder, text: $fieldValue) + .autocorrectionDisabled() + .padding() + .background( + RoundedRectangle(cornerSize: CGSize(width: 10, height: 10)) + .stroke(Color(uiColor: .label), lineWidth: 0.5) + ) + } + } +} + +struct NewLoginHostView: View { + @State var host = "" + @State var label = "" + private var saveAction: ((String, String?) -> Void) + + init(saveAction: @escaping ((String, String?) -> Void)) { + self.saveAction = saveAction + } + + func save() { + var hostToSave = host.trimmingCharacters(in: .whitespaces) + if let httpsRange = hostToSave.range(of: "://") { + hostToSave = String(host[...httpsRange.upperBound]) + } + saveAction(hostToSave, label.trimmingCharacters(in: .whitespaces)) + } + + var body: some View { + List { + NewLoginHostField(fieldLabel: SFSDKResourceUtils.localizedString("LOGIN_SERVER_URL"), + fieldPlaceholder: SFSDKResourceUtils.localizedString("LOGIN_SERVER_URL_PLACEHOLDER"), + fieldValue: $host) + .keyboardType(.URL) + .autocapitalization(.none) + .listRowSeparator(.hidden) + + NewLoginHostField(fieldLabel: SFSDKResourceUtils.localizedString("LOGIN_SERVER_NAME"), + fieldPlaceholder: SFSDKResourceUtils.localizedString("LOGIN_SERVER_NAME_PLACEHOLDER"), + fieldValue: $label) + .listRowSeparator(.hidden) + .padding(.bottom) + } + + .background(Color(uiColor: .secondarySystemBackground)) + .scrollDisabled(true) + .listStyle(.plain) + .navigationTitle(SFSDKResourceUtils.localizedString("LOGIN_ADD_SERVER")) + .toolbar { + ToolbarItemGroup(placement: .topBarTrailing) { + Button { + save() + } label: { + Text("Done").bold() + } + .disabled(host.trimmingCharacters(in: .whitespaces).isEmpty) + } + }.tint(.white) + } +} + +#Preview { + NewLoginHostView {_,_ in } +} diff --git a/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Login/LoginHost/SFSDKLoginHostListViewController.m b/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Login/LoginHost/SFSDKLoginHostListViewController.m index 77eeeee342..d6af40e637 100644 --- a/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Login/LoginHost/SFSDKLoginHostListViewController.m +++ b/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Login/LoginHost/SFSDKLoginHostListViewController.m @@ -27,13 +27,14 @@ */ #import "SFSDKLoginHostListViewController.h" -#import "SFSDKNewLoginHostViewController.h" #import "SFSDKLoginHostStorage.h" #import "SFSDKLoginHost.h" #import "SFSDKResourceUtils.h" #import "SFManagedPreferences.h" #import "SFUserAccountManager.h" #import "SFSDKViewUtils.h" +#import + static NSString * const SFDCLoginHostListCellIdentifier = @"SFDCLoginHostListCellIdentifier"; @interface SFSDKLoginHostListViewController () @@ -98,9 +99,10 @@ - (void)showAddLoginHost { * Invoked when the user presses the Add button. This method presents the new login host view. */ - (void)showAddLoginHost:(id)sender { - SFSDKNewLoginHostViewController *detailViewController = [[SFSDKNewLoginHostViewController alloc] initWithStyle:UITableViewStyleGrouped]; - detailViewController.loginHostListViewController = self; - + UIViewController *detailViewController = [SFSDKNewLoginHostViewController viewControllerWithSaveAction:^(NSString * _Nonnull host, NSString * _Nullable label) { + [self addLoginHost:[SFSDKLoginHost hostWithName:label host:host deletable:YES]]; + }]; + if ([self.delegate respondsToSelector:@selector(hostListViewController:willPresentLoginHostViewController:)]) { [self.delegate hostListViewController:self willPresentLoginHostViewController:self]; } diff --git a/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Login/LoginHost/SFSDKNewLoginHostViewController.h b/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Login/LoginHost/SFSDKNewLoginHostViewController.h deleted file mode 100644 index 91e743fe71..0000000000 --- a/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Login/LoginHost/SFSDKNewLoginHostViewController.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - SFSDKNewLoginHostViewController.h - SalesforceSDKCore - - Created by Kunal Chitalia on 1/22/16. - Copyright (c) 2016-present, salesforce.com, inc. All rights reserved. - - Redistribution and use of this software in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, this list of conditions - and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, this list of - conditions and the following disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of salesforce.com, inc. nor the names of its contributors may be used to - endorse or promote products derived from this software without specific prior written - permission of salesforce.com, inc. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY - WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import - -NS_ASSUME_NONNULL_BEGIN - -@class SFSDKLoginHostListViewController; - -/** - * View controller that allows the user to enter a new login host that contains - * a host (the server address) and an optional name. - */ -@interface SFSDKNewLoginHostViewController : UITableViewController - -/** The server text field -*/ -@property (nonatomic, strong) UITextField *server; - -/** The name text field -*/ -@property (nonatomic, strong) UITextField *name; - -/** A reference to the login host list view controller used to add the host to the list of login hosts - and to also properly resize the popover controller. - */ -@property (nonatomic, weak) SFSDKLoginHostListViewController *loginHostListViewController; - -@end - -NS_ASSUME_NONNULL_END diff --git a/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Login/LoginHost/SFSDKNewLoginHostViewController.m b/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Login/LoginHost/SFSDKNewLoginHostViewController.m deleted file mode 100644 index 33dd15fc56..0000000000 --- a/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Login/LoginHost/SFSDKNewLoginHostViewController.m +++ /dev/null @@ -1,133 +0,0 @@ -/* - SFSDKNewLoginHostViewController.m - SalesforceSDKCore - - Created by Kunal Chitalia on 1/22/16. - Copyright (c) 2016-present, salesforce.com, inc. All rights reserved. - - Redistribution and use of this software in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, this list of conditions - and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, this list of - conditions and the following disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of salesforce.com, inc. nor the names of its contributors may be used to - endorse or promote products derived from this software without specific prior written - permission of salesforce.com, inc. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY - WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#import "SFSDKNewLoginHostViewController.h" -#import "SFSDKLoginHostListViewController.h" -#import "SFSDKLoginHost.h" -#import "SFSDKTextFieldTableViewCell.h" -#import "SFSDKResourceUtils.h" - -@implementation SFSDKNewLoginHostViewController - -static NSString * const SFSDKNewLoginHostCellIdentifier = @"SFSDKNewLoginHostCellIdentifier"; - -#pragma mark - View lifecycle - -- (void)viewDidLoad { - [super viewDidLoad]; - [self setEdgesForExtendedLayout:UIRectEdgeNone]; - self.tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, self.tableView.bounds.size.width, 0.01f)]; - self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, self.tableView.bounds.size.width, 0.01f)]; - - // Disable the scroll because there is enough space - // on both the iPhone and iPad to display the two editing rows. - self.tableView.scrollEnabled = NO; - self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone - target:self action:@selector(addNewServer:)]; - self.navigationItem.rightBarButtonItem.enabled = NO; - self.title = [SFSDKResourceUtils localizedString:@"LOGIN_ADD_SERVER"]; - [self.tableView registerClass:[SFSDKTextFieldTableViewCell class] forCellReuseIdentifier:SFSDKNewLoginHostCellIdentifier]; -} - -- (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - - // Set the size of this view so any popover controller will resize to fit - CGRect r = [self.tableView rectForSection:0]; - CGSize size = CGSizeMake(380, r.size.height); - self.preferredContentSize = size; - self.loginHostListViewController.preferredContentSize = size; - self.preferredContentSize = size; - - // Make sure to also set the content size of the other view controller, otherwise the popover won't - // resize if this view is smaller than the previous view. - self.loginHostListViewController.preferredContentSize = size; -} - -#pragma mark - Actions - -/** - * Invoked when the user taps on the done button to add the login host to the list of hosts. - */ -- (void)addNewServer:(id)sender { - NSString *hostName = [self.name.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; - NSString *host = [self.server.text stringByTrimmingCharactersInSet: - [NSCharacterSet whitespaceCharacterSet]]; - NSRange httpsRange = [host rangeOfString:@"://"]; - if (host && httpsRange.length > 0) { - host = [host substringFromIndex:httpsRange.location + httpsRange.length]; - } - [self.loginHostListViewController addLoginHost:[SFSDKLoginHost hostWithName:hostName host:host deletable:YES]]; -} - -#pragma mark - Table view data source - -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return 1; -} - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return 2; // One row for the host and one for the name -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - SFSDKTextFieldTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SFSDKNewLoginHostCellIdentifier forIndexPath:indexPath]; - cell.accessoryType = UITableViewCellAccessoryNone; - cell.selectionStyle = UITableViewCellSelectionStyleNone; - cell.textField.autocorrectionType = UITextAutocorrectionTypeNo; - cell.textField.delegate = self; - cell.textField.tag = indexPath.row; - - // Create the text field for each specific row. - if (0 == indexPath.row) { - cell.textField.placeholder = [SFSDKResourceUtils localizedString:@"LOGIN_SERVER_URL"]; - cell.textField.keyboardType = UIKeyboardTypeURL; - cell.textField.autocapitalizationType = UITextAutocapitalizationTypeNone; - self.server = cell.textField; - [cell.textField becomeFirstResponder]; - } else { - cell.textField.placeholder = [SFSDKResourceUtils localizedString:@"LOGIN_SERVER_NAME"]; - cell.textField.keyboardType = UIKeyboardTypeDefault; - self.name = cell.textField; - } - return cell; -} - -#pragma mark - Text field delegate - -- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { - - // Enable the Done button only if there is something in the URL field - if (textField == self.server) { - NSString *resultingString = [textField.text stringByReplacingCharactersInRange:range withString:string]; - self.navigationItem.rightBarButtonItem.enabled = [resultingString length] > 0; - } - return YES; -} - -@end diff --git a/shared/resources/SalesforceSDKResources.bundle/en.lproj/Localizable.strings b/shared/resources/SalesforceSDKResources.bundle/en.lproj/Localizable.strings index abac4ed3c7..8df85529c9 100644 --- a/shared/resources/SalesforceSDKResources.bundle/en.lproj/Localizable.strings +++ b/shared/resources/SalesforceSDKResources.bundle/en.lproj/Localizable.strings @@ -59,8 +59,10 @@ "LOGIN_SERVER_SANDBOX" = "Sandbox"; "LOGIN_CHOOSE_SERVER" = "Choose Connection"; "LOGIN_ADD_SERVER" = "Add Connection"; -"LOGIN_SERVER_URL" = "Host (Example: login.salesforce.com)"; -"LOGIN_SERVER_NAME" = "Label (Optional)"; +"LOGIN_SERVER_URL" = "Host"; +"LOGIN_SERVER_NAME" = "Label"; +"LOGIN_SERVER_URL_PLACEHOLDER" = "Example: login.salesforce.com"; +"LOGIN_SERVER_NAME_PLACEHOLDER" = "Optional"; //Account Switcher "ACCOUNT_SWITCHER_TITLE" = "Manage Accounts"; From 62003221d323ff723ff090016c06dbe71237743a Mon Sep 17 00:00:00 2001 From: Brianna Birman Date: Wed, 8 Jan 2025 15:58:35 -0800 Subject: [PATCH 2/2] Add localizable string for done button --- .../Classes/Login/LoginHost/NewLoginHostView.swift | 2 +- .../SalesforceSDKResources.bundle/en.lproj/Localizable.strings | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Login/LoginHost/NewLoginHostView.swift b/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Login/LoginHost/NewLoginHostView.swift index eddf2efa70..c08aef420b 100644 --- a/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Login/LoginHost/NewLoginHostView.swift +++ b/libs/SalesforceSDKCore/SalesforceSDKCore/Classes/Login/LoginHost/NewLoginHostView.swift @@ -97,7 +97,7 @@ struct NewLoginHostView: View { Button { save() } label: { - Text("Done").bold() + Text(SFSDKResourceUtils.localizedString("DONE_BUTTON")).bold() } .disabled(host.trimmingCharacters(in: .whitespaces).isEmpty) } diff --git a/shared/resources/SalesforceSDKResources.bundle/en.lproj/Localizable.strings b/shared/resources/SalesforceSDKResources.bundle/en.lproj/Localizable.strings index 8df85529c9..5e45960225 100644 --- a/shared/resources/SalesforceSDKResources.bundle/en.lproj/Localizable.strings +++ b/shared/resources/SalesforceSDKResources.bundle/en.lproj/Localizable.strings @@ -63,6 +63,7 @@ "LOGIN_SERVER_NAME" = "Label"; "LOGIN_SERVER_URL_PLACEHOLDER" = "Example: login.salesforce.com"; "LOGIN_SERVER_NAME_PLACEHOLDER" = "Optional"; +"DONE_BUTTON" = "Done"; //Account Switcher "ACCOUNT_SWITCHER_TITLE" = "Manage Accounts";