From abb04432fbc6b2ff9b04eaad2ba96e56414f5708 Mon Sep 17 00:00:00 2001 From: Yishi Lin Date: Fri, 31 Mar 2017 03:08:20 +0800 Subject: [PATCH] Add buttons in the detail password table - An icon to show/hide passwords - An icon to refresh HOTP passwords --- .../Invisible.imageset/Contents.json | 22 +++++++ .../Invisible.imageset/Invisible-64.png | Bin 0 -> 1215 bytes .../Invisible.imageset/Invisible-75.png | Bin 0 -> 1477 bytes .../Visible.imageset/Contents.json | 22 +++++++ .../Visible.imageset/Visible-64.png | Bin 0 -> 1154 bytes .../Visible.imageset/Visible-75.png | Bin 0 -> 1418 bytes pass/Helpers/Globals.swift | 8 ++- pass/Views/LabelTableViewCell.swift | 62 ++++++++++++++++++ 8 files changed, 111 insertions(+), 3 deletions(-) create mode 100644 pass/Assets.xcassets/Invisible.imageset/Contents.json create mode 100644 pass/Assets.xcassets/Invisible.imageset/Invisible-64.png create mode 100644 pass/Assets.xcassets/Invisible.imageset/Invisible-75.png create mode 100644 pass/Assets.xcassets/Visible.imageset/Contents.json create mode 100644 pass/Assets.xcassets/Visible.imageset/Visible-64.png create mode 100644 pass/Assets.xcassets/Visible.imageset/Visible-75.png diff --git a/pass/Assets.xcassets/Invisible.imageset/Contents.json b/pass/Assets.xcassets/Invisible.imageset/Contents.json new file mode 100644 index 0000000..be7c464 --- /dev/null +++ b/pass/Assets.xcassets/Invisible.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "Invisible-64.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "Invisible-75.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/pass/Assets.xcassets/Invisible.imageset/Invisible-64.png b/pass/Assets.xcassets/Invisible.imageset/Invisible-64.png new file mode 100644 index 0000000000000000000000000000000000000000..d5db5884ec2583adeec6c7aa3b3c35ce03cf8723 GIT binary patch literal 1215 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 UK{D9%{r~^~07*qoM6N<$g1p@ZnE(I) literal 0 HcmV?d00001 diff --git a/pass/Assets.xcassets/Visible.imageset/Visible-75.png b/pass/Assets.xcassets/Visible.imageset/Visible-75.png new file mode 100644 index 0000000000000000000000000000000000000000..144e87d2da8d7320867835729ae35897552ff4a3 GIT binary patch literal 1418 zcma*n{Xf$Q00;2zmT5N6weoB>+VW7mmNKjslRVGU3^#GoJj_Em4~?>Br3d5WsmLf# zlci-$(UJRxaSDjkZjXM;ktk!QgqO<)x-8 z8c2#hF{=zLMUSmKlHS28FKPMy)?0Z?CX>?(s^(}OokYjZJ1LAEB^I^kb`vjQSLr!c zLaN&k=?m9D0_9iMnVRSO5&7`&W_UJOFFvCKYHbA46*_b8DIP~JHFm|)YIIu%X)`?f8}S?5x*<4H4Q+O{*=3VQ`+$GbS<##=kjff72pR3!{)%SN(_i`C7dqAs!@ZRi;Bsc@NBi`j}6&HKVRRl z`35!^wyTct-9+72$c?<-5OLZCkJTgt=zK+bs@U`Xm*(hN{+b(zZmf`Xlyj@t$Wov# zm{;-HSd0nN8i5X70v|5EQLjlU66)J0xM*s=4uvM+4#i{YfqEZP*T`)G9jukQHMQJW z4QIf1)bYdK;3*4+Y!@dvvM?%|+?^>_U7F>%%UaX#nH&w!_$(exmc~=9YV;!Q)!lsy zWXG>?`f^3KjI|6he7V)qL z5pw@EoWZljEOE+eemkp{8&xMb5-r9jK=hp87Q}G}qNr0eMd%y!dn=Ipj+yXx;sw!M z_*PA7*CbTW9zkyx`zN=Dm=mT)>GU+M<)Jk1hpFAsHYOn?&Z(D&+>~kvr9z-%+Z-#J zC0w9Z(b?9dtljm>NKV@aVfbonMo0Q-QC86FFAuWqsqY8IXa$|=C|miGh4NvxjrMDtCtQ`L9LUi%c|voDU?ubOu5T4`>dS~NyTG9$@rd%y;JeE4X_!PGq z5OT^a2Nc(C9?C?Fum{+eNsd{N;g2O85C-fQQ*fDoS55LF;V#q2r2xX+DxUf=IhZp3 z-g3`eE~0}{1s+a)!ob`$G@r}#qmE8fVny1#Q@u`g=&0f1!3ncR5l#I-X3um(t`BCZ z?8UQ%YIgk_vbL`0+sap7?DG@xeNPU(LT76ourSg&$Me|KvhLI5eiEBEXJX5M_H|YK zez0#U`B%jXT*_?x@J*VS)>Fw_dmfos@n}#BBLF5j|GLCMAhm6MV*WpAOPe{N$nbkU S$BVuj3wXHsl3H9M*?$9s&UYpN literal 0 HcmV?d00001 diff --git a/pass/Helpers/Globals.swift b/pass/Helpers/Globals.swift index dda0746..069ff6b 100644 --- a/pass/Helpers/Globals.swift +++ b/pass/Helpers/Globals.swift @@ -21,15 +21,17 @@ class Globals { static let repositoryPath = "\(libraryPath)/password-store" static var passcodeConfiguration = PasscodeLockConfiguration() - static let red = UIColor(red:1.00, green:0.23, blue:0.19, alpha:1.0) - static let blue = UIColor(red:0.00, green:0.48, blue:1.00, alpha:1.0) - static let passwordDefaultLength = ["Random": (min: 6, max: 24, def: 16), "Apple": (min: 15, max: 15, def: 15)] static let passwordDots = "••••••••••••" static let passwordFonts = "Menlo" + // UI related + static let red = UIColor(red:1.00, green:0.23, blue:0.19, alpha:1.0) + static let blue = UIColor(red:0.00, green:0.48, blue:1.00, alpha:1.0) + static let tableCellButtonSize = CGFloat(20.0) + private init() { } } diff --git a/pass/Views/LabelTableViewCell.swift b/pass/Views/LabelTableViewCell.swift index 726b535..2ffbc5c 100644 --- a/pass/Views/LabelTableViewCell.swift +++ b/pass/Views/LabelTableViewCell.swift @@ -27,6 +27,9 @@ class LabelTableViewCell: UITableViewCell { weak var delegatePasswordTableView : PasswordDetailTableViewController? + var passwordDisplayButton: UIButton? + var buttons: UIView? + var cellData: LabelTableViewCellData? { didSet { titleLabel.text = cellData?.title ?? "" @@ -43,9 +46,11 @@ class LabelTableViewCell: UITableViewCell { } else { contentLabel.text = Globals.passwordDots } + contentLabel.font = UIFont(name: Globals.passwordFonts, size: contentLabel.font.pointSize) } else { contentLabel.text = cellData?.content } + updateButtons() } } @@ -58,6 +63,13 @@ class LabelTableViewCell: UITableViewCell { override func awakeFromNib() { super.awakeFromNib() } + + override func layoutSubviews() { + super.layoutSubviews() + if buttons != nil { + self.accessoryView = buttons + } + } override func setSelected(_ selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) @@ -99,13 +111,26 @@ class LabelTableViewCell: UITableViewCell { contentLabel.text = "" } isReveal = true + passwordDisplayButton?.setImage(#imageLiteral(resourceName: "Invisible"), for: .normal) } func concealPassword(_ sender: Any?) { contentLabel.text = Globals.passwordDots isReveal = false + passwordDisplayButton?.setImage(#imageLiteral(resourceName: "Visible"), for: .normal) } + func reversePasswordDisplay(_ sender: Any?) { + if isReveal { + // conceal + concealPassword(sender) + } else { + // reveal + revealPassword(sender) + } + } + + func openLink(_ sender: Any?) { // if isURLCell, passwordTableView should not be nil delegatePasswordTableView!.openLink() @@ -115,4 +140,41 @@ class LabelTableViewCell: UITableViewCell { // if isHOTPCell, passwordTableView should not be nil delegatePasswordTableView!.getNextHOTP() } + + func updateButtons() { + passwordDisplayButton = nil + buttons = nil + if isPasswordCell { + // password button + passwordDisplayButton = UIButton(type: .system) + passwordDisplayButton!.frame = CGRect(x: 0, y: 0, width: Globals.tableCellButtonSize, height: Globals.tableCellButtonSize) + passwordDisplayButton!.setImage(#imageLiteral(resourceName: "Visible"), for: .normal) + passwordDisplayButton!.imageView?.contentMode = .scaleAspectFit + passwordDisplayButton!.addTarget(self, action: #selector(reversePasswordDisplay), for: UIControlEvents.touchUpInside) + buttons = passwordDisplayButton + } else if isHOTPCell { + let spacing = CGFloat(10.0) + + // hotp button + let nextButton = UIButton(type: .system) + nextButton.frame = CGRect(x: 0, y: 0, + width: Globals.tableCellButtonSize, height: Globals.tableCellButtonSize) + nextButton.setImage(#imageLiteral(resourceName: "Refresh"), for: .normal) + nextButton.imageView?.contentMode = .scaleAspectFit + nextButton.addTarget(self, action: #selector(getNextHOTP), for: UIControlEvents.touchUpInside) + + // password button + passwordDisplayButton = UIButton(type: .system) + passwordDisplayButton!.frame = CGRect(x: Globals.tableCellButtonSize + spacing, y: 0, + width: Globals.tableCellButtonSize, height: Globals.tableCellButtonSize) + passwordDisplayButton!.setImage(#imageLiteral(resourceName: "Visible"), for: .normal) + passwordDisplayButton!.imageView?.contentMode = .scaleAspectFit + passwordDisplayButton!.addTarget(self, action: #selector(reversePasswordDisplay), for: UIControlEvents.touchUpInside) + + buttons = UIView() + buttons!.frame = CGRect(x: 0, y: 0, width: Globals.tableCellButtonSize * 2 + spacing, height: Globals.tableCellButtonSize) + buttons!.addSubview(nextButton) + buttons!.addSubview(passwordDisplayButton!) + } + } }