support edit password
This commit is contained in:
parent
41d45bfbf9
commit
b2ee8c429f
14 changed files with 459 additions and 72 deletions
|
|
@ -55,6 +55,9 @@
|
|||
DCFB779F1E4F40C7008DE471 /* FillPasswordTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = DCFB779D1E4F40C7008DE471 /* FillPasswordTableViewCell.xib */; };
|
||||
DCFB77A11E4F68C8008DE471 /* PasswordEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFB77A01E4F68C8008DE471 /* PasswordEntity.swift */; };
|
||||
DCFB77A31E500D9C008DE471 /* PasswordDetailTitleTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = DCFB77A21E500D9C008DE471 /* PasswordDetailTitleTableViewCell.xib */; };
|
||||
DCFB77A71E502DF9008DE471 /* EditPasswordTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFB77A61E502DF9008DE471 /* EditPasswordTableViewController.swift */; };
|
||||
DCFB77A91E502FF6008DE471 /* PasswordEditorTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFB77A81E502FF6008DE471 /* PasswordEditorTableViewController.swift */; };
|
||||
DCFB77AB1E503729008DE471 /* ContentTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFB77AA1E503729008DE471 /* ContentTableViewCell.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
|
|
@ -111,6 +114,9 @@
|
|||
DCFB779D1E4F40C7008DE471 /* FillPasswordTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = FillPasswordTableViewCell.xib; sourceTree = "<group>"; };
|
||||
DCFB77A01E4F68C8008DE471 /* PasswordEntity.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordEntity.swift; sourceTree = "<group>"; };
|
||||
DCFB77A21E500D9C008DE471 /* PasswordDetailTitleTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PasswordDetailTitleTableViewCell.xib; sourceTree = "<group>"; };
|
||||
DCFB77A61E502DF9008DE471 /* EditPasswordTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditPasswordTableViewController.swift; sourceTree = "<group>"; };
|
||||
DCFB77A81E502FF6008DE471 /* PasswordEditorTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordEditorTableViewController.swift; sourceTree = "<group>"; };
|
||||
DCFB77AA1E503729008DE471 /* ContentTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentTableViewCell.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
|
@ -144,6 +150,8 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
DC037CB71E4DD1A500609409 /* AddPasswordTableViewController.swift */,
|
||||
DCFB77A81E502FF6008DE471 /* PasswordEditorTableViewController.swift */,
|
||||
DCFB77A61E502DF9008DE471 /* EditPasswordTableViewController.swift */,
|
||||
DC037CB11E4CAB1700609409 /* AboutRepositoryTableViewController.swift */,
|
||||
DC037CAF1E4CA51F00609409 /* GeneralSettingsTableViewController.swift */,
|
||||
DC962CDE1E4B62C10033B5D8 /* AboutTableViewController.swift */,
|
||||
|
|
@ -201,6 +209,7 @@
|
|||
DCFB77A21E500D9C008DE471 /* PasswordDetailTitleTableViewCell.xib */,
|
||||
DC037CBD1E4ED4E100609409 /* TextViewTableViewCell.swift */,
|
||||
DC037CBE1E4ED4E100609409 /* TextViewTableViewCell.xib */,
|
||||
DCFB77AA1E503729008DE471 /* ContentTableViewCell.swift */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -408,10 +417,12 @@
|
|||
DC037CBF1E4ED4E100609409 /* TextViewTableViewCell.swift in Sources */,
|
||||
DC8963C01E38EEB900828B09 /* SSHKeySettingTableViewController.swift in Sources */,
|
||||
DC193FFA1E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift in Sources */,
|
||||
DCFB77AB1E503729008DE471 /* ContentTableViewCell.swift in Sources */,
|
||||
DCA0499C1E3362F400522E8F /* PGPKeySettingTableViewController.swift in Sources */,
|
||||
DC7E6EEA1E432E48006C2443 /* Password.swift in Sources */,
|
||||
DC4914961E434301007FF592 /* LabelTableViewCell.swift in Sources */,
|
||||
DCAAF7451E2FA66800AB94BC /* SettingsTableViewController.swift in Sources */,
|
||||
DCFB77A71E502DF9008DE471 /* EditPasswordTableViewController.swift in Sources */,
|
||||
DCA0499A1E335CC800522E8F /* GitServerSettingTableViewController.swift in Sources */,
|
||||
DCDDEAB31E4896BF00F68193 /* PasswordDetailTitleTableViewCell.swift in Sources */,
|
||||
DC037CAE1E4C9B9B00609409 /* PasswordRepositorySettingsTableViewController.swift in Sources */,
|
||||
|
|
@ -436,6 +447,7 @@
|
|||
DC19400B1E4B36B60077E0A3 /* Utils.swift in Sources */,
|
||||
DCA0499E1E33BAC100522E8F /* Globals.swift in Sources */,
|
||||
DCFB77A11E4F68C8008DE471 /* PasswordEntity.swift in Sources */,
|
||||
DCFB77A91E502FF6008DE471 /* PasswordEditorTableViewController.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -423,7 +423,7 @@
|
|||
<placeholder placeholderIdentifier="IBFirstResponder" id="7c1-c7-Qyp" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
<exit id="7K9-cE-9qq" userLabel="Exit" sceneMemberID="exit"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="6590" y="2127"/>
|
||||
<point key="canvasLocation" x="6084" y="2202"/>
|
||||
</scene>
|
||||
<!--Git Repository Authentication Setting Table View Controller-->
|
||||
<scene sceneID="xth-c9-Oea">
|
||||
|
|
@ -492,7 +492,7 @@
|
|||
<placeholder placeholderIdentifier="IBFirstResponder" id="e1d-uR-lAI" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
<exit id="MfG-VE-Ork" userLabel="Exit" sceneMemberID="exit"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="7583" y="2127"/>
|
||||
<point key="canvasLocation" x="7077" y="2202"/>
|
||||
</scene>
|
||||
<!--PGP Key-->
|
||||
<scene sceneID="8Hi-tl-elT">
|
||||
|
|
@ -624,7 +624,7 @@
|
|||
<placeholder placeholderIdentifier="IBFirstResponder" id="hbx-RC-qg1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
<exit id="jjl-Xi-fkn" userLabel="Exit" sceneMemberID="exit"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="5638" y="3511"/>
|
||||
<point key="canvasLocation" x="5132" y="3586"/>
|
||||
</scene>
|
||||
<!--Add Password-->
|
||||
<scene sceneID="738-Zk-wRb">
|
||||
|
|
@ -656,7 +656,7 @@
|
|||
<placeholder placeholderIdentifier="IBFirstResponder" id="6R0-BP-wo8" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
<exit id="rRf-7l-IGe" userLabel="Exit" sceneMemberID="exit"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="4869.5652173913049" y="268.20652173913044"/>
|
||||
<point key="canvasLocation" x="5132" y="-229"/>
|
||||
</scene>
|
||||
<!--Password Detail Table View Controller-->
|
||||
<scene sceneID="9wY-d0-fB1">
|
||||
|
|
@ -672,10 +672,13 @@
|
|||
<outlet property="delegate" destination="tW4-E9-CGv" id="7PQ-0M-SCC"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
<connections>
|
||||
<segue destination="eui-w4-P7T" kind="show" identifier="editPasswordSegue" id="Ydg-pZ-oNS"/>
|
||||
</connections>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="9sC-44-OKL" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="3961" y="982"/>
|
||||
<point key="canvasLocation" x="3987" y="601"/>
|
||||
</scene>
|
||||
<!--Passwords-->
|
||||
<scene sceneID="ACd-rk-Zf3">
|
||||
|
|
@ -734,6 +737,38 @@
|
|||
</objects>
|
||||
<point key="canvasLocation" x="1451" y="3510"/>
|
||||
</scene>
|
||||
<!--Edit Password Table View Controller-->
|
||||
<scene sceneID="NhX-bh-UBe">
|
||||
<objects>
|
||||
<tableViewController id="2RE-j0-dBT" customClass="EditPasswordTableViewController" customModule="pass" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="18" sectionFooterHeight="18" id="wRM-8V-raT">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
|
||||
<sections/>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="2RE-j0-dBT" id="SPm-AZ-299"/>
|
||||
<outlet property="delegate" destination="2RE-j0-dBT" id="cRC-pf-iA4"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
<navigationItem key="navigationItem" id="Hj9-Iq-kId">
|
||||
<barButtonItem key="leftBarButtonItem" systemItem="cancel" id="5zc-lC-5AP">
|
||||
<connections>
|
||||
<segue destination="HB6-Yu-Y3J" kind="unwind" unwindAction="cancelEditPasswordWithSegue:" id="B5h-gu-WUv"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
<barButtonItem key="rightBarButtonItem" systemItem="save" id="4l7-58-u8N">
|
||||
<connections>
|
||||
<segue destination="HB6-Yu-Y3J" kind="unwind" identifier="saveEditPasswordSegue" unwindAction="saveEditPasswordWithSegue:" id="1sb-Aa-Qdy"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
</navigationItem>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="HlX-6r-eOU" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
<exit id="HB6-Yu-Y3J" userLabel="Exit" sceneMemberID="exit"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="6084" y="601"/>
|
||||
</scene>
|
||||
<!--About Repository Table View Controller-->
|
||||
<scene sceneID="u1v-BP-jaG">
|
||||
<objects>
|
||||
|
|
@ -751,7 +786,7 @@
|
|||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="2jy-oC-WQa" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="5471" y="1007"/>
|
||||
<point key="canvasLocation" x="5132" y="1496"/>
|
||||
</scene>
|
||||
<!--Navigation Controller-->
|
||||
<scene sceneID="yn4-1A-RA2">
|
||||
|
|
@ -769,7 +804,7 @@
|
|||
</navigationController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="kr5-iH-doj" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="5638" y="2129"/>
|
||||
<point key="canvasLocation" x="5132" y="2204"/>
|
||||
</scene>
|
||||
<!--Key Setting Table View Controller-->
|
||||
<scene sceneID="7pC-mh-aE6">
|
||||
|
|
@ -888,7 +923,7 @@
|
|||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="eY3-aM-BJB" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="5638" y="2818"/>
|
||||
<point key="canvasLocation" x="5132" y="2893"/>
|
||||
</scene>
|
||||
<!--Password Repository Settings Table View Controller-->
|
||||
<scene sceneID="Wxu-vK-gsd">
|
||||
|
|
@ -1037,7 +1072,7 @@
|
|||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="AWL-FF-UWb" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="5638" y="5165"/>
|
||||
<point key="canvasLocation" x="5132" y="5240"/>
|
||||
</scene>
|
||||
<!--Special Thanks Table View Controller-->
|
||||
<scene sceneID="FNS-LJ-tzc">
|
||||
|
|
@ -1056,7 +1091,7 @@
|
|||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="Z6I-8E-8pB" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="5638" y="6273"/>
|
||||
<point key="canvasLocation" x="5132" y="6348"/>
|
||||
</scene>
|
||||
<!--Navigation Controller-->
|
||||
<scene sceneID="zfZ-pX-bff">
|
||||
|
|
@ -1074,7 +1109,25 @@
|
|||
</navigationController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="Zq0-iH-LGe" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="3962.3188405797105" y="268.20652173913044"/>
|
||||
<point key="canvasLocation" x="3988" y="-229"/>
|
||||
</scene>
|
||||
<!--Navigation Controller-->
|
||||
<scene sceneID="zp3-R2-7dZ">
|
||||
<objects>
|
||||
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="eui-w4-P7T" sceneMemberID="viewController">
|
||||
<toolbarItems/>
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" id="AuM-kc-jXp">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</navigationBar>
|
||||
<nil name="viewControllers"/>
|
||||
<connections>
|
||||
<segue destination="2RE-j0-dBT" kind="relationship" relationship="rootViewController" id="dZk-bD-gYZ"/>
|
||||
</connections>
|
||||
</navigationController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="llB-WG-h5s" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="5132" y="601"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
|
|
|
|||
53
pass/Controllers/EditPasswordTableViewController.swift
Normal file
53
pass/Controllers/EditPasswordTableViewController.swift
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
//
|
||||
// EditPasswordTableViewController.swift
|
||||
// pass
|
||||
//
|
||||
// Created by Mingshen Sun on 12/2/2017.
|
||||
// Copyright © 2017 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class EditPasswordTableViewController: PasswordEditorTableViewController {
|
||||
|
||||
var password: Password?
|
||||
|
||||
override func viewDidLoad() {
|
||||
tableData = [
|
||||
[[.type: PasswordEditorCellType.textFieldCell, .title: "name", .content: password!.name]],
|
||||
[[.type: PasswordEditorCellType.fillPasswordCell, .title: "password", .content: password!.password]],
|
||||
[[.type: PasswordEditorCellType.textViewCell, .title: "additions", .content: password!.getAdditionsPlainText()]],
|
||||
]
|
||||
sectionHeaderTitles = ["name", "password", "additions"].map {$0.uppercased()}
|
||||
super.viewDidLoad()
|
||||
}
|
||||
|
||||
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
|
||||
if identifier == "saveEditPasswordSegue" {
|
||||
let nameCell = tableView.cellForRow(at: IndexPath(row: 0, section: 0)) as! ContentTableViewCell
|
||||
if nameCell.getContent() != password?.name {
|
||||
let alertMessage = "Editing name is not supported."
|
||||
let alert = UIAlertController(title: "Cannot Save Edit", message: alertMessage, preferredStyle: UIAlertControllerStyle.alert)
|
||||
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
|
||||
self.present(alert, animated: true) {
|
||||
nameCell.setContent(content: self.password!.name)
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
||||
let cells = tableView.visibleCells
|
||||
var cellContents = [String: String]()
|
||||
for cell in cells {
|
||||
let indexPath = tableView.indexPath(for: cell)!
|
||||
let contentCell = cell as! ContentTableViewCell
|
||||
let cellTitle = tableData[indexPath.section][indexPath.row][.title] as! String
|
||||
cellContents[cellTitle] = contentCell.getContent()!
|
||||
}
|
||||
password!.updatePassword(name: cellContents["name"]!, plainText: "\(cellContents["password"]!)\n\(cellContents["additions"]!)")
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -64,14 +64,13 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
indicator.startAnimating()
|
||||
tableView.addSubview(indicator)
|
||||
tableView.addSubview(indicatorLable)
|
||||
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .edit, target: self, action: #selector(pressEdit(_:)))
|
||||
|
||||
if let imageData = passwordEntity?.image {
|
||||
let image = UIImage(data: imageData as Data)
|
||||
passwordImage = image
|
||||
}
|
||||
|
||||
tableData.append(TableSection(title: "", item: []))
|
||||
tableData[0].item.append(TableCell())
|
||||
|
||||
DispatchQueue.global(qos: .userInitiated).async {
|
||||
do {
|
||||
|
|
@ -84,6 +83,59 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
self.present(alert, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
// var tableDataIndex = 1
|
||||
// self.tableData.append(TableSection(title: "", item: []))
|
||||
// let password = self.password!
|
||||
// if let username = password.getUsername() {
|
||||
// self.tableData[tableDataIndex].item.append(TableCell(title: "username", content: username))
|
||||
// }
|
||||
// self.tableData[tableDataIndex].item.append(TableCell(title: "password", content: password.password))
|
||||
// if password.additions.count > 0 {
|
||||
// self.tableData.append(TableSection(title: "additions", item: []))
|
||||
// tableDataIndex += 1
|
||||
// for additionKey in password.additionKeys {
|
||||
// self.tableData[tableDataIndex].item.append(TableCell(title: additionKey, content: password.additions[additionKey]!))
|
||||
//
|
||||
// }
|
||||
// }
|
||||
let password = self.password!
|
||||
self.setTableData()
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
self?.tableView.reloadData()
|
||||
indicator.stopAnimating()
|
||||
indicatorLable.isHidden = true
|
||||
if let url = password.getURL() {
|
||||
if self?.passwordEntity?.image == nil{
|
||||
self?.updatePasswordImage(url: url)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func pressEdit(_ sender: Any?) {
|
||||
performSegue(withIdentifier: "editPasswordSegue", sender: self)
|
||||
}
|
||||
|
||||
@IBAction func cancelEditPassword(segue: UIStoryboardSegue) {
|
||||
|
||||
}
|
||||
|
||||
@IBAction func saveEditPassword(segue: UIStoryboardSegue) {
|
||||
if password!.changed {
|
||||
PasswordStore.shared.update(passwordEntity: passwordEntity!, password: password!, progressBlock: { progress in
|
||||
|
||||
})
|
||||
NotificationCenter.default.post(Notification(name: Notification.Name("passwordUpdated")))
|
||||
setTableData()
|
||||
tableView.reloadData()
|
||||
}
|
||||
}
|
||||
|
||||
func setTableData() {
|
||||
self.tableData = Array<TableSection>()
|
||||
tableData.append(TableSection(title: "", item: []))
|
||||
tableData[0].item.append(TableCell())
|
||||
var tableDataIndex = 1
|
||||
self.tableData.append(TableSection(title: "", item: []))
|
||||
let password = self.password!
|
||||
|
|
@ -99,14 +151,13 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
|
||||
}
|
||||
}
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
self?.tableView.reloadData()
|
||||
indicator.stopAnimating()
|
||||
indicatorLable.isHidden = true
|
||||
if let url = password.getURL() {
|
||||
if self?.passwordEntity?.image == nil{
|
||||
self?.updatePasswordImage(url: url)
|
||||
}
|
||||
|
||||
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
||||
if segue.identifier == "editPasswordSegue" {
|
||||
if let controller = segue.destination as? UINavigationController {
|
||||
if let editController = controller.viewControllers.first as? EditPasswordTableViewController {
|
||||
editController.password = password
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
77
pass/Controllers/PasswordEditorTableViewController.swift
Normal file
77
pass/Controllers/PasswordEditorTableViewController.swift
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
//
|
||||
// PasswordEditorTableViewController.swift
|
||||
// pass
|
||||
//
|
||||
// Created by Mingshen Sun on 12/2/2017.
|
||||
// Copyright © 2017 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
enum PasswordEditorCellType {
|
||||
case textFieldCell, textViewCell, fillPasswordCell
|
||||
}
|
||||
|
||||
enum PasswordEditorCellKey {
|
||||
case type, title, content, placeholders
|
||||
}
|
||||
|
||||
class PasswordEditorTableViewController: UITableViewController {
|
||||
var navigationItemTitle: String?
|
||||
var tableData = [
|
||||
[Dictionary<PasswordEditorCellKey, Any>]
|
||||
]()
|
||||
var sectionHeaderTitles = [String]()
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
navigationItem.title = navigationItemTitle
|
||||
tableView.register(UINib(nibName: "TextFieldTableViewCell", bundle: nil), forCellReuseIdentifier: "textFieldCell")
|
||||
tableView.register(UINib(nibName: "TextViewTableViewCell", bundle: nil), forCellReuseIdentifier: "textViewCell")
|
||||
tableView.register(UINib(nibName: "FillPasswordTableViewCell", bundle: nil), forCellReuseIdentifier: "fillPasswordCell")
|
||||
|
||||
|
||||
tableView.rowHeight = UITableViewAutomaticDimension
|
||||
tableView.estimatedRowHeight = 48
|
||||
tableView.allowsSelection = false
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let cellData = tableData[indexPath.section][indexPath.row]
|
||||
var cell = ContentTableViewCell()
|
||||
|
||||
switch cellData[PasswordEditorCellKey.type] as! PasswordEditorCellType {
|
||||
case .textViewCell:
|
||||
cell = tableView.dequeueReusableCell(withIdentifier: "textViewCell", for: indexPath) as! ContentTableViewCell
|
||||
case .fillPasswordCell:
|
||||
cell = tableView.dequeueReusableCell(withIdentifier: "fillPasswordCell", for: indexPath) as! ContentTableViewCell
|
||||
default:
|
||||
cell = tableView.dequeueReusableCell(withIdentifier: "textFieldCell", for: indexPath) as! ContentTableViewCell
|
||||
}
|
||||
if let content = cellData[PasswordEditorCellKey.content] as? String {
|
||||
cell.setContent(content: content)
|
||||
}
|
||||
return cell
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
|
||||
return 44
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
|
||||
return 0.1
|
||||
}
|
||||
|
||||
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||
return tableData.count
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return tableData[section].count
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
return sectionHeaderTitles[section]
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -67,6 +67,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
}
|
||||
})
|
||||
}
|
||||
PasswordStore.shared.updatePasswordEntityCoreData()
|
||||
DispatchQueue.main.async {
|
||||
self.passwordEntities = PasswordStore.shared.fetchPasswordEntityCoreData()
|
||||
self.reloadTableView(data: self.passwordEntities!)
|
||||
|
|
|
|||
|
|
@ -19,16 +19,47 @@ class Password {
|
|||
var password = ""
|
||||
var additions = [String: String]()
|
||||
var additionKeys = [String]()
|
||||
var plainText = ""
|
||||
var changed = false
|
||||
|
||||
convenience init(name: String, plainText: String) {
|
||||
var i = 0
|
||||
init(name: String, plainText: String) {
|
||||
let plainTextSplit = plainText.characters.split(maxSplits: 1, omittingEmptySubsequences: false) {
|
||||
$0 == "\n" || $0 == "\r\n"
|
||||
}.map(String.init)
|
||||
let password = plainTextSplit[0]
|
||||
let additionFieldsArray = Password.getAdditionFields(from: plainTextSplit[1])
|
||||
// self.init(name: name, password: password, additionsArray: additionFieldsArray)
|
||||
self.name = name
|
||||
self.password = password
|
||||
self.plainText = plainText
|
||||
for additionField in additionFieldsArray {
|
||||
self.additions[additionField.title] = additionField.content
|
||||
self.additionKeys.append(additionField.title)
|
||||
}
|
||||
}
|
||||
|
||||
// private convenience init(name: String, password: String, additionsArray: [AdditionField]) {
|
||||
// self.name = name
|
||||
// self.password = password
|
||||
// for additionField in additionsArray {
|
||||
// self.additions[additionField.title] = additionField.content
|
||||
// self.additionKeys.append(additionField.title)
|
||||
// }
|
||||
// }
|
||||
|
||||
func getUsername() -> String? {
|
||||
return getAdditionValue(withKey: "Username") ?? getAdditionValue(withKey: "username")
|
||||
}
|
||||
|
||||
func getURL() -> String? {
|
||||
return getAdditionValue(withKey: "URL") ?? getAdditionValue(withKey: "url") ?? getAdditionValue(withKey: "Url")
|
||||
}
|
||||
|
||||
static func getAdditionFields(from additionFieldsPlainText: String) -> [AdditionField]{
|
||||
var additionFieldsArray = [AdditionField]()
|
||||
var password = ""
|
||||
var unkownIndex = 0
|
||||
plainText.enumerateLines() { line, _ in
|
||||
if i == 0 {
|
||||
password = line
|
||||
} else {
|
||||
|
||||
additionFieldsPlainText.enumerateLines() { line, _ in
|
||||
let items = line.characters.split(separator: ":", maxSplits: 1, omittingEmptySubsequences: true).map(String.init)
|
||||
var key = ""
|
||||
var value = ""
|
||||
|
|
@ -42,31 +73,35 @@ class Password {
|
|||
}
|
||||
additionFieldsArray.append(AdditionField(title: key, content: value))
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
self.init(name: name, password: password, additionsArray: additionFieldsArray)
|
||||
return additionFieldsArray
|
||||
}
|
||||
|
||||
init(name: String, password: String, additionsArray: [AdditionField]) {
|
||||
func updatePassword(name: String, plainText: String) {
|
||||
self.name = name
|
||||
if self.plainText != plainText {
|
||||
let plainTextSplit = plainText.characters.split(maxSplits: 1, omittingEmptySubsequences: false) {
|
||||
$0 == "\n" || $0 == "\r\n"
|
||||
}.map(String.init)
|
||||
let password = plainTextSplit[0]
|
||||
let additionFieldsArray = Password.getAdditionFields(from: plainTextSplit[1])
|
||||
self.password = password
|
||||
for additionField in additionsArray {
|
||||
self.additions = [String: String]()
|
||||
self.additionKeys = []
|
||||
for additionField in additionFieldsArray {
|
||||
self.additions[additionField.title] = additionField.content
|
||||
self.additionKeys.append(additionField.title)
|
||||
}
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
|
||||
func getUsername() -> String? {
|
||||
return getAdditionValue(withKey: "Username") ?? getAdditionValue(withKey: "username")
|
||||
}
|
||||
|
||||
func getURL() -> String? {
|
||||
return getAdditionValue(withKey: "URL") ?? getAdditionValue(withKey: "url") ?? getAdditionValue(withKey: "Url")
|
||||
func getAdditionsPlainText() -> String {
|
||||
let plainAdditionsText = self.additionKeys.map { "\($0): \(self.additions[$0]!)" }.joined(separator: "\n")
|
||||
return plainAdditionsText
|
||||
}
|
||||
|
||||
func getPlainText() -> String {
|
||||
let plainAdditionsText = self.additionKeys.map { "\($0): \(self.additions[$0]!)" }.joined(separator: "\n")
|
||||
return "\(self.password)\n\(plainAdditionsText)"
|
||||
return "\(self.password)\n\(getAdditionsPlainText())"
|
||||
}
|
||||
|
||||
func getPlainData() -> Data {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ extension PasswordEntity {
|
|||
|
||||
func encrypt(password: Password) throws -> Data {
|
||||
name = password.name
|
||||
rawPath = ""
|
||||
let plainData = password.getPlainData()
|
||||
let pgp = PasswordStore.shared.pgp
|
||||
let encryptedData = try pgp.encryptData(plainData, usingPublicKey: pgp.getKeysOf(.public)[0], armored: false)
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ class PasswordStore {
|
|||
]
|
||||
let remote = try GTRemote(name: "origin", in: storeRepository!)
|
||||
try storeRepository?.pull((storeRepository?.currentBranch())!, from: remote, withOptions: options, progress: transferProgressBlock)
|
||||
updatePasswordEntityCoreData()
|
||||
// updatePasswordEntityCoreData()
|
||||
}
|
||||
|
||||
func updatePasswordEntityCoreData() {
|
||||
|
|
@ -214,7 +214,8 @@ class PasswordStore {
|
|||
func updateRemoteRepo() {
|
||||
}
|
||||
|
||||
func createCommitInRepository(message: String, fileData: Data, filename: String, progressBlock: (_ progress: Float) -> Void) -> GTCommit? {
|
||||
|
||||
func addEntryToGTTree(fileData: Data, filename: String) -> GTTree {
|
||||
do {
|
||||
let head = try storeRepository!.headReference()
|
||||
let branch = GTBranch(reference: head, repository: storeRepository!)
|
||||
|
|
@ -224,6 +225,50 @@ class PasswordStore {
|
|||
try treeBulider.addEntry(with: fileData, fileName: filename, fileMode: GTFileMode.blob)
|
||||
|
||||
let newTree = try treeBulider.writeTree()
|
||||
return newTree
|
||||
} catch {
|
||||
fatalError("Failed to add entries to GTTree: \(error)")
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func removeEntryFromGTTree(filename: String) -> GTTree {
|
||||
do {
|
||||
let head = try storeRepository!.headReference()
|
||||
let branch = GTBranch(reference: head, repository: storeRepository!)
|
||||
let headCommit = try branch?.targetCommit()
|
||||
|
||||
let treeBulider = try GTTreeBuilder(tree: headCommit?.tree, repository: storeRepository!)
|
||||
try treeBulider.removeEntry(withFileName: filename)
|
||||
|
||||
let newTree = try treeBulider.writeTree()
|
||||
return newTree
|
||||
} catch {
|
||||
fatalError("Failed to remove entries to GTTree: \(error)")
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func createAddCommitInRepository(message: String, fileData: Data, filename: String, progressBlock: (_ progress: Float) -> Void) -> GTCommit? {
|
||||
do {
|
||||
let newTree = addEntryToGTTree(fileData: fileData, filename: filename)
|
||||
let headReference = try storeRepository!.headReference()
|
||||
let commitEnum = try GTEnumerator(repository: storeRepository!)
|
||||
try commitEnum.pushSHA(headReference.targetOID.sha)
|
||||
let parent = commitEnum.nextObject() as! GTCommit
|
||||
progressBlock(0.5)
|
||||
let commit = try storeRepository!.createCommit(with: newTree, message: message, parents: [parent], updatingReferenceNamed: headReference.name)
|
||||
progressBlock(0.7)
|
||||
return commit
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func createRemoveCommitInRepository(message: String, filename: String, progressBlock: (_ progress: Float) -> Void) -> GTCommit? {
|
||||
do {
|
||||
let newTree = removeEntryFromGTTree(filename: filename)
|
||||
let headReference = try storeRepository!.headReference()
|
||||
let commitEnum = try GTEnumerator(repository: storeRepository!)
|
||||
try commitEnum.pushSHA(headReference.targetOID.sha)
|
||||
|
|
@ -272,13 +317,26 @@ class PasswordStore {
|
|||
passwordEntity.synced = false
|
||||
try context.save()
|
||||
print(saveURL.path)
|
||||
let _ = createCommitInRepository(message: "Add new password by pass for iOS", fileData: encryptedData, filename: saveURL.lastPathComponent, progressBlock: progressBlock)
|
||||
let _ = createAddCommitInRepository(message: "Add new password by pass for iOS", fileData: encryptedData, filename: saveURL.lastPathComponent, progressBlock: progressBlock)
|
||||
progressBlock(1.0)
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
|
||||
func update(passwordEntity: PasswordEntity, password: Password, progressBlock: (_ progress: Float) -> Void) {
|
||||
do {
|
||||
let encryptedData = try passwordEntity.encrypt(password: password)
|
||||
let saveURL = storeURL.appendingPathComponent(passwordEntity.rawPath!)
|
||||
try encryptedData.write(to: saveURL)
|
||||
passwordEntity.synced = false
|
||||
let _ = createAddCommitInRepository(message: "Update password by pass for iOS", fileData: encryptedData, filename: saveURL.lastPathComponent, progressBlock: progressBlock)
|
||||
try context.save()
|
||||
} catch {
|
||||
fatalError("Failed to fetch employees: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
func deleteCoreData(entityName: String) {
|
||||
let deleteFetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entityName)
|
||||
let deleteRequest = NSBatchDeleteRequest(fetchRequest: deleteFetchRequest)
|
||||
|
|
|
|||
28
pass/Views/ContentTableViewCell.swift
Normal file
28
pass/Views/ContentTableViewCell.swift
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
//
|
||||
// ContentTableViewCell.swift
|
||||
// pass
|
||||
//
|
||||
// Created by Mingshen Sun on 12/2/2017.
|
||||
// Copyright © 2017 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class ContentTableViewCell: UITableViewCell {
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
// Initialization code
|
||||
}
|
||||
|
||||
override func setSelected(_ selected: Bool, animated: Bool) {
|
||||
super.setSelected(selected, animated: animated)
|
||||
}
|
||||
|
||||
func getContent() -> String? {
|
||||
return nil
|
||||
}
|
||||
|
||||
func setContent(content: String) { }
|
||||
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import UIKit
|
||||
|
||||
class FillPasswordTableViewCell: UITableViewCell {
|
||||
class FillPasswordTableViewCell: ContentTableViewCell {
|
||||
|
||||
@IBOutlet weak var contentTextField: UITextField!
|
||||
override func awakeFromNib() {
|
||||
|
|
@ -25,4 +25,12 @@ class FillPasswordTableViewCell: UITableViewCell {
|
|||
@IBAction func generatePassword(_ sender: UIButton) {
|
||||
contentTextField.text = Utils.randomString(length: 16)
|
||||
}
|
||||
|
||||
override func getContent() -> String? {
|
||||
return contentTextField.text
|
||||
}
|
||||
|
||||
override func setContent(content: String) {
|
||||
contentTextField.text = content
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import UIKit
|
||||
|
||||
class TextFieldTableViewCell: UITableViewCell {
|
||||
class TextFieldTableViewCell: ContentTableViewCell {
|
||||
|
||||
@IBOutlet weak var contentTextField: UITextField!
|
||||
|
||||
|
|
@ -20,4 +20,10 @@ class TextFieldTableViewCell: UITableViewCell {
|
|||
super.setSelected(selected, animated: animated)
|
||||
}
|
||||
|
||||
override func getContent() -> String? {
|
||||
return contentTextField.text
|
||||
}
|
||||
override func setContent(content: String) {
|
||||
contentTextField.text = content
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import UIKit
|
||||
|
||||
class TextViewTableViewCell: UITableViewCell {
|
||||
class TextViewTableViewCell: ContentTableViewCell {
|
||||
|
||||
@IBOutlet weak var contentTextView: UITextView!
|
||||
override func awakeFromNib() {
|
||||
|
|
@ -18,4 +18,11 @@ class TextViewTableViewCell: UITableViewCell {
|
|||
super.setSelected(selected, animated: animated)
|
||||
}
|
||||
|
||||
override func getContent() -> String? {
|
||||
return contentTextView.text
|
||||
}
|
||||
|
||||
override func setContent(content: String) {
|
||||
contentTextView.text = content
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,20 +12,19 @@
|
|||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="145" id="KGk-i7-Jjw" customClass="TextViewTableViewCell" customModule="pass" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="145"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="217" id="KGk-i7-Jjw" customClass="TextViewTableViewCell" customModule="pass" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="217"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="144"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="216.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="xHX-Sh-1pR">
|
||||
<rect key="frame" x="15" y="8" width="297" height="128.5"/>
|
||||
<rect key="frame" x="15" y="8" width="297" height="200.5"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="120" id="OY2-uq-PPw"/>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="160" id="OY2-uq-PPw"/>
|
||||
</constraints>
|
||||
<string key="text">Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.</string>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<textInputTraits key="textInputTraits" autocapitalizationType="sentences" autocorrectionType="no"/>
|
||||
</textView>
|
||||
|
|
@ -40,7 +39,7 @@
|
|||
<connections>
|
||||
<outlet property="contentTextView" destination="xHX-Sh-1pR" id="grB-ki-nyo"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="34" y="66.5"/>
|
||||
<point key="canvasLocation" x="34" y="102.5"/>
|
||||
</tableViewCell>
|
||||
</objects>
|
||||
</document>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue