Rewrite PasswordViewController
This commit is contained in:
parent
372e897350
commit
68077bf04c
10 changed files with 676 additions and 729 deletions
117
pass/Services/PasswordNavigationDataSource.swift
Normal file
117
pass/Services/PasswordNavigationDataSource.swift
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
//
|
||||
// PasswordNavigationDataSource.swift
|
||||
// pass
|
||||
//
|
||||
// Created by Sun, Mingshen on 1/16/21.
|
||||
// Copyright © 2021 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import passKit
|
||||
|
||||
struct Section {
|
||||
var title: String
|
||||
var entries: [PasswordTableEntry]
|
||||
}
|
||||
|
||||
class PasswordNavigationDataSource: NSObject, UITableViewDataSource {
|
||||
var sections: [Section]
|
||||
var filteredSections: [Section]
|
||||
|
||||
var isSearchActive = false
|
||||
var cellGestureRecognizer: UIGestureRecognizer?
|
||||
|
||||
let hideSectionHeaderThreshold = 6
|
||||
|
||||
init(entries: [PasswordTableEntry] = []) {
|
||||
sections = buildSections(from: entries)
|
||||
filteredSections = sections
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
filteredSections[section].entries.count
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
showSectionTitles() ? filteredSections[section].title : nil
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int {
|
||||
index
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "passwordTableViewCell", for: indexPath) as! PasswordTableViewCell
|
||||
let entry = getPasswordTableEntry(at: indexPath)
|
||||
cell.configure(with: entry)
|
||||
|
||||
if let gestureRecognizer = cellGestureRecognizer, !entry.isDir {
|
||||
cell.addGestureRecognizer(gestureRecognizer)
|
||||
}
|
||||
return cell
|
||||
}
|
||||
|
||||
func numberOfSections(in tableView: UITableView) -> Int {
|
||||
filteredSections.count
|
||||
}
|
||||
|
||||
func sectionIndexTitles(for _: UITableView) -> [String]? {
|
||||
showSectionTitles() ? filteredSections.map(\.title) : nil
|
||||
}
|
||||
|
||||
func showSectionTitles() -> Bool {
|
||||
!isSearchActive && filteredSections.count > hideSectionHeaderThreshold
|
||||
}
|
||||
|
||||
func getPasswordTableEntry(at indexPath: IndexPath) -> PasswordTableEntry {
|
||||
filteredSections[indexPath.section].entries[indexPath.row]
|
||||
}
|
||||
|
||||
func showTableEntries(matching text: String) {
|
||||
guard !text.isEmpty else {
|
||||
filteredSections = sections
|
||||
return
|
||||
}
|
||||
|
||||
filteredSections = sections.map { section in
|
||||
let entries = section.entries.filter { $0.match(text) }
|
||||
return Section(title: section.title, entries: entries)
|
||||
}
|
||||
.filter { !$0.entries.isEmpty }
|
||||
}
|
||||
|
||||
func showUnsyncedTableEntries() {
|
||||
filteredSections = sections.map { section in
|
||||
let entries = section.entries.filter { !$0.synced }
|
||||
return Section(title: section.title, entries: entries)
|
||||
}
|
||||
.filter { !$0.entries.isEmpty }
|
||||
}
|
||||
}
|
||||
|
||||
private func buildSections(from entries: [PasswordTableEntry]) -> [Section] {
|
||||
let collation = UILocalizedIndexedCollation.current()
|
||||
let sectionTitles = collation.sectionIndexTitles
|
||||
var sections = [Section]()
|
||||
|
||||
// initialize all sections
|
||||
for titleNumber in 0 ..< sectionTitles.count {
|
||||
sections.append(Section(title: sectionTitles[titleNumber], entries: [PasswordTableEntry]()))
|
||||
}
|
||||
|
||||
// put entries into sections
|
||||
for entry in entries {
|
||||
let sectionNumber = collation.section(for: entry, collationStringSelector: #selector(getter: PasswordTableEntry.title))
|
||||
sections[sectionNumber].entries.append(entry)
|
||||
}
|
||||
|
||||
// sort each list and set sectionTitles
|
||||
for titleNumber in 0 ..< sectionTitles.count {
|
||||
let entriesToSort = sections[titleNumber].entries
|
||||
let sortedEntries = collation.sortedArray(from: entriesToSort, collationStringSelector: #selector(getter: PasswordTableEntry.title))
|
||||
sections[titleNumber].entries = sortedEntries as! [PasswordTableEntry]
|
||||
}
|
||||
|
||||
// only keep non-empty sections
|
||||
return sections.filter { !$0.entries.isEmpty }
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue