Add suggested passwords in AutoFill
This commit is contained in:
parent
156588bd93
commit
d4669bbfcb
4 changed files with 94 additions and 6 deletions
|
|
@ -17,13 +17,13 @@
|
|||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="XmI-l4-SgT">
|
||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="XmI-l4-SgT">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="passwordTableViewCell" textLabel="U0x-8f-AET" detailTextLabel="kY1-Ac-C3d" style="IBUITableViewCellStyleValue1" id="fXA-SG-IOe" customClass="PasswordTableViewCell" customModule="passAutoFillExtension" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="28" width="375" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="55.5" width="375" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="fXA-SG-IOe" id="KPa-Az-i6V">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ class CredentialProviderViewController: ASCredentialProviderViewController {
|
|||
override func prepareCredentialList(for serviceIdentifiers: [ASCredentialServiceIdentifier]) {
|
||||
let url = serviceIdentifiers.first.flatMap { URL(string: $0.identifier) }
|
||||
passwordsViewController.navigationItem.prompt = url?.host
|
||||
let keywords = url?.host?.sanitizedDomain?.components(separatedBy: ".") ?? []
|
||||
passwordsViewController.showPasswordsWithSuggstion(keywords)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -50,3 +52,14 @@ extension CredentialProviderViewController: PasswordSelectionDelegate {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension String {
|
||||
var sanitizedDomain: String? {
|
||||
replacingOccurrences(of: ".com", with: "")
|
||||
.replacingOccurrences(of: ".org", with: "")
|
||||
.replacingOccurrences(of: ".edu", with: "")
|
||||
.replacingOccurrences(of: ".net", with: "")
|
||||
.replacingOccurrences(of: ".gov", with: "")
|
||||
.replacingOccurrences(of: "www.", with: "")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,18 +27,27 @@ class PasswordsViewController: UIViewController {
|
|||
return uiSearchController
|
||||
}()
|
||||
|
||||
lazy var searchBar: UISearchBar = {
|
||||
self.searchController.searchBar
|
||||
}()
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
navigationItem.searchController = searchController
|
||||
navigationItem.hidesSearchBarWhenScrolling = false
|
||||
|
||||
searchController.searchBar.delegate = self
|
||||
searchBar.delegate = self
|
||||
|
||||
tableView.delegate = self
|
||||
tableView.dataSource = dataSource
|
||||
}
|
||||
|
||||
func showPasswordsWithSuggstion(_ keywords: [String]) {
|
||||
dataSource.showTableEntriesWithSuggestion(matching: keywords)
|
||||
tableView.reloadData()
|
||||
}
|
||||
|
||||
@IBAction
|
||||
private func cancel(_: AnyObject?) {
|
||||
self.extensionContext?.cancelRequest(withError: NSError(domain: ASExtensionErrorDomain, code: ASExtensionError.userCanceled.rawValue))
|
||||
|
|
|
|||
|
|
@ -12,20 +12,69 @@ import passKit
|
|||
class PasswordsTableDataSource: NSObject, UITableViewDataSource {
|
||||
var passwordTableEntries: [PasswordTableEntry]
|
||||
var filteredPasswordsTableEntries: [PasswordTableEntry]
|
||||
var suggestedPasswordsTableEntries: [PasswordTableEntry]
|
||||
var otherPasswordsTableEntries: [PasswordTableEntry]
|
||||
|
||||
var showSuggestion: Bool = false
|
||||
|
||||
init(entries: [PasswordTableEntry] = []) {
|
||||
passwordTableEntries = entries
|
||||
filteredPasswordsTableEntries = passwordTableEntries
|
||||
suggestedPasswordsTableEntries = []
|
||||
otherPasswordsTableEntries = []
|
||||
}
|
||||
|
||||
func numberOfSections(in tableView: UITableView) -> Int {
|
||||
if !showSuggestion {
|
||||
return 1
|
||||
} else {
|
||||
return 2
|
||||
}
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
filteredPasswordsTableEntries.count
|
||||
if !showSuggestion {
|
||||
return filteredPasswordsTableEntries.count
|
||||
}
|
||||
|
||||
if section == 0 {
|
||||
return suggestedPasswordsTableEntries.count
|
||||
} else {
|
||||
return otherPasswordsTableEntries.count
|
||||
}
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
if suggestedPasswordsTableEntries.isEmpty {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !showSuggestion {
|
||||
return "All Passwords"
|
||||
}
|
||||
|
||||
if section == 0 {
|
||||
return "Suggested Passwords"
|
||||
} else {
|
||||
return "Other Passwords"
|
||||
}
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "passwordTableViewCell", for: indexPath) as! PasswordTableViewCell
|
||||
|
||||
let entry = filteredPasswordsTableEntries[indexPath.row]
|
||||
var entry: PasswordTableEntry!
|
||||
if !showSuggestion {
|
||||
entry = filteredPasswordsTableEntries[indexPath.row]
|
||||
cell.configure(with: entry)
|
||||
return cell
|
||||
}
|
||||
|
||||
if indexPath.section == 0 {
|
||||
entry = suggestedPasswordsTableEntries[indexPath.row]
|
||||
} else {
|
||||
entry = otherPasswordsTableEntries[indexPath.row]
|
||||
}
|
||||
cell.configure(with: entry)
|
||||
|
||||
return cell
|
||||
|
|
@ -34,9 +83,26 @@ class PasswordsTableDataSource: NSObject, UITableViewDataSource {
|
|||
func showTableEntries(matching text: String) {
|
||||
guard !text.isEmpty else {
|
||||
filteredPasswordsTableEntries = passwordTableEntries
|
||||
showSuggestion = true
|
||||
return
|
||||
}
|
||||
|
||||
filteredPasswordsTableEntries = passwordTableEntries.filter { $0.match(text) }
|
||||
showSuggestion = false
|
||||
}
|
||||
|
||||
func showTableEntriesWithSuggestion(matching keywords: [String]) {
|
||||
for entry in passwordTableEntries {
|
||||
var match = false
|
||||
for keyword in keywords {
|
||||
match = match || entry.match(keyword)
|
||||
}
|
||||
if match {
|
||||
suggestedPasswordsTableEntries.append(entry)
|
||||
} else {
|
||||
otherPasswordsTableEntries.append(entry)
|
||||
}
|
||||
}
|
||||
showSuggestion = !suggestedPasswordsTableEntries.isEmpty
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue