DSignatureFileListViewController.swift 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  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 self.signatureArrays.count > 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: DSignatureFileListCellView = 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. if row > -1 && row < self.signatureArrays.count {
  108. let model = self.signatureArrays[row] as! KMDSignatureModel
  109. if self.isFileList == false && model.isFormKeyChain == false {
  110. KMDSignatureManager.default().removeSignatureCertPath(model.filePath)
  111. }
  112. self.reloadData()
  113. }
  114. }
  115. //MARK: IBAction
  116. @IBAction func closeAction(_ sender: Any) {
  117. guard let callBack = self.actionBlock else {
  118. return
  119. }
  120. callBack(self, .cancel)
  121. }
  122. @IBAction func refreshAction(_ sender: Any) {
  123. DispatchQueue.main.async {
  124. self.progressIndicator.startAnimation(nil)
  125. self.progressMaskView.isHidden = false
  126. DispatchQueue.global().async {
  127. KMDSignatureManager.default().loadAllKeyChainCertificates()
  128. DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) {
  129. self.progressIndicator.stopAnimation(nil)
  130. self.progressMaskView.isHidden = true
  131. }
  132. }
  133. }
  134. }
  135. @IBAction func configNewAction(_ sender: Any) {
  136. guard let callBack = self.actionBlock else {
  137. return
  138. }
  139. callBack(self, .createNewDsign)
  140. }
  141. @IBAction func cancelAction(_ sender: Any) {
  142. guard let callBack = self.actionBlock else {
  143. return
  144. }
  145. callBack(self, .cancel)
  146. }
  147. @IBAction func continueAction(_ sender: Any) {
  148. guard let callBack = self.actionBlock else {
  149. return
  150. }
  151. callBack(self, .confirm)
  152. }
  153. //MARK: NSTableViewDelegate
  154. func numberOfRows(in tableView: NSTableView) -> Int {
  155. if self.isFileList {
  156. return 1
  157. }
  158. return self.signatureArrays?.count ?? 0
  159. }
  160. func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
  161. return 66.0
  162. }
  163. func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? {
  164. let row = KMCustomTableRowView.init()
  165. return row
  166. }
  167. func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
  168. let cellView = DSignatureFileListCellView()
  169. cellView.itemIndex = row
  170. if (self.signatureArrays.count > row) {
  171. let model = self.signatureArrays[row] as! KMDSignatureModel
  172. cellView.signModel = model
  173. }
  174. if (cellView.signModel == self.currentModel) {
  175. cellView.radioBtn.state = .on
  176. } else {
  177. cellView.radioBtn.state = .off
  178. }
  179. weak var weakSelf = self
  180. cellView.radioActionHandle = {_ in
  181. if weakSelf!.tableView.numberOfRows > cellView.itemIndex {
  182. weakSelf!.tableView.selectRowIndexes([cellView.itemIndex], byExtendingSelection: false)
  183. }
  184. weakSelf!.currentModel = weakSelf!.signatureArrays[weakSelf!.tableView.selectedRow] as? KMDSignatureModel
  185. weakSelf!.refreshSelectedState()
  186. }
  187. cellView.viewDetailBlock = {cellView in
  188. var filePath: NSString!
  189. var save: Bool = true
  190. var password: String = ""
  191. if cellView.signModel?.isFormKeyChain == true {
  192. let folderPath = kDSignatureFolderPath
  193. if FileManager.default.fileExists(atPath: folderPath) == false {
  194. let success: ()? = try?FileManager.default.createDirectory(atPath: folderPath, withIntermediateDirectories: false)
  195. if success == nil {
  196. save = false
  197. }
  198. }
  199. filePath = kDSignatureFolderPath.appending("/KMDSignatures.p12") as NSString
  200. save = KMDSignatureManager.exportKeyChain(withP12FilePath: filePath as String?, signatureModel: cellView.signModel, passWord: password as String?)
  201. cellView.signModel?.filePath = filePath as? String
  202. } else {
  203. if cellView.signModel?.password != nil {
  204. password = (cellView.signModel?.password)!
  205. }
  206. if cellView.signModel?.filePath != nil {
  207. filePath = cellView.signModel?.filePath as? NSString
  208. }
  209. }
  210. if save {
  211. var certificate: CPDFSignatureCertificate!
  212. certificate = CPDFSignatureCertificate(pkcs12Path: filePath as String?, password: password as String?)
  213. if certificate != nil {
  214. guard let callBack = self.viewCertDetailBlock else {
  215. return
  216. }
  217. callBack(self, certificate, !cellView.signModel!.isFormKeyChain)
  218. }
  219. } else {
  220. let alert = NSAlert.init()
  221. alert.messageText = NSLocalizedString("Failed to get certificate details!", comment: "")
  222. alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
  223. alert.runModal()
  224. }
  225. }
  226. return cellView
  227. }
  228. func tableViewSelectionDidChange(_ notification: Notification) {
  229. if (self.signatureArrays.count > self.tableView.selectedRow) {
  230. self.currentModel = self.signatureArrays[self.tableView.selectedRow] as? KMDSignatureModel
  231. self.refreshSelectedState()
  232. }
  233. }
  234. //MARK: NSMenuDelegate
  235. func menuNeedsUpdate(_ menu: NSMenu) {
  236. menu.removeAllItems()
  237. let row = self.tableView.clickedRow
  238. if row > -1 && row < self.signatureArrays.count {
  239. let model = self.signatureArrays[row] as! KMDSignatureModel
  240. if self.isFileList == false && model.isFormKeyChain == false {
  241. menu.addItem(withTitle: NSLocalizedString("Delete", comment: ""), action: #selector(menuItemClick_Delete), keyEquivalent: "")
  242. }
  243. }
  244. }
  245. //MARK: Noti
  246. func signatureDidStartLoadNoti() {
  247. DispatchQueue.main.async {
  248. self.progressIndicator.startAnimation(nil)
  249. self.progressMaskView.isHidden = false
  250. }
  251. }
  252. func signatureDidFinishLoadNoti() {
  253. DispatchQueue.main.async {
  254. self.progressIndicator.stopAnimation(nil)
  255. self.progressMaskView.isHidden = true
  256. self.reloadData()
  257. }
  258. }
  259. }