passforios/pass/Views/LabelTableViewCell.swift

213 lines
7.6 KiB
Swift
Raw Normal View History

2017-02-02 21:04:31 +08:00
//
// LabelTableViewCell.swift
// pass
//
// Created by Mingshen Sun on 2/2/2017.
// Copyright © 2017 Bob Sun. All rights reserved.
//
import UIKit
import SVProgressHUD
2017-02-02 21:04:31 +08:00
2017-02-05 13:56:37 +08:00
struct LabelTableViewCellData {
var title: String
var content: String
}
2017-02-02 21:04:31 +08:00
class LabelTableViewCell: UITableViewCell {
@IBOutlet weak var contentLabel: UILabel!
@IBOutlet weak var titleLabel: UILabel!
2017-04-05 00:17:39 +08:00
private enum CellType {
case password, URL, HOTP, other
}
2017-02-05 13:56:37 +08:00
2017-04-05 00:17:39 +08:00
private var type = CellType.other
private var isReveal = false
2017-02-05 13:56:37 +08:00
weak var delegatePasswordTableView : PasswordDetailTableViewController?
2017-04-05 00:17:39 +08:00
private var passwordDisplayButton: UIButton?
private var buttons: UIView?
2017-02-05 13:56:37 +08:00
var cellData: LabelTableViewCellData? {
didSet {
2017-04-05 00:17:39 +08:00
guard let title = cellData?.title, let content = cellData?.content else {
type = .other
return
}
titleLabel.text = title
switch title.lowercased() {
case "password":
type = .password
if isReveal {
2017-04-05 00:17:39 +08:00
contentLabel.attributedText = Utils.attributedPassword(plainPassword: content)
} else {
2017-04-05 00:17:39 +08:00
if content == "" {
contentLabel.text = ""
} else {
contentLabel.text = Globals.passwordDots
}
}
contentLabel.font = UIFont(name: Globals.passwordFonts, size: contentLabel.font.pointSize)
2017-04-05 00:17:39 +08:00
case "hmac-based":
type = .HOTP
if isReveal {
2017-04-05 00:17:39 +08:00
contentLabel.text = content
} else {
2017-04-05 00:17:39 +08:00
contentLabel.text = Globals.oneTimePasswordDots
}
contentLabel.font = UIFont(name: Globals.passwordFonts, size: contentLabel.font.pointSize)
2017-04-05 00:17:39 +08:00
case "url":
type = .URL
contentLabel.text = content
default:
type = .other
contentLabel.text = content
}
updateButtons()
2017-02-05 13:56:37 +08:00
}
}
2017-02-02 21:04:31 +08:00
2017-02-05 00:35:23 +08:00
override var canBecomeFirstResponder: Bool {
get {
return true
}
}
2017-02-02 21:04:31 +08:00
override func awakeFromNib() {
super.awakeFromNib()
}
override func layoutSubviews() {
super.layoutSubviews()
if buttons != nil {
self.accessoryView = buttons
}
}
2017-02-02 21:04:31 +08:00
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
2017-02-05 00:35:23 +08:00
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
2017-04-05 00:17:39 +08:00
switch type {
case .password:
if isReveal {
2017-04-05 00:17:39 +08:00
return action == #selector(copy(_:)) || action == #selector(concealPassword(_:))
} else {
2017-04-05 00:17:39 +08:00
return action == #selector(copy(_:)) || action == #selector(revealPassword(_:))
}
2017-04-05 00:17:39 +08:00
case .URL:
return action == #selector(copy(_:)) || action == #selector(openLink(_:))
case .HOTP:
if isReveal {
2017-04-05 00:17:39 +08:00
return action == #selector(copy(_:)) || action == #selector(concealPassword(_:)) || action == #selector(getNextHOTP(_:))
} else {
2017-04-05 00:17:39 +08:00
return action == #selector(copy(_:)) || action == #selector(revealPassword(_:)) || action == #selector(getNextHOTP(_:))
}
2017-04-05 00:17:39 +08:00
default:
return action == #selector(copy(_:))
}
2017-02-05 00:35:23 +08:00
}
2017-04-05 00:17:39 +08:00
2017-02-05 00:35:23 +08:00
override func copy(_ sender: Any?) {
2017-02-23 17:56:12 +08:00
Utils.copyToPasteboard(textToCopy: cellData?.content)
2017-02-05 00:35:23 +08:00
}
2017-02-08 17:55:18 +08:00
func revealPassword(_ sender: Any?) {
2017-04-05 00:17:39 +08:00
let plainPassword = cellData?.content ?? ""
if type == .password {
contentLabel.attributedText = Utils.attributedPassword(plainPassword: plainPassword)
} else {
2017-04-05 00:17:39 +08:00
contentLabel.text = plainPassword
}
isReveal = true
passwordDisplayButton?.setImage(#imageLiteral(resourceName: "Invisible"), for: .normal)
}
func concealPassword(_ sender: Any?) {
2017-04-05 00:17:39 +08:00
if type == .password {
if cellData?.content.isEmpty == false {
contentLabel.text = Globals.passwordDots
} else {
contentLabel.text = ""
}
} else {
contentLabel.text = Globals.oneTimePasswordDots
}
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()
}
func getNextHOTP(_ sender: Any?) {
// if isHOTPCell, passwordTableView should not be nil
delegatePasswordTableView!.getNextHOTP()
2017-02-08 17:55:18 +08:00
}
2017-04-05 00:17:39 +08:00
private func updateButtons() {
// total width and height of a button
let height = min(self.bounds.height, 36.0)
let width = max(height * 0.8, Globals.tableCellButtonSize)
// margins (between button boundary and icon)
let marginY = max((height - Globals.tableCellButtonSize) / 2, 0.0)
let marginX = max((width - Globals.tableCellButtonSize) / 2, 0.0)
2017-04-05 00:17:39 +08:00
switch type {
case .password:
if let content = cellData?.content, content != "" {
// password button
passwordDisplayButton = UIButton(type: .system)
passwordDisplayButton!.frame = CGRect(x: 0, y: 0, width: width, height: height)
passwordDisplayButton!.setImage(#imageLiteral(resourceName: "Visible"), for: .normal)
passwordDisplayButton!.imageView?.contentMode = .scaleAspectFit
passwordDisplayButton!.contentEdgeInsets = UIEdgeInsetsMake(marginY, marginX, marginY, marginX)
passwordDisplayButton!.addTarget(self, action: #selector(reversePasswordDisplay), for: UIControlEvents.touchUpInside)
buttons = passwordDisplayButton
}
case .HOTP:
// hotp button
let nextButton = UIButton(type: .system)
nextButton.frame = CGRect(x: 0, y: 0, width: width, height: height)
nextButton.setImage(#imageLiteral(resourceName: "Refresh"), for: .normal)
nextButton.imageView?.contentMode = .scaleAspectFit
nextButton.contentEdgeInsets = UIEdgeInsetsMake(marginY, marginX, marginY, marginX)
nextButton.addTarget(self, action: #selector(getNextHOTP), for: UIControlEvents.touchUpInside)
// password button
passwordDisplayButton = UIButton(type: .system)
passwordDisplayButton!.frame = CGRect(x: width, y: 0, width: width, height: height)
passwordDisplayButton!.setImage(#imageLiteral(resourceName: "Visible"), for: .normal)
passwordDisplayButton!.imageView?.contentMode = .scaleAspectFit
passwordDisplayButton!.contentEdgeInsets = UIEdgeInsetsMake(marginY, marginX, marginY, marginX)
passwordDisplayButton!.addTarget(self, action: #selector(reversePasswordDisplay), for: UIControlEvents.touchUpInside)
buttons = UIView()
buttons!.frame = CGRect(x: 0, y: 0, width: width * 2, height: height)
buttons!.addSubview(nextButton)
buttons!.addSubview(passwordDisplayButton!)
2017-04-05 00:17:39 +08:00
default:
passwordDisplayButton = nil
buttons = nil
}
}
2017-02-02 21:04:31 +08:00
}