CloudFileListController.swift 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. //
  2. // CloudFileListController.swift
  3. // O2Platform
  4. //
  5. // Created by FancyLou on 2019/10/17.
  6. // Copyright © 2019 zoneland. All rights reserved.
  7. //
  8. import UIKit
  9. import CocoaLumberjack
  10. import Promises
  11. import QuickLook
  12. //当前页面显示模式 normal:普通页面 shareToMe:分享给我的页面 myShare:我分享的页面
  13. enum FileListShowMode {
  14. case normal
  15. case shareToMe
  16. case myShare
  17. }
  18. class CloudFileListController: CloudFileBaseVC {
  19. private let tableViewBottomConstraintName = "tableViewBottomConstraint"
  20. //当前页面显示模式
  21. var showMode: FileListShowMode = .normal
  22. //分享id 分享的二级以及后面的列表请求需要
  23. private var shareId: String = ""
  24. //面包屑 列表 可以传入顶级组织的OOFolder
  25. var breadcrumbList: [OOFolder] = []
  26. //table 数据
  27. private var dataList: [DataModel] = []
  28. //底部工具栏
  29. var toolbarView: UIToolbar!
  30. @IBOutlet weak var tableView: UITableView!
  31. @IBOutlet weak var breadcrumBar: UIScrollView!
  32. override func viewDidLoad() {
  33. super.viewDidLoad()
  34. //最后一个 设置title
  35. switch self.showMode {
  36. case .normal:
  37. self.title = Languager.standardLanguager().string(key: "Cloud Files")
  38. self.navigationItem.rightBarButtonItems = [UIBarButtonItem(image: UIImage(named: "add"), style: .plain, target: self, action: #selector(addEvent))]
  39. break
  40. case .shareToMe:
  41. self.title = Languager.standardLanguager().string(key: "Cloud File Share To Me")
  42. let btnName = Languager.standardLanguager().string(key: "Cloud File My Share Files")
  43. self.navigationItem.rightBarButtonItems = [UIBarButtonItem(title: btnName, style: .plain, target: self, action: #selector(openMyShare))]
  44. break
  45. case .myShare:
  46. self.title = Languager.standardLanguager().string(key: "Cloud File My Share Files")
  47. self.navigationItem.rightBarButtonItems = []
  48. break
  49. }
  50. //初始化数据
  51. if self.breadcrumbList.isEmpty {
  52. let all = OOFolder()
  53. all.id = ""
  54. all.name = Languager.standardLanguager().string(key: "All File")
  55. self.breadcrumbList.append(all)
  56. }
  57. //toolbar 初始化底部工具栏 先放在屏幕下面
  58. self.toolbarView = UIToolbar(frame: CGRect(x: 0, y: self.view.height - 44, width: self.view.width, height: 44))
  59. //初始化tableView
  60. self.tableView.dataSource = self
  61. self.tableView.delegate = self
  62. self.tableView.register(UINib.init(nibName: "CFFileTableViewCell", bundle: nil), forCellReuseIdentifier: "CFFileTableViewCell")
  63. self.tableView.register(UINib.init(nibName: "CFFolderTableViewCell", bundle: nil), forCellReuseIdentifier: "CFFolderTableViewCell")
  64. self.loadListData()
  65. }
  66. // MARK: - private
  67. //点击新建按钮
  68. @objc private func addEvent() {
  69. var actions: [UIAlertAction] = []
  70. let uploadFile = Languager.standardLanguager().string(key: "Upload File")
  71. let newFile = UIAlertAction(title: uploadFile, style: .default) { (action) in
  72. self.choosePhotoAndUpload()
  73. }
  74. let newFolderTitle = Languager.standardLanguager().string(key: "New Folder")
  75. let newFolder = UIAlertAction(title: newFolderTitle, style: .default) { (action) in
  76. self.createFolder()
  77. }
  78. actions.append(newFile)
  79. actions.append(newFolder)
  80. let newMsg = Languager.standardLanguager().string(key: "New")
  81. self.showSheetAction(title: "", message: newMsg, actions: actions)
  82. }
  83. //点击打开我分享的页面
  84. @objc private func openMyShare() {
  85. if let myShareVC = self.storyboard?.instantiateViewController(withIdentifier: "cloudFileListMultiModeVC") as? CloudFileListController {
  86. myShareVC.showMode = .myShare
  87. myShareVC.breadcrumbList = []
  88. self.pushVC(myShareVC)
  89. }
  90. }
  91. private func reloadUI() {
  92. self.refreshBottomToolBar()
  93. self.tableView.reloadData()
  94. }
  95. private func refreshBreadcrumbBar() {
  96. self.breadcrumBar.removeSubviews()
  97. var oX = CGFloat(4.0)
  98. let arrowW = CGFloat(24)
  99. let arrowH = CGFloat(32)
  100. breadcrumbList.forEachEnumerated { (index, bar) in
  101. let name = bar.name ?? ""
  102. var textColor:UIColor
  103. if self.breadcrumbList.count == (index+1) {
  104. textColor = UIColor(hex:"#666666")
  105. }else {
  106. textColor = base_color
  107. }
  108. let firstSize = name.getSize(with: 15)
  109. let oY = (self.breadcrumBar.bounds.height - firstSize.height) / 2
  110. let firstLabel = UILabel(frame: CGRect(x: CGFloat(oX), y: oY, width: firstSize.width, height: firstSize.height))
  111. firstLabel.textAlignment = .left
  112. let textAttributes = [NSAttributedString.Key.foregroundColor: textColor,NSAttributedString.Key.font:UIFont(name:"PingFangSC-Regular",size:15)!]
  113. firstLabel.attributedText = NSMutableAttributedString(string: name, attributes: textAttributes)
  114. firstLabel.sizeToFit()
  115. self.breadcrumBar.addSubview(firstLabel)
  116. oX += firstSize.width
  117. if self.breadcrumbList.count != (index+1) {
  118. let arrowY = (self.breadcrumBar.bounds.height - arrowH) / 2
  119. let arrowImage = UIImageView(frame: CGRect(x: CGFloat(oX), y: arrowY, width: arrowW, height: arrowH))
  120. arrowImage.image = UIImage(named: "arrow_r")
  121. arrowImage.contentMode = .scaleAspectFit
  122. self.breadcrumBar.addSubview(arrowImage)
  123. oX += arrowW
  124. }
  125. firstLabel.addTapGesture(action: { (rec) in
  126. DDLogDebug("点击了 \(index)")
  127. if self.breadcrumbList.count != (index+1) {
  128. var newList:[OOFolder] = []
  129. for i in 0...index {
  130. newList.append(self.breadcrumbList[i])
  131. }
  132. self.breadcrumbList = newList
  133. self.loadListData()
  134. }
  135. })
  136. }
  137. var size = self.breadcrumBar.contentSize;
  138. size.width = oX;
  139. self.breadcrumBar.showsHorizontalScrollIndicator = true;
  140. self.breadcrumBar.contentSize = size;
  141. self.breadcrumBar.bounces = true;
  142. }
  143. //底部工具栏中的单个按钮生成
  144. fileprivate func generateBottomButton(_ items: inout [UIBarButtonItem], name: String, tapCall: @escaping ()->Void) {
  145. let spaceItem = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
  146. let btn = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
  147. btn.setTitle(name, for: .normal)
  148. btn.setTitleColor(base_color, for: .normal)
  149. btn.addTapGesture { (tap) in
  150. tapCall()
  151. }
  152. let item = UIBarButtonItem(customView: btn)
  153. items.append(spaceItem)
  154. items.append(item)
  155. items.append(spaceItem)
  156. }
  157. //重新生成刷新底部工具栏和按钮
  158. private func refreshBottomToolBar() {
  159. let totalCount = self.checkedFileList.count + self.checkedFolderList.count
  160. if totalCount > 0 {
  161. var items: [UIBarButtonItem] = []
  162. switch self.showMode {
  163. case .normal:
  164. if totalCount == 1 {
  165. let reName = Languager.standardLanguager().string(key: "Rename")
  166. generateBottomButton(&items, name: reName, tapCall: {
  167. self.renameOp()
  168. })
  169. }
  170. //其他按钮 删除 移动 分享
  171. let deleteName = Languager.standardLanguager().string(key: "Delete")
  172. self.generateBottomButton(&items, name: deleteName) {
  173. self.deleteOp()
  174. }
  175. let moveName = Languager.standardLanguager().string(key: "Move")
  176. self.generateBottomButton(&items, name: moveName) {
  177. self.moveOp()
  178. }
  179. let shareName = Languager.standardLanguager().string(key: "Share")
  180. self.generateBottomButton(&items, name: shareName) {
  181. self.shareOp()
  182. }
  183. break
  184. case .myShare:
  185. //取消分享
  186. let deleteName = Languager.standardLanguager().string(key: "Share Delete")
  187. self.generateBottomButton(&items, name: deleteName) {
  188. self.deleteMyShareFile()
  189. }
  190. break
  191. case .shareToMe:
  192. //屏蔽分享給我的
  193. let deleteName = Languager.standardLanguager().string(key: "Shield Share")
  194. self.generateBottomButton(&items, name: deleteName) {
  195. self.shieldFileShareToMe()
  196. }
  197. break
  198. }
  199. self.layoutBottomBar(items: items)
  200. }else {
  201. var c = false
  202. self.view.constraints.forEach { (constraint) in
  203. if constraint.identifier == self.tableViewBottomConstraintName {
  204. c = true
  205. }
  206. }
  207. if !c {
  208. let bottom = NSLayoutConstraint(item: self.view as Any, attribute: NSLayoutConstraint.Attribute.bottom, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self.tableView, attribute: NSLayoutConstraint.Attribute.bottom, multiplier: 1, constant: 0)
  209. bottom.identifier = self.tableViewBottomConstraintName
  210. self.toolbarView.removeConstraints(self.toolbarView.constraints)
  211. self.toolbarView.removeFromSuperview()
  212. self.view.addConstraint(bottom)
  213. self.view.layoutIfNeeded()
  214. }
  215. }
  216. }
  217. //布局底部工具栏
  218. private func layoutBottomBar(items: [UIBarButtonItem]) {
  219. DDLogDebug("layout bottom \(items.count)")
  220. let toolBarHeight = CGFloat(44.0)
  221. var bottomSpace = CGFloat(0)
  222. if iPhoneX {
  223. bottomSpace = CGFloat(-34.0)
  224. }
  225. if items.count > 0 {
  226. self.toolbarView.items = items
  227. self.view.addSubview(self.toolbarView)
  228. self.toolbarView.translatesAutoresizingMaskIntoConstraints = false
  229. //高度约束
  230. let heightC = NSLayoutConstraint(item: self.toolbarView as Any, attribute: NSLayoutConstraint.Attribute.height, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 0.0, constant: toolBarHeight)
  231. self.toolbarView.addConstraint(heightC)
  232. //底部约束
  233. let bottom = NSLayoutConstraint(item: self.toolbarView as Any, attribute: NSLayoutConstraint.Attribute.bottom, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self.view, attribute: NSLayoutConstraint.Attribute.bottom, multiplier: 1, constant: bottomSpace)
  234. //右边约束
  235. let trailing = NSLayoutConstraint(item: self.toolbarView as Any, attribute: NSLayoutConstraint.Attribute.trailing, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self.view, attribute: NSLayoutConstraint.Attribute.trailing, multiplier: 1, constant: 0)
  236. //左边约束
  237. let leading = NSLayoutConstraint(item: self.toolbarView as Any, attribute: NSLayoutConstraint.Attribute.leading, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self.view, attribute: NSLayoutConstraint.Attribute.leading, multiplier: 1, constant: 0)
  238. self.view.addConstraints([bottom, leading, trailing])
  239. self.view.constraints.forEach { (constraint) in
  240. //删除原来tableView的底部约束
  241. if constraint.identifier == self.tableViewBottomConstraintName {
  242. self.view.removeConstraint(constraint)
  243. }
  244. }
  245. //添加tableView和底部工具栏的约束
  246. let webcTop = NSLayoutConstraint(item: self.tableView as Any, attribute: NSLayoutConstraint.Attribute.bottom, relatedBy: NSLayoutConstraint.Relation.equal, toItem: self.toolbarView as Any, attribute: NSLayoutConstraint.Attribute.top, multiplier: 1, constant: 0)
  247. self.view.addConstraint(webcTop)
  248. self.view.layoutIfNeeded()
  249. }
  250. }
  251. private func isFolderChecked(_ folder: OOFolder) -> Bool {
  252. return self.checkedFolderList.contains(folder)
  253. }
  254. private func isFileChecked(_ file: OOAttachment) -> Bool {
  255. return self.checkedFileList.contains(file)
  256. }
  257. // MARK: - 后台数据服务
  258. override func loadListData() {
  259. self.refreshBreadcrumbBar()
  260. self.showLoading()
  261. //清空数据
  262. self.dataList = []
  263. self.checkedFileList = []
  264. self.checkedFolderList = []
  265. //分模式查询数据
  266. switch self.showMode {
  267. case .normal:
  268. let id = self.breadcrumbList[self.breadcrumbList.count-1].id ?? ""
  269. self.cFileVM.loadCloudFileList(folderParentId: id)
  270. .then { (result) in
  271. self.dataList = result
  272. self.hideLoading()
  273. self.reloadUI()
  274. }.catch { (error) in
  275. DDLogError(error.localizedDescription)
  276. self.hideLoading()
  277. self.reloadUI()
  278. }
  279. break
  280. case .myShare:
  281. let folder = self.breadcrumbList[self.breadcrumbList.count-1]
  282. var parentId = ""
  283. //有fileId的是分享或者分享给我的 顶层列表对象才有
  284. if let fileId = folder.fileId, !fileId.isBlank {
  285. parentId = fileId
  286. self.shareId = folder.id ?? ""
  287. }else {
  288. parentId = folder.id ?? ""
  289. }
  290. self.cFileVM.loadMyShareList(folderParentId: parentId, shareId: self.shareId)
  291. .then { (result) in
  292. self.dataList = result
  293. self.hideLoading()
  294. self.reloadUI()
  295. }.catch { (error) in
  296. DDLogError(error.localizedDescription)
  297. self.hideLoading()
  298. self.reloadUI()
  299. }
  300. break
  301. case .shareToMe:
  302. let folder = self.breadcrumbList[self.breadcrumbList.count-1]
  303. var parentId = ""
  304. //有fileId的是分享或者分享给我的 顶层列表对象才有
  305. if let fileId = folder.fileId, !fileId.isBlank {
  306. parentId = fileId
  307. self.shareId = folder.id ?? ""
  308. }else {
  309. parentId = folder.id ?? ""
  310. }
  311. self.cFileVM.loadShareToMeList(folderParentId: parentId, shareId: self.shareId)
  312. .then { (result) in
  313. self.dataList = result
  314. self.hideLoading()
  315. self.reloadUI()
  316. }.catch { (error) in
  317. DDLogError(error.localizedDescription)
  318. self.hideLoading()
  319. self.reloadUI()
  320. }
  321. break
  322. }
  323. }
  324. //新建文件夹
  325. private func createFolder() {
  326. let newFolderTitle = Languager.standardLanguager().string(key: "New Folder")
  327. self.showPromptAlert(title: newFolderTitle, message: "", inputText: "") { (ok, result) in
  328. if result != "" {
  329. let folderId = self.breadcrumbList.last?.id ?? ""
  330. self.cFileVM.createFolder(name: result, superior: folderId).then({ (id) in
  331. self.loadListData()
  332. }).catch({ (error) in
  333. DDLogError("创建文件失败,\(error.localizedDescription)")
  334. let errTitle = Languager.standardLanguager().string(key: "Create Folder Error Message")
  335. self.showError(title: errTitle)
  336. })
  337. }
  338. }
  339. }
  340. //选择照片上传
  341. private func choosePhotoAndUpload() {
  342. self.choosePhotoWithImagePicker { (fileName, imageData) in
  343. self.showLoading()
  344. let folderId = self.breadcrumbList.last?.id ?? O2.O2_First_ID
  345. self.cFileVM.uploadFile(folderId: folderId, fileName: fileName, file: imageData)
  346. .then { result in
  347. DDLogInfo("上传成功,\(result)")
  348. self.hideLoading()
  349. self.loadListData()
  350. }.catch { (error) in
  351. DDLogError(error.localizedDescription)
  352. self.hideLoading()
  353. }
  354. }
  355. }
  356. //取消分享
  357. private func deleteMyShareFile() {
  358. let totalCount = self.checkedFileList.count + self.checkedFolderList.count
  359. if totalCount > 0 {
  360. let alert = Languager.standardLanguager().string(key: "Alert")
  361. let msg = Languager.standardLanguager().string(key: "Delete My Share File Confirm Message")
  362. self.showDefaultConfirm(title: alert, message: msg) { (action) in
  363. var ids:[String] = []
  364. self.checkedFolderList.forEach { (folder) in
  365. ids.append(folder.id!)
  366. }
  367. self.checkedFileList.forEach { (file) in
  368. ids.append(file.id!)
  369. }
  370. self.cFileVM.deleteShareList(shareList: ids)
  371. .then({ (result) in
  372. self.loadListData()
  373. }).catch({ (error) in
  374. DDLogError(error.localizedDescription)
  375. self.showError(title: error.localizedDescription)
  376. })
  377. }
  378. }
  379. }
  380. //屏蔽分享給我的文件
  381. private func shieldFileShareToMe() {
  382. let totalCount = self.checkedFileList.count + self.checkedFolderList.count
  383. if totalCount > 0 {
  384. let alert = Languager.standardLanguager().string(key: "Alert")
  385. let msg = Languager.standardLanguager().string(key: "Shield Share File Confirm Message")
  386. self.showDefaultConfirm(title: alert, message: msg) { (action) in
  387. var ids:[String] = []
  388. self.checkedFolderList.forEach { (folder) in
  389. ids.append(folder.id!)
  390. }
  391. self.checkedFileList.forEach { (file) in
  392. ids.append(file.id!)
  393. }
  394. self.cFileVM.shieldShareList(shareList: ids)
  395. .then({ (result) in
  396. self.loadListData()
  397. }).catch({ (error) in
  398. DDLogError(error.localizedDescription)
  399. self.showError(title: error.localizedDescription)
  400. })
  401. }
  402. }
  403. }
  404. }
  405. // MARK: - UITableView
  406. extension CloudFileListController: UITableViewDelegate, UITableViewDataSource {
  407. func numberOfSections(in tableView: UITableView) -> Int {
  408. return 1
  409. }
  410. func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  411. return self.dataList.count
  412. }
  413. func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
  414. return UIView(frame: CGRect.zero)
  415. }
  416. func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  417. let item = self.dataList[indexPath.row]
  418. // 分享列表的时候 二级一下目录文件不能显示checkbox 它们是不能操作的
  419. var isShowCheckBox = true
  420. if self.showMode != .normal && self.breadcrumbList.count > 1 {
  421. isShowCheckBox = false
  422. }
  423. if item is OOFolder {
  424. let folder = item as! OOFolder
  425. if let cell = tableView.dequeueReusableCell(withIdentifier: "CFFolderTableViewCell", for: indexPath) as? CFFolderTableViewCell {
  426. cell.clickdelegate = self
  427. cell.setData(folder: folder, checked: self.isFolderChecked(folder), isShowCheck: isShowCheckBox)
  428. return cell
  429. } else {
  430. return UITableViewCell()
  431. }
  432. } else if item is OOAttachment {
  433. let file = item as! OOAttachment
  434. if let cell = tableView.dequeueReusableCell(withIdentifier: "CFFileTableViewCell", for: indexPath) as? CFFileTableViewCell {
  435. cell.clickdelegate = self
  436. cell.setData(file: file, checked: self.isFileChecked(file), isShowCheck: isShowCheckBox)
  437. return cell
  438. } else {
  439. return UITableViewCell()
  440. }
  441. }else {
  442. return UITableViewCell()
  443. }
  444. }
  445. func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
  446. //点击处理
  447. let item = self.dataList[indexPath.row]
  448. if item is OOFolder { //点击文件夹进入下一层
  449. let folder = item as! OOFolder
  450. self.breadcrumbList.append(folder)
  451. self.loadListData()
  452. } else if item is OOAttachment { //点击文件
  453. let file = item as! OOAttachment
  454. if let trueId = file.fileId {
  455. file.id = trueId
  456. }
  457. self.clickFile(file: file)
  458. }
  459. tableView.deselectRow(at: indexPath, animated: true)
  460. }
  461. }
  462. // MARK: - Ext CloudFileCheckClickDelegate
  463. extension CloudFileListController: CloudFileCheckClickDelegate {
  464. func clickFolder(_ folder: OOFolder) {
  465. DDLogDebug("clci folder")
  466. if self.checkedFolderList.contains(folder) {
  467. self.checkedFolderList.removeFirst(folder)
  468. }else {
  469. self.checkedFolderList.append(folder)
  470. }
  471. self.reloadUI()
  472. }
  473. func clickFile(_ file: OOAttachment) {
  474. DDLogDebug("click file")
  475. if self.checkedFileList.contains(file) {
  476. self.checkedFileList.removeFirst(file)
  477. }else {
  478. self.checkedFileList.append(file)
  479. }
  480. self.reloadUI()
  481. }
  482. }