DSignatureFileListViewController.swift 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. //
  2. // DSignatureFileListViewController.swift
  3. // PDF Reader Pro Edition
  4. //
  5. // Created by Niehaoyu on 2023/9/27.
  6. //
  7. import Cocoa
  8. @objcMembers class DSignatureFileListViewController: NSViewController, NSTableViewDelegate, NSTableViewDataSource, NSMenuDelegate {
  9. @IBOutlet weak var contendView: NSView!
  10. @IBOutlet weak var titleLabel: NSTextField!
  11. @IBOutlet weak var subTitleLabel: NSTextField!
  12. @IBOutlet weak var tableView: NSTableView!
  13. @IBOutlet weak var updateButton: NSButton!
  14. @IBOutlet weak var closeButton: NSButton!
  15. @IBOutlet weak var createButton: NSButton!
  16. @IBOutlet weak var cancelButton: NSButton!
  17. @IBOutlet weak var continueButton: NSButton!
  18. @IBOutlet weak var progressMaskView: NSView!
  19. @IBOutlet weak var progressIndicator: NSProgressIndicator!
  20. var _isFileList: Bool = false
  21. var currentModel: KMDSignatureModel?
  22. private var signatureArrays: NSArray?
  23. var actionBlock: ((_ fileListVC: DSignatureFileListViewController, _ type: DSignatureActionType)->Void)?
  24. var viewCertDetailBlock: ((_ fileListVC: DSignatureFileListViewController, _ certificate: CPDFSignatureCertificate, _ isDigitalFile: Bool)->Void)?
  25. deinit {
  26. NotificationCenter.default.removeObserver(self)
  27. }
  28. override func viewWillAppear() {
  29. super.viewWillAppear()
  30. self.reloadData()
  31. }
  32. override func viewDidLoad() {
  33. super.viewDidLoad()
  34. // Do view setup here.
  35. self.tableView.delegate = self
  36. self.tableView.dataSource = self
  37. self.tableView.backgroundColor = NSColor.clear
  38. self.tableView.allowsEmptySelection = false
  39. self.localizedLanguage()
  40. self.progressMaskView.isHidden = true
  41. let menu = NSMenu.init()
  42. menu.delegate = self;
  43. self.tableView.menu = menu
  44. NotificationCenter.default.addObserver(self, selector: #selector(signatureDidStartLoadNoti), name: NSNotification.Name(rawValue: DSignatureDidStartLoadNotification), object: nil)
  45. NotificationCenter.default.addObserver(self, selector: #selector(signatureDidFinishLoadNoti), name: NSNotification.Name(rawValue: DSignatureDidFinishLoadNotification), object: nil)
  46. }
  47. //MARK: Setter
  48. var isFileList: Bool {
  49. set {
  50. _isFileList = newValue;
  51. if(_isFileList) {
  52. self.titleLabel.stringValue = NSLocalizedString("Add digital IDs from a file:", comment: "")
  53. self.subTitleLabel.stringValue = NSLocalizedString("The following digital ID will be added to your list of digital ID that you can use for digitally signing:", comment: "")
  54. self.cancelButton.title = NSLocalizedString("Previous Step", comment: "")
  55. self.createButton.isHidden = true
  56. self.updateButton.isHidden = true
  57. }else {
  58. self.titleLabel.stringValue = NSLocalizedString("Sign with a Digital ID", comment: "")
  59. self.subTitleLabel.stringValue = NSLocalizedString("Choose the digital ID that you want to use for signing:", comment: "")
  60. self.cancelButton.title = NSLocalizedString("Cancel", comment: "")
  61. self.createButton.isHidden = false
  62. self.updateButton.isHidden = false
  63. }
  64. self.reloadData()
  65. }
  66. get {
  67. return _isFileList;
  68. }
  69. }
  70. //MARK: Public Method
  71. func localizedLanguage() {
  72. self.titleLabel.stringValue = NSLocalizedString("Sign with a Digital ID", comment: "")
  73. self.subTitleLabel.stringValue = NSLocalizedString("Choose the digital ID that you want to use for signing:", comment: "")
  74. self.createButton.title = NSLocalizedString("Configure New Digital ID", comment: "")
  75. self.cancelButton.title = NSLocalizedString("Cancel", comment: "")
  76. self.updateButton.isHidden = false
  77. self.titleLabel.textColor = NSColor.labelColor
  78. self.subTitleLabel.textColor = NSColor.labelColor
  79. self.continueButton.title = NSLocalizedString("Continue", comment: "")
  80. self.updateButton.title = NSLocalizedString("Refresh", comment: "")
  81. }
  82. func reloadData() {
  83. self.signatureArrays = KMDSignatureManager.default().signatures
  84. self.tableView.reloadData()
  85. if let cnt = self.signatureArrays?.count, cnt > 0 {
  86. self.tableView.selectRowIndexes([0], byExtendingSelection: true)
  87. self.currentModel = self.signatureArrays?.firstObject as? KMDSignatureModel
  88. self.continueButton.isEnabled = true
  89. } else {
  90. self.continueButton.isEnabled = false
  91. }
  92. }
  93. func refreshSelectedState() {
  94. let selectRow = self.tableView.selectedRow
  95. for index in 0...self.tableView.numberOfRows-1 {
  96. let rowView = self.tableView.rowView(atRow: index, makeIfNecessary: true)
  97. let cellView = rowView?.view(atColumn: 0) as? DSignatureFileListCellView
  98. if (index == selectRow) {
  99. cellView?.radioBtn.state = .on
  100. } else {
  101. cellView?.radioBtn.state = .off
  102. }
  103. }
  104. }
  105. func menuItemClick_Delete() {
  106. let row = self.tableView.clickedRow
  107. let cnt = self.signatureArrays?.count ?? 0
  108. if row > -1 && row < cnt {
  109. let model = self.signatureArrays?[row] as? KMDSignatureModel
  110. let isFormKeyChain = model?.isFormKeyChain ?? true
  111. if self.isFileList == false && isFormKeyChain == false {
  112. KMDSignatureManager.default().removeSignatureCertPath(model?.filePath ?? "")
  113. }
  114. self.reloadData()
  115. }
  116. }
  117. //MARK: IBAction
  118. @IBAction func closeAction(_ sender: Any) {
  119. guard let callBack = self.actionBlock else {
  120. return
  121. }
  122. callBack(self, .cancel)
  123. }
  124. @IBAction func refreshAction(_ sender: Any) {
  125. DispatchQueue.main.async {
  126. self.progressIndicator.startAnimation(nil)
  127. self.progressMaskView.isHidden = false
  128. DispatchQueue.global().async {
  129. KMDSignatureManager.default().loadAllKeyChainCertificates()
  130. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) {
  131. self.progressIndicator.stopAnimation(nil)
  132. self.progressMaskView.isHidden = true
  133. }
  134. }
  135. }
  136. }
  137. @IBAction func configNewAction(_ sender: Any) {
  138. guard let callBack = self.actionBlock else {
  139. return
  140. }
  141. callBack(self, .createNewDsign)
  142. }
  143. @IBAction func cancelAction(_ sender: Any) {
  144. guard let callBack = self.actionBlock else {
  145. return
  146. }
  147. callBack(self, .cancel)
  148. }
  149. @IBAction func continueAction(_ sender: Any) {
  150. guard let callBack = self.actionBlock else {
  151. return
  152. }
  153. callBack(self, .confirm)
  154. }
  155. //MARK: NSTableViewDelegate
  156. func numberOfRows(in tableView: NSTableView) -> Int {
  157. if self.isFileList {
  158. return 1
  159. }
  160. return self.signatureArrays?.count ?? 0
  161. }
  162. func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
  163. return 66.0
  164. }
  165. func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? {
  166. let row = KMCustomTableRowView.init()
  167. return row
  168. }
  169. func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
  170. let cellView = DSignatureFileListCellView()
  171. cellView.itemIndex = row
  172. let cnt = self.signatureArrays?.count ?? 0
  173. if (cnt > row) {
  174. let model = self.signatureArrays?[row] as? KMDSignatureModel
  175. cellView.signModel = model
  176. }
  177. if (cellView.signModel == self.currentModel) {
  178. cellView.radioBtn.state = .on
  179. } else {
  180. cellView.radioBtn.state = .off
  181. }
  182. weak var weakSelf = self
  183. cellView.radioActionHandle = {_ in
  184. if weakSelf!.tableView.numberOfRows > cellView.itemIndex {
  185. weakSelf?.tableView.selectRowIndexes([cellView.itemIndex], byExtendingSelection: false)
  186. }
  187. weakSelf?.currentModel = weakSelf!.signatureArrays?[weakSelf!.tableView.selectedRow] as? KMDSignatureModel
  188. weakSelf?.refreshSelectedState()
  189. }
  190. cellView.viewDetailBlock = {cellView in
  191. var filePath: NSString?
  192. var save: Bool = true
  193. var password: String = ""
  194. if cellView.signModel?.isFormKeyChain == true {
  195. let folderPath = kDSignatureFolderPath
  196. if FileManager.default.fileExists(atPath: folderPath) == false {
  197. let success: ()? = try?FileManager.default.createDirectory(atPath: folderPath, withIntermediateDirectories: false)
  198. if success == nil {
  199. save = false
  200. }
  201. }
  202. filePath = kDSignatureFolderPath.appending("/KMDSignatures.p12") as NSString
  203. save = KMDSignatureManager.exportKeyChain(withP12FilePath: filePath as String?, signatureModel: cellView.signModel, passWord: password as String?)
  204. cellView.signModel?.filePath = filePath as? String
  205. } else {
  206. if cellView.signModel?.password != nil {
  207. password = (cellView.signModel?.password) ?? ""
  208. }
  209. if cellView.signModel?.filePath != nil {
  210. filePath = cellView.signModel?.filePath as? NSString
  211. }
  212. }
  213. if save {
  214. var certificate: CPDFSignatureCertificate?
  215. certificate = CPDFSignatureCertificate(pkcs12Path: filePath as String?, password: password as String?)
  216. if certificate != nil {
  217. guard let callBack = self.viewCertDetailBlock else {
  218. return
  219. }
  220. callBack(self, certificate!, !(cellView.signModel?.isFormKeyChain ?? false))
  221. }
  222. } else {
  223. let alert = NSAlert.init()
  224. alert.messageText = NSLocalizedString("Failed to get certificate details!", comment: "")
  225. alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
  226. alert.runModal()
  227. }
  228. }
  229. return cellView
  230. }
  231. func tableViewSelectionDidChange(_ notification: Notification) {
  232. let cnt = self.signatureArrays?.count ?? 0
  233. if (cnt > self.tableView.selectedRow) {
  234. self.currentModel = self.signatureArrays?[self.tableView.selectedRow] as? KMDSignatureModel
  235. self.refreshSelectedState()
  236. }
  237. }
  238. //MARK: NSMenuDelegate
  239. func menuNeedsUpdate(_ menu: NSMenu) {
  240. menu.removeAllItems()
  241. let row = self.tableView.clickedRow
  242. let cnt = self.signatureArrays?.count ?? 0
  243. if row > -1 && row < cnt {
  244. let model = self.signatureArrays?[row] as? KMDSignatureModel
  245. let isFormKeyChain = model?.isFormKeyChain ?? true
  246. if self.isFileList == false && isFormKeyChain == false {
  247. menu.addItem(withTitle: NSLocalizedString("Delete", comment: ""), action: #selector(menuItemClick_Delete), keyEquivalent: "")
  248. }
  249. }
  250. }
  251. //MARK: Noti
  252. func signatureDidStartLoadNoti() {
  253. DispatchQueue.main.async {
  254. self.progressIndicator.startAnimation(nil)
  255. self.progressMaskView.isHidden = false
  256. }
  257. }
  258. func signatureDidFinishLoadNoti() {
  259. DispatchQueue.main.async {
  260. self.progressIndicator.stopAnimation(nil)
  261. self.progressMaskView.isHidden = true
  262. self.reloadData()
  263. }
  264. }
  265. }