KMCloudDocumentsViewController.swift 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824
  1. //
  2. // KMCloudDocumentsViewController.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by wanjun on 2022/11/23.
  6. //
  7. import Cocoa
  8. enum KMCloudDocumentState : Int {
  9. case Box = 0
  10. case DropBox
  11. case GoogleDrive
  12. case OneDrive
  13. public func string() -> String {
  14. switch self {
  15. case .Box:
  16. return "Box"
  17. case .DropBox:
  18. return "DropBox"
  19. case .GoogleDrive:
  20. return "GoogleDrive"
  21. case .OneDrive:
  22. return "OneDrive"
  23. }
  24. }
  25. }
  26. class KMCloudAccountListTableviewCell: NSTableCellView {
  27. @IBOutlet weak var accountLabel: NSTextField!
  28. }
  29. class KMCloudFileNameListTableviewCell: NSTableCellView {
  30. @IBOutlet weak var fileImageView: NSImageView!
  31. @IBOutlet weak var titleLabel: NSTextField!
  32. @IBOutlet weak var subtitleLabel: NSTextField!
  33. }
  34. class KMCloudFileModifyTimeListTableviewCell: NSTableCellView {
  35. @IBOutlet weak var modifyTimeLabel: NSTextField!
  36. }
  37. class KMCloudFileSizeListTableviewCell: NSTableCellView {
  38. @IBOutlet weak var sizeLabel: NSTextField!
  39. }
  40. class KMCloudDocumentsViewController: NSViewController {
  41. @IBOutlet weak var topBox: NSBox!
  42. @IBOutlet weak var cloudDocumentsLabel: NSTextField!
  43. @IBOutlet weak var addCloudsBox: KMBox!
  44. @IBOutlet weak var addCloudsLabel: NSTextField!
  45. @IBOutlet weak var addCloudsImageView: NSImageView!
  46. @IBOutlet weak var mainBox: NSBox!
  47. @IBOutlet weak var emptyScrollView: NSScrollView!
  48. @IBOutlet weak var emptyCollectionView: KMCollectionView!
  49. @IBOutlet weak var cloudSplitView: NSSplitView!
  50. @IBOutlet weak var cloudLeftBox: NSBox!
  51. @IBOutlet weak var cloudRightBox: NSBox!
  52. @IBOutlet weak var accountListTableView: NSTableView!
  53. @IBOutlet weak var fileListTableView: KMMenuTableView!
  54. @IBOutlet weak var fileNameTableColumn: NSTableColumn!
  55. @IBOutlet weak var fileModifyTimeTableColumn: NSTableColumn!
  56. @IBOutlet weak var fileSizeTableColumn: NSTableColumn!
  57. @IBOutlet weak var pathControl: NSPathControl!
  58. @IBOutlet weak var pathBox: NSBox!
  59. var myPathControl = KMCloudPathControl()
  60. var pathString: String = ""
  61. var cloudPlates: [KMCloudDocumentState] = [.DropBox, .GoogleDrive]
  62. var accounts: [Any] = []
  63. var cloudFiles: [Any] = []
  64. var currentAccount: KMCloudServer?
  65. var filepaths: [KMServicesCloudFile] = []
  66. override func viewDidLoad() {
  67. super.viewDidLoad()
  68. // Do view setup here.
  69. let serverArr = KMCloudServer.getAllLoginServer()
  70. for server in serverArr! {
  71. self.accounts.append(server)
  72. }
  73. emptyCollectionView.register(KMCloudEmptyCollectionViewItem.self, forItemWithIdentifier: NSUserInterfaceItemIdentifier(rawValue: "KMCloudEmptyCollectionViewItem"))
  74. emptyCollectionView.isSelectable = true
  75. self.fileListTableView.menuDelegate = self
  76. initializeUI()
  77. initLocalization()
  78. self.pathControl.url = URL(fileURLWithPath: "Cloud Documents\\Test\\Test2")
  79. self.pathControl.pathStyle = .popUp
  80. addCloudsBox.downCallback = { [weak self](downEntered: Bool, mouseBox: KMBox, event) -> Void in
  81. if self != nil {
  82. if downEntered {
  83. self!.addCloudsAction()
  84. }
  85. }
  86. }
  87. }
  88. override func viewDidAppear() {
  89. super.viewDidAppear()
  90. reloadData()
  91. }
  92. override func viewWillLayout() {
  93. super.viewWillLayout()
  94. if (self.emptyCollectionView.isHidden == false) {
  95. self.emptyCollectionView.reloadData()
  96. }
  97. }
  98. // MARK: Init
  99. func initializeUI() -> Void {
  100. let menu = NSMenu()
  101. let item = NSMenuItem(title: NSLocalizedString("Delete", comment: ""), action: #selector(accountListTableView_itemClick), target: self)
  102. menu.addItem(item)
  103. self.accountListTableView.menu = menu
  104. self.accountListTableView.allowsEmptySelection = false
  105. self.fileListTableView.doubleAction = #selector(fileListTableViewDoubleAction)
  106. let pathControl = self.myPathControl
  107. self.pathBox.contentView?.addSubview(pathControl)
  108. pathControl.frame = self.pathBox.contentView!.bounds
  109. pathControl.autoresizingMask = [.width, .height]
  110. self.pathString = NSLocalizedString("Cloud Documents", comment: "")
  111. pathControl.urlString = self.pathString
  112. pathControl.itemClick = { [weak self] index in
  113. if (index == 0) {
  114. self!.updateFilesList((self?.currentAccount)!, nil)
  115. } else {
  116. self!.updateFilesList((self?.currentAccount)!, self?.filepaths[index-1])
  117. }
  118. }
  119. }
  120. func initLocalization() -> Void {
  121. cloudDocumentsLabel.stringValue = NSLocalizedString("Cloud Documents", comment: "")
  122. addCloudsLabel.stringValue = NSLocalizedString("Add Account", comment: "")
  123. addCloudsBox.toolTip = NSLocalizedString("Add Account", comment: "")
  124. fileNameTableColumn.title = NSLocalizedString("File Name", comment: "")
  125. fileModifyTimeTableColumn.title = NSLocalizedString("Change time", comment: "")
  126. fileSizeTableColumn.title = NSLocalizedString("Size", comment: "")
  127. }
  128. // MARK: private
  129. func reloadData() -> Void {
  130. DispatchQueue.main.async {
  131. if (KMCloudServer.isConnectionAvailable()) {
  132. self.hiddenNotNetworkView()
  133. self.emptyCollectionView.isHidden = true
  134. self.cloudSplitView.isHidden = true
  135. if self.accounts.count > 0 {
  136. self.cloudSplitView.isHidden = false
  137. self.accountListTableView.reloadData()
  138. self.fileListTableView.reloadData()
  139. } else {
  140. self.emptyCollectionView.isHidden = false
  141. self.emptyCollectionView.reloadData()
  142. }
  143. } else {
  144. self.showNotNetworkView()
  145. }
  146. }
  147. }
  148. // MARK: Action
  149. func loginCloud(state: KMCloudDocumentState) -> Void {
  150. switch state {
  151. case .Box:
  152. break
  153. case .DropBox:
  154. let serverArray = KMCloudServer.getAllLoginServer()
  155. var dropboxIsLogin: Bool = false
  156. for server in serverArray! {
  157. if (server.serverType == KMDropbox) {
  158. dropboxIsLogin = true
  159. break
  160. }
  161. }
  162. if (dropboxIsLogin) {
  163. self.logoutAccount(self.currentAccount!)
  164. } else {
  165. let server = KMCloudServer(cloudWith: KMDropbox)
  166. server?.authorizedLoginCompletion({ cloudFiles, finished in
  167. if (!finished) { /// 登录失败
  168. return
  169. }
  170. let serverArr = KMCloudServer.getAllLoginServer()
  171. var currentServer: KMCloudServer?
  172. for server in serverArr! {
  173. if ((server as! KMCloudServer).serverType == KMDropbox) {
  174. currentServer = server
  175. break
  176. }
  177. }
  178. // let userData: KMDropboxUserMetadata = cloudFiles as! KMDropboxUserMetadata
  179. if (currentServer != nil) {
  180. self.accounts.append(currentServer)
  181. self.reloadData()
  182. }
  183. })
  184. }
  185. break
  186. case .GoogleDrive:
  187. let serverArray = KMCloudServer.getAllLoginServer()
  188. var isLogin: Bool = false
  189. for server in serverArray! {
  190. if (server.serverType == KMGoogleDrive) {
  191. isLogin = true
  192. break
  193. }
  194. }
  195. if (isLogin) {
  196. self.logoutAccount(self.currentAccount!)
  197. } else {
  198. let server = KMCloudServer(cloudWith: KMGoogleDrive)
  199. server?.authorizedLoginCompletion({ cloudFiles, finished in
  200. if (!finished) { /// 登录失败
  201. return
  202. }
  203. let serverArr = KMCloudServer.getAllLoginServer()
  204. var currentServer: KMCloudServer?
  205. for server in serverArr! {
  206. if ((server as! KMCloudServer).serverType == KMGoogleDrive) {
  207. currentServer = server
  208. break
  209. }
  210. }
  211. // let userData: KMDropboxUserMetadata = cloudFiles as! KMDropboxUserMetadata
  212. if (currentServer != nil) {
  213. self.accounts.append(currentServer)
  214. self.reloadData()
  215. }
  216. })
  217. }
  218. break
  219. case .OneDrive:
  220. break
  221. }
  222. }
  223. func addCloudsAction() -> Void {
  224. var popViewDataArr: [String] = []
  225. for plate in self.cloudPlates {
  226. popViewDataArr.append(plate.string())
  227. }
  228. let vc: KMHomePopViewController = KMHomePopViewController().initWithPopViewDataArr(popViewDataArr)
  229. let createFilePopover: NSPopover = NSPopover.init()
  230. createFilePopover.contentViewController = vc
  231. createFilePopover.animates = true
  232. createFilePopover.behavior = .transient
  233. createFilePopover.setValue(true, forKey: "shouldHideAnchor")
  234. createFilePopover.show(relativeTo: CGRect(x: addCloudsBox.bounds.origin.x, y: 10, width: addCloudsBox.bounds.size.width, height: addCloudsBox.bounds.size.height), of: addCloudsBox, preferredEdge: .minY)
  235. vc.downCallback = { [weak self](downEntered: Bool, count: String) -> Void in
  236. if self != nil {
  237. if downEntered {
  238. var state: KMCloudDocumentState = .Box
  239. if count == NSLocalizedString("Box", comment: "") {
  240. state = .Box
  241. } else if count == NSLocalizedString("DropBox", comment: "") {
  242. state = .DropBox
  243. } else if count == NSLocalizedString("GoogleDrive", comment: "") {
  244. state = .GoogleDrive
  245. } else if count == NSLocalizedString("OneDrive", comment: "") {
  246. state = .OneDrive
  247. }
  248. self!.loginCloud(state: state)
  249. }
  250. }
  251. }
  252. }
  253. private func showNotNetworkView() {
  254. self.hiddenNotNetworkView()
  255. self.emptyCollectionView.isHidden = true
  256. self.cloudSplitView.isHidden = true
  257. let superview = self.emptyCollectionView.superview
  258. let view = KMCloudNoNetworkView()
  259. let viewH: CGFloat = 220
  260. view.frame = NSMakeRect(0, (NSHeight(superview!.bounds)-viewH)*0.5, (superview?.bounds.size.width)!, viewH)
  261. view.autoresizingMask = [.width, .minYMargin]
  262. superview?.addSubview(view)
  263. view.itemClick = { [weak self] index in
  264. /// 刷新
  265. self?.hiddenNotNetworkView()
  266. self?.reloadData()
  267. }
  268. }
  269. private func hiddenNotNetworkView() {
  270. let superview = self.emptyCollectionView.superview
  271. var flagView: KMCloudNoNetworkView?
  272. for view in superview!.subviews {
  273. if (view is KMCloudNoNetworkView) {
  274. flagView = (view as! KMCloudNoNetworkView)
  275. break
  276. }
  277. }
  278. if (flagView == nil) {
  279. return
  280. }
  281. flagView?.removeFromSuperview()
  282. }
  283. private func showCloudFileEmptyView() {
  284. self.hiddenCloudFileEmptyView()
  285. let superview = self.fileListTableView.enclosingScrollView?.superview
  286. self.fileListTableView.enclosingScrollView!.isHidden = true
  287. let view = KMCloudFileEmptyView()
  288. let viewH: CGFloat = 220
  289. view.frame = NSMakeRect(0, (NSHeight(superview!.bounds)-viewH)*0.5, (superview?.bounds.size.width)!, viewH)
  290. view.autoresizingMask = [.width, .minYMargin]
  291. superview?.addSubview(view)
  292. }
  293. private func hiddenCloudFileEmptyView() {
  294. let superview = self.fileListTableView.enclosingScrollView?.superview
  295. self.fileListTableView.enclosingScrollView!.isHidden = false
  296. var flagView: KMCloudFileEmptyView?
  297. for view in superview!.subviews {
  298. if (view is KMCloudFileEmptyView) {
  299. flagView = (view as! KMCloudFileEmptyView)
  300. break
  301. }
  302. }
  303. if (flagView == nil) {
  304. return
  305. }
  306. flagView?.removeFromSuperview()
  307. }
  308. @objc func accountListTableView_itemClick(sender: NSMenuItem) {
  309. if (self.accountListTableView.selectedRow < self.accounts.count) {
  310. self.logoutAccount(self.accounts[self.accountListTableView.selectedRow] as! KMCloudServer)
  311. }
  312. }
  313. @objc func openFileMenuClick(sender: NSMenuItem) {
  314. if (self.currentAccount == nil) {
  315. return
  316. }
  317. let file: KMServicesCloudFile = self.cloudFiles[sender.tag] as! KMServicesCloudFile
  318. self.fileListBeginLoading()
  319. KMCloudDocumentTools.downloadDocument(self.currentAccount!, file) { finished, fileUrl in
  320. self.fileListEndLoading()
  321. if (finished) {
  322. if !fileUrl.path.isPDFValid() {
  323. let alert = NSAlert()
  324. alert.alertStyle = .critical
  325. alert.messageText = NSLocalizedString("An error occurred while opening this document. The file is damaged and could not be repaired.", comment: "")
  326. alert.runModal()
  327. return
  328. }
  329. NSDocumentController.shared.openDocument(withContentsOf: fileUrl, display: true) { document, result, error in
  330. if error != nil {
  331. NSApp.presentError(error!)
  332. return
  333. }
  334. (document as! KMMainDocument).cloud = true
  335. (document as! KMMainDocument).cloudUploadHanddler = { callback in
  336. KMCloudDocumentTools.uploadDocument(self.currentAccount!, file) { finished, fileUrl in
  337. callback(finished, "")
  338. }
  339. }
  340. }
  341. }
  342. }
  343. }
  344. @objc func openFolderMenuClick(sender: NSMenuItem) {
  345. if (self.currentAccount == nil) {
  346. return
  347. }
  348. let file: KMServicesCloudFile = self.cloudFiles[sender.tag] as! KMServicesCloudFile
  349. self.updateFilesList(self.currentAccount!, file)
  350. }
  351. @objc func fileListTableViewDoubleAction(sender: Any) {
  352. let indexs = self.fileListTableView.selectedRowIndexes
  353. for index in indexs {
  354. let file: KMServicesCloudFile = self.cloudFiles[index] as! KMServicesCloudFile
  355. if (file.filetype == .file) {
  356. if (self.currentAccount == nil) {
  357. continue
  358. }
  359. if (!KMCloudDocumentTools.canOpenDocument(file)) {
  360. continue
  361. }
  362. self.fileListBeginLoading()
  363. KMCloudDocumentTools.downloadDocument(self.currentAccount!, file) { finished, fileUrl in
  364. self.fileListEndLoading()
  365. if (finished) {
  366. NSDocumentController.shared.openDocument(withContentsOf: fileUrl, display: true) { document, result, error in
  367. if error != nil {
  368. NSApp.presentError(error!)
  369. return
  370. }
  371. (document as! KMMainDocument).cloud = true
  372. (document as! KMMainDocument).cloudUploadHanddler = { callback in
  373. KMCloudDocumentTools.uploadDocument(self.currentAccount!, file) { finished, fileUrl in
  374. callback(finished, "")
  375. }
  376. }
  377. }
  378. }
  379. }
  380. } else {
  381. if (self.currentAccount == nil) {
  382. continue
  383. }
  384. self.updateFilesList(self.currentAccount!, file)
  385. }
  386. }
  387. }
  388. private func logoutAccount(_ account: KMCloudServer) {
  389. DispatchQueue.main.async {
  390. let alert = NSAlert()
  391. alert.messageText = NSLocalizedString("Are you Sure Delete“\(account.userEmail!)”?", comment: "")
  392. alert.addButton(withTitle: NSLocalizedString("Delete", comment: ""))
  393. alert.addButton(withTitle: NSLocalizedString("Cancel", comment: ""))
  394. let response = alert.runModal()
  395. if (response == .alertSecondButtonReturn) { /// 取消
  396. return
  397. }
  398. account.authorizedLogoutCompletion({ [weak self] finished in
  399. if (!finished) {
  400. return
  401. }
  402. var i: Int = 0
  403. for account_ in self!.accounts {
  404. if ((account_ as! KMCloudServer).serverType == account.serverType) {
  405. break
  406. }
  407. i += 1
  408. }
  409. self!.accounts.remove(at: i)
  410. self!.cloudFiles.removeAll()
  411. self!.reloadData()
  412. })
  413. }
  414. }
  415. private func updateFilesList(_ server: KMCloudServer, _ file: KMServicesCloudFile?) {
  416. self.myPathControl.enabled = false
  417. self.fileListBeginLoading()
  418. server.getListWithFilePath(file) { [weak self] fileList, serviceType, error in
  419. if (error != nil) {
  420. self!.myPathControl.enabled = true
  421. return
  422. }
  423. if (fileList == nil) {
  424. self!.myPathControl.enabled = true
  425. return
  426. }
  427. if (file == nil) { /// 切换账号
  428. self?.filepaths.removeAll()
  429. self?.currentAccount = server
  430. } else {
  431. let index = self?.filepaths.firstIndex(of: file!)
  432. if (index == nil) {
  433. self?.filepaths.append(file!)
  434. } else {
  435. let count = self?.filepaths.count
  436. for i in 0 ..< count! {
  437. if (i <= index!) {
  438. continue
  439. }
  440. self?.filepaths.remove(at: i)
  441. }
  442. }
  443. }
  444. self!.pathString = NSLocalizedString("Cloud Documents", comment: "")
  445. for filepath in self!.filepaths {
  446. self!.pathString = self!.pathString.appending("\\\(filepath.fileName!)")
  447. }
  448. self!.myPathControl.urlString = self?.pathString
  449. self?.cloudFiles.removeAll()
  450. for file in fileList! {
  451. self?.cloudFiles.append(file)
  452. }
  453. /// 排序
  454. self?.cloudFiles.sort(by: { file1, file2 in
  455. if ((file1 as! KMServicesCloudFile).filetype == .file) {
  456. if ((file2 as! KMServicesCloudFile).filetype == .file) {
  457. return (file1 as! KMServicesCloudFile).fileName.caseInsensitiveCompare((file2 as! KMServicesCloudFile).fileName) == .orderedAscending
  458. } else {
  459. return false
  460. }
  461. } else {
  462. if ((file2 as! KMServicesCloudFile).filetype == .file) {
  463. return true
  464. } else {
  465. return (file1 as! KMServicesCloudFile).fileName.caseInsensitiveCompare((file2 as! KMServicesCloudFile).fileName) == .orderedAscending
  466. }
  467. }
  468. })
  469. DispatchQueue.main.async {
  470. self?.fileListTableView.reloadData()
  471. if (self?.cloudFiles.count == 0) {
  472. self?.showCloudFileEmptyView()
  473. } else {
  474. self?.hiddenCloudFileEmptyView()
  475. }
  476. self!.myPathControl.enabled = true
  477. self?.fileListEndLoading()
  478. }
  479. }
  480. }
  481. private func fileListBeginLoading() {
  482. self.fileListTableView.enclosingScrollView?.superview!.beginLoading()
  483. }
  484. private func fileListEndLoading() {
  485. self.fileListTableView.enclosingScrollView?.superview?.endLoading()
  486. }
  487. }
  488. // MARK: - NSSplitViewDelegate
  489. extension KMCloudDocumentsViewController: NSSplitViewDelegate {
  490. func splitView(_ splitView: NSSplitView, constrainMinCoordinate proposedMinimumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat {
  491. return 170.0
  492. }
  493. func splitView(_ splitView: NSSplitView, constrainMaxCoordinate proposedMaximumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat {
  494. return 170.0
  495. }
  496. func splitView(_ splitView: NSSplitView, shouldAdjustSizeOfSubview view: NSView) -> Bool {
  497. return false
  498. }
  499. func splitViewDidResizeSubviews(_ notification: Notification) {
  500. let rect = self.cloudSplitView.frame
  501. self.cloudLeftBox.setFrameSize(CGSize(width: 170, height: rect.size.height))
  502. self.cloudRightBox.frame = CGRect(origin: CGPoint(x: 171.0, y: 0), size: CGSize(width: rect.width - 171.0, height: rect.height))
  503. }
  504. func splitView(_ splitView: NSSplitView, constrainSplitPosition proposedPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat {
  505. return proposedPosition
  506. }
  507. func splitView(_ splitView: NSSplitView, canCollapseSubview subview: NSView) -> Bool {
  508. return false
  509. }
  510. func splitView(_ splitView: NSSplitView, shouldCollapseSubview subview: NSView, forDoubleClickOnDividerAt dividerIndex: Int) -> Bool {
  511. return false
  512. }
  513. func splitView(_ splitView: NSSplitView, shouldHideDividerAt dividerIndex: Int) -> Bool {
  514. return splitView.isEqual(to: self.cloudSplitView)
  515. }
  516. func splitView(_ splitView: NSSplitView, effectiveRect proposedEffectiveRect: NSRect, forDrawnRect drawnRect: NSRect, ofDividerAt dividerIndex: Int) -> NSRect {
  517. return proposedEffectiveRect
  518. }
  519. func splitView(_ splitView: NSSplitView, additionalEffectiveRectOfDividerAt dividerIndex: Int) -> NSRect {
  520. return NSMakeRect(0, 0, 0, 0)
  521. }
  522. }
  523. // MARK: - NSCollectionViewDataSource
  524. extension KMCloudDocumentsViewController: NSCollectionViewDataSource {
  525. func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
  526. if collectionView.isEqual(to: emptyCollectionView) {
  527. return self.cloudPlates.count
  528. }
  529. return 0
  530. }
  531. func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
  532. if collectionView.isEqual(to: emptyCollectionView) {
  533. let item: KMCloudEmptyCollectionViewItem = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "KMCloudEmptyCollectionViewItem"), for: indexPath) as! KMCloudEmptyCollectionViewItem
  534. let state = self.cloudPlates[indexPath.item]
  535. item.refreshUI(item: state.rawValue)
  536. return item
  537. }
  538. return NSCollectionViewItem.init()
  539. }
  540. }
  541. // MARK: - NSCollectionViewDelegate
  542. extension KMCloudDocumentsViewController: NSCollectionViewDelegate {
  543. func collectionView(_ collectionView: NSCollectionView, didSelectItemsAt indexPaths: Set<IndexPath>) {
  544. if collectionView.isEqual(to: emptyCollectionView) {
  545. let state = self.cloudPlates[indexPaths.first!.item]
  546. loginCloud(state: state)
  547. }
  548. }
  549. }
  550. // MARK: - NSCollectionViewDelegateFlowLayout
  551. extension KMCloudDocumentsViewController: NSCollectionViewDelegateFlowLayout {
  552. func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> NSSize {
  553. if collectionView.isEqual(to: emptyCollectionView) {
  554. return self.emptyCollectionView.itemSize
  555. }
  556. return CGSize(width: 218, height: 224)
  557. }
  558. func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
  559. if collectionView.isEqual(to: emptyCollectionView) {
  560. return self.emptyCollectionView.minimumLineSpacing
  561. }
  562. return 14
  563. }
  564. func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
  565. if collectionView.isEqual(to: emptyCollectionView) {
  566. return self.emptyCollectionView.minimumInteritemSpacing
  567. }
  568. return 14
  569. }
  570. func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, insetForSectionAt section: Int) -> NSEdgeInsets {
  571. if (collectionView.isEqual(to: self.emptyCollectionView)) {
  572. let width: CGFloat = NSWidth(collectionView.superview!.frame)
  573. let height: CGFloat = NSHeight(collectionView.superview!.frame)
  574. let itemSize = self.emptyCollectionView.itemSize
  575. let itemCount: Int = self.emptyCollectionView.numberOfItems(inSection: 0)
  576. let itemHSpace = self.emptyCollectionView.minimumLineSpacing
  577. let itemVSpace = self.emptyCollectionView.minimumInteritemSpacing
  578. var left: CGFloat = (width - itemSize.width * CGFloat(itemCount) - itemHSpace * CGFloat(itemCount-1)) * 0.5
  579. if (left < 0) {
  580. left = 0
  581. }
  582. var top: CGFloat = (height - itemSize.height * CGFloat(itemCount) - itemVSpace * CGFloat(itemCount-1)) * 0.5
  583. if (top < 0) {
  584. top = 0
  585. }
  586. return NSEdgeInsetsMake(top, left, top, left)
  587. }
  588. return NSEdgeInsetsZero
  589. }
  590. }
  591. // MARK: NSTableViewDelegate
  592. extension KMCloudDocumentsViewController: NSTableViewDelegate {
  593. func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
  594. if tableView.isEqual(to: accountListTableView) {
  595. return 57
  596. } else if tableView.isEqual(to: fileListTableView) {
  597. return 75
  598. }
  599. return 0;
  600. }
  601. func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
  602. let identifier = tableColumn?.identifier
  603. if tableView.isEqual(to: accountListTableView) {
  604. let server: KMCloudServer = self.accounts[row] as! KMCloudServer
  605. let cellView: KMCloudAccountListTableviewCell = tableView.makeView(withIdentifier:identifier!, owner: self) as! KMCloudAccountListTableviewCell
  606. cellView.accountLabel.stringValue = server.userEmail ?? ""
  607. cellView.toolTip = server.userEmail
  608. return cellView
  609. } else if tableView.isEqual(to: fileListTableView) {
  610. let file: KMServicesCloudFile = self.cloudFiles[row] as! KMServicesCloudFile
  611. if identifier == NSUserInterfaceItemIdentifier("name") {
  612. let cellView: KMCloudFileNameListTableviewCell = tableView.makeView(withIdentifier:identifier!, owner: self) as! KMCloudFileNameListTableviewCell
  613. if (file.filetype == .file) {
  614. let fileType = KMCloudDocumentTools.getFileType(self.currentAccount!, file)
  615. let image = NSWorkspace.shared.icon(forFileType: fileType)
  616. cellView.fileImageView.image = image
  617. cellView.subtitleLabel.stringValue = fileType
  618. } else {
  619. cellView.fileImageView.image = NSImage(named: NSImage.folderName)
  620. cellView.subtitleLabel.stringValue = "Folders"
  621. }
  622. cellView.titleLabel.stringValue = file.fileName
  623. return cellView
  624. } else if identifier == NSUserInterfaceItemIdentifier("modifyTime") {
  625. let cellView: KMCloudFileModifyTimeListTableviewCell = tableView.makeView(withIdentifier:identifier!, owner: self) as! KMCloudFileModifyTimeListTableviewCell
  626. if (file.fileModiDateString != nil) {
  627. cellView.modifyTimeLabel.stringValue = KMCloudDocumentTools.parseDate(file.fileModiDate)
  628. } else {
  629. cellView.modifyTimeLabel.stringValue = ""
  630. }
  631. return cellView
  632. } else if identifier == NSUserInterfaceItemIdentifier("size") {
  633. let cellView: KMCloudFileSizeListTableviewCell = tableView.makeView(withIdentifier:identifier!, owner: self) as! KMCloudFileSizeListTableviewCell
  634. if (file.filetype == .file) {
  635. cellView.sizeLabel.stringValue = file.fileSizeString
  636. } else {
  637. cellView.sizeLabel.stringValue = ""
  638. }
  639. return cellView
  640. } else {
  641. let cellView: KMCloudFileNameListTableviewCell = tableView.makeView(withIdentifier:identifier!, owner: self) as! KMCloudFileNameListTableviewCell
  642. return cellView
  643. }
  644. } else {
  645. let cellView: KMCloudAccountListTableviewCell = tableView.makeView(withIdentifier:identifier!, owner: self) as! KMCloudAccountListTableviewCell
  646. return cellView
  647. }
  648. }
  649. func tableViewSelectionDidChange(_ notification: Notification) {
  650. let tableView = notification.object as! NSTableView
  651. if tableView.isEqual(to: accountListTableView) {
  652. let server: KMCloudServer = self.accounts[self.accountListTableView.selectedRow] as! KMCloudServer
  653. self.updateFilesList(server, nil)
  654. self.pathString = NSLocalizedString("Cloud Documents", comment: "")
  655. self.myPathControl.urlString = self.pathString
  656. } else if tableView.isEqual(to: fileListTableView) {}
  657. }
  658. }
  659. // MARK: NSTableViewDataSource
  660. extension KMCloudDocumentsViewController: NSTableViewDataSource {
  661. func numberOfRows(in tableView: NSTableView) -> Int {
  662. if tableView.isEqual(to: accountListTableView) {
  663. return self.accounts.count
  664. } else if tableView.isEqual(to: fileListTableView) {
  665. return self.cloudFiles.count
  666. }
  667. return 0
  668. }
  669. }
  670. extension KMCloudDocumentsViewController: KMLoadingProtocol {
  671. func beginLoading() {
  672. self.view.beginLoading()
  673. }
  674. func endLoading() {
  675. self.view.endLoading()
  676. }
  677. }
  678. extension KMCloudDocumentsViewController: KMMenuTableViewDelegate {
  679. func km_menu(for event: NSEvent) -> NSMenu? {
  680. let point = self.fileListTableView.convert(event.locationInWindow, from: nil)
  681. let index = self.fileListTableView.row(at: point)
  682. if (index < 0) { /// 空白处
  683. return nil
  684. }
  685. let file: KMServicesCloudFile = self.cloudFiles[index] as! KMServicesCloudFile
  686. if (file.filetype == .folder) {
  687. let menu = NSMenu(title: "")
  688. let editItem = NSMenuItem(title: NSLocalizedString("Open Folder", comment: ""), action: #selector(openFolderMenuClick), keyEquivalent: "")
  689. editItem.target = self
  690. editItem.tag = index
  691. menu.addItem(editItem)
  692. return menu
  693. }
  694. if (file.filetype == .file) {
  695. let fileExtension: String = file.fileName.components(separatedBy: ".").last!
  696. if (fileExtension.lowercased() != "pdf") {
  697. return nil
  698. }
  699. let menu = NSMenu(title: "")
  700. let editItem = NSMenuItem(title: NSLocalizedString("Open File", comment: ""), action: #selector(openFileMenuClick), keyEquivalent: "")
  701. editItem.target = self
  702. editItem.tag = index
  703. menu.addItem(editItem)
  704. return menu
  705. }
  706. return nil
  707. }
  708. }