Quellcode durchsuchen

更新语音助手

fancy vor 5 Jahren
Ursprung
Commit
d2a98eeded
100 geänderte Dateien mit 441 neuen und 13441 gelöschten Zeilen
  1. 1 0
      o2ios/.gitignore
  2. 122 1006
      o2ios/O2Platform.xcodeproj/project.pbxproj
  3. 1 1
      o2ios/O2Platform/App/Applications/c/OOAppEditController.swift
  4. 4 5
      o2ios/O2Platform/App/Calendar-日程管理/Controller/OOCalendarViewController.swift
  5. 5 5
      o2ios/O2Platform/App/Contact-通讯录/Controller/ContactGroupPickerViewController.swift
  6. 3 3
      o2ios/O2Platform/App/Contact-通讯录/Controller/ContactIdentityPickerViewController.swift
  7. 3 3
      o2ios/O2Platform/App/Contact-通讯录/Controller/ContactPersonPickerViewController.swift
  8. 3 3
      o2ios/O2Platform/App/Contact-通讯录/Controller/ContactUnitPickerViewController.swift
  9. 0 281
      o2ios/O2Platform/App/Contact-通讯录/Controller/OOPersonsViewController.swift
  10. 0 42
      o2ios/O2Platform/App/Contact-通讯录/Controller/OOPersonsViewController.xib
  11. 2 2
      o2ios/O2Platform/App/Login-绑定登录/c/OOBindNodeViewController.swift
  12. 2 2
      o2ios/O2Platform/App/Login-绑定登录/c/OOBindRegisterController.swift
  13. 0 55
      o2ios/O2Platform/App/Login-绑定登录/vm/OOLoginViewModel.swift
  14. 8 7
      o2ios/O2Platform/App/NewAttance-考勤打卡/c/OOAttanceCheckInController.swift
  15. 6 6
      o2ios/O2Platform/App/NewAttance-考勤打卡/c/OOAttanceSettingController.swift
  16. 10 6
      o2ios/O2Platform/App/NewAttance-考勤打卡/c/OOAttandanceWorkPlaceController.swift
  17. 0 7
      o2ios/O2Platform/App/Setting-设置/c/SPersonViewController.swift
  18. 120 126
      o2ios/O2Platform/App/VoiceAI-语音处理/Controller/OOVoiceAIController.swift
  19. 9 9
      o2ios/O2Platform/App/meeting-会议/Controller/OOMeetingInforController.swift
  20. 3 3
      o2ios/O2Platform/App/meeting-会议/Controller/OOMeetingMeetingRoomManageController.swift
  21. 1 104
      o2ios/O2Platform/AppDelegate.swift
  22. 12 0
      o2ios/O2Platform/Extension/String+Extenstion.swift
  23. 24 0
      o2ios/O2Platform/Extension/UIColor+Extension.swift
  24. 102 0
      o2ios/O2Platform/Extension/UIImage+Extension.swift
  25. 0 52
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/Model/JCCEmoticon.swift
  26. 0 49
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/Model/JCCEmoticonGroup.swift
  27. 0 47
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/Model/JCCEmoticonLarge.swift
  28. 0 62
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/Model/JCDraft.swift
  29. 0 170
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/Model/JCMessage.swift
  30. 0 25
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/Model/JCRemind.swift
  31. 0 26
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/Protocols/JCMessageContentViewType.swift
  32. 0 81
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/Protocols/JCMessageOptions.swift
  33. 0 45
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/Protocols/JCMessageType.swift
  34. 0 15
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/Protocols/JCUserType.swift
  35. 0 132
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/FileCell.swift
  36. 0 80
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/GroupAvatorCell.swift
  37. 0 85
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/ImageFileCell.swift
  38. 0 29
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/ImageFileHeader.swift
  39. 0 494
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCChatView.swift
  40. 0 364
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCChatViewCell.swift
  41. 0 46
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCChatViewData.swift
  42. 0 324
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCChatViewLayout.swift
  43. 0 40
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCChatViewLayoutAttributes.swift
  44. 0 38
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCChatViewLayoutAttributesInfo.swift
  45. 0 380
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCChatViewUpdate.swift
  46. 0 232
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCConversationCell.swift
  47. 0 78
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCGroupMemberCell.swift
  48. 0 215
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCGroupSettingCell.swift
  49. 0 74
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCMessageAvatarView.swift
  50. 0 32
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCMessageCardView.swift
  51. 0 114
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCMessageTipsView.swift
  52. 0 56
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCNetworkTipsCell.swift
  53. 0 101
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCSelectMemberCell.swift
  54. 0 90
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCSingleSettingCell.swift
  55. 0 58
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCUpdateMemberCell.swift
  56. 0 83
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JACMessageImageContentView.swift
  57. 0 27
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCBusinessCardContent.swift
  58. 0 125
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCBusinessCardContentView.swift
  59. 0 28
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageFileContent.swift
  60. 0 127
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageFileContentView.swift
  61. 0 34
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageImageContent.swift
  62. 0 26
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageLocationContent.swift
  63. 0 70
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageLocationContentView.swift
  64. 0 39
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageNoticeContent.swift
  65. 0 41
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageNoticeContentView.swift
  66. 0 42
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageTextContent.swift
  67. 0 49
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageTextContentView.swift
  68. 0 93
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageTimeLineContent.swift
  69. 0 39
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageTimeLineContentView.swift
  70. 0 36
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageVideoContent.swift
  71. 0 115
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageVideoContentView.swift
  72. 0 36
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageVoiceContent.swift
  73. 0 124
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageVoiceContentView.swift
  74. 0 119
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/MorePopupView.swift
  75. 0 248
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/FileManagerViewController.swift
  76. 0 203
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/FileViewController.swift
  77. 0 276
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/FriendsBusinessCardViewController.swift
  78. 0 136
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/GroupAvatorViewController.swift
  79. 0 160
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/ImageFileViewController.swift
  80. 0 1347
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/JCChatViewController.swift
  81. 0 613
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/JCConversationListViewController.swift
  82. 0 112
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/JCDocumentViewController.swift
  83. 0 166
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/JCFileDownloadViewController.swift
  84. 0 269
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/JCForwardViewController.swift
  85. 0 144
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/JCGroupMembersViewController.swift
  86. 0 424
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/JCGroupSettingViewController.swift
  87. 0 199
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/JCRemindListViewController.swift
  88. 0 301
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/JCRemoveMemberViewController.swift
  89. 0 256
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/JCSingleSettingViewController.swift
  90. 0 441
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/JCUpdateMemberViewController.swift
  91. 0 232
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/ScanQRCodeViewController.swift
  92. 0 146
      o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/UnreadListViewController.swift
  93. 0 90
      o2ios/O2Platform/Framework/JMessage/ChatModule/Input/InputView/Emoticon/JCEmoticon.swift
  94. 0 125
      o2ios/O2Platform/Framework/JMessage/ChatModule/Input/InputView/Emoticon/JCEmoticonBackgroundView.swift
  95. 0 33
      o2ios/O2Platform/Framework/JMessage/ChatModule/Input/InputView/Emoticon/JCEmoticonGroup.swift
  96. 0 369
      o2ios/O2Platform/Framework/JMessage/ChatModule/Input/InputView/Emoticon/JCEmoticonInputView.swift
  97. 0 176
      o2ios/O2Platform/Framework/JMessage/ChatModule/Input/InputView/Emoticon/JCEmoticonInputViewLayout.swift
  98. 0 94
      o2ios/O2Platform/Framework/JMessage/ChatModule/Input/InputView/Emoticon/JCEmoticonLine.swift
  99. 0 119
      o2ios/O2Platform/Framework/JMessage/ChatModule/Input/InputView/Emoticon/JCEmoticonPage.swift
  100. 0 199
      o2ios/O2Platform/Framework/JMessage/ChatModule/Input/InputView/Emoticon/JCEmoticonPageView.swift

+ 1 - 0
o2ios/.gitignore

@@ -6,6 +6,7 @@
 build/
 DerivedData/
 BuildShell/
+O2Platform/Framework/BaiDuASR/
 
 ## Various settings
 *.pbxuser

Datei-Diff unterdrückt, da er zu groß ist
+ 122 - 1006
o2ios/O2Platform.xcodeproj/project.pbxproj


+ 1 - 1
o2ios/O2Platform/App/Applications/c/OOAppEditController.swift

@@ -45,7 +45,7 @@ class OOAppEditController: UITableViewController {
         }
         
         delegate?.appEditControllerUpdater()
-        MBProgressHUD_JChat.show(text: "更新成功", view: view, 2)
+        self.showMessage(msg: "更新成功")
     }
     
     func loadData() {

+ 4 - 5
o2ios/O2Platform/App/Calendar-日程管理/Controller/OOCalendarViewController.swift

@@ -163,8 +163,7 @@ class OOCalendarViewController: UITableViewController {
             showError(title: "日历名称不能为空!")
             return
         }
-
-        MBProgressHUD_JChat.showMessage(message: "正在保存...", toView: self.view)
+        self.showLoading(title: "正在保存...")
         /*
       var calendar = self.calendarInfo
       if calendarInfo != nil && calendarInfo?.id != nil { // 修改
@@ -196,7 +195,7 @@ class OOCalendarViewController: UITableViewController {
                 DDLogInfo("保存日历成功!!!\(result)")
                 self.closeWindow()
             }.always {
-                MBProgressHUD_JChat.hide(forView: self.view, animated: false)
+                self.hideLoading()
             }.catch { (error) in
                 DDLogError(error.localizedDescription)
                 self.showError(title: "保存日历错误!")
@@ -204,12 +203,12 @@ class OOCalendarViewController: UITableViewController {
 
     }
     private func deleteCalendar() {
-        MBProgressHUD_JChat.showMessage(message: "正在删除...", toView: self.view)
+        self.showLoading()
         viewModel.deleteCalendar(id: (calendarInfo?.id!)!).then { (result) in
             DDLogInfo("删除结果:\(result)")
             self.closeWindow()
         }.always {
-            MBProgressHUD_JChat.hide(forView: self.view, animated: false)
+            self.hideLoading()
         }.catch { (error) in
             DDLogError(error.localizedDescription)
             self.showError(title: "删除日历错误!")

+ 5 - 5
o2ios/O2Platform/App/Contact-通讯录/Controller/ContactGroupPickerViewController.swift

@@ -85,19 +85,19 @@ class ContactGroupPickerViewController: UITableViewController {
     
     private func loadFirstPageData() {
          DDLogDebug("loadFirstPageData ............group")
-        MBProgressHUD_JChat.showMessage(message: "loading...", toView: view)
+        self.showLoading()
         viewModel.loadGroupList(lastId: "(0)").then { (list)  in
             self.groupDataList.removeAll()
             self.groupDataList = list
             self.tableView.reloadData()
-            MBProgressHUD_JChat.hide(forView: self.view, animated: true)
+            self.hideLoading()
             if self.tableView.mj_header.isRefreshing(){
                 self.tableView.mj_header.endRefreshing()
             }
             DDLogDebug("loadFirstPageData ............finish")
         }.catch { (error) in
                 DDLogError(error.localizedDescription)
-                MBProgressHUD_JChat.hide(forView: self.view, animated: true)
+            self.hideLoading()
             if self.tableView.mj_header.isRefreshing(){
                 self.tableView.mj_header.endRefreshing()
             }
@@ -111,13 +111,13 @@ class ContactGroupPickerViewController: UITableViewController {
                     self.groupDataList.append(model)
                 })
                 self.tableView.reloadData()
-                MBProgressHUD_JChat.hide(forView: self.view, animated: true)
+                self.hideLoading()
                 if self.tableView.mj_footer.isRefreshing(){
                     self.tableView.mj_footer.endRefreshing()
                 }
                 }.catch { (error) in
                     DDLogError(error.localizedDescription)
-                    MBProgressHUD_JChat.hide(forView: self.view, animated: true)
+                    self.hideLoading()
                     if self.tableView.mj_footer.isRefreshing(){
                         self.tableView.mj_footer.endRefreshing()
                     }

+ 3 - 3
o2ios/O2Platform/App/Contact-通讯录/Controller/ContactIdentityPickerViewController.swift

@@ -123,7 +123,7 @@ class ContactIdentityPickerViewController: UITableViewController {
     
     //获取组织数据 必须先操作面包屑导航数据
     private func loadData() {
-        MBProgressHUD_JChat.showMessage(message: "loading...", toView: view)
+        self.showLoading()
         viewModel.loadUnitList(parent: unitParent, topList: topUnitList)
             .then { (list) -> Promise<[OOIdentityModel]> in
                 DDLogDebug("loadUnitList 结果: \(list.count)")
@@ -144,10 +144,10 @@ class ContactIdentityPickerViewController: UITableViewController {
                 DDLogDebug("loadIdentityList 结果: \(result.count)")
                 self.identityDataList = result
                 self.tableView.reloadData()
-                MBProgressHUD_JChat.hide(forView: self.view, animated: true)
+                self.hideLoading()
             }).catch { (error) in
                 DDLogError(error.localizedDescription)
-                MBProgressHUD_JChat.hide(forView: self.view, animated: true)
+                self.hideLoading()
         }
     }
     

+ 3 - 3
o2ios/O2Platform/App/Contact-通讯录/Controller/ContactPersonPickerViewController.swift

@@ -90,15 +90,15 @@ class ContactPersonPickerViewController: UITableViewController {
             self.personDataList.removeAll()
             self.tableView.reloadData()
         }else{
-            MBProgressHUD_JChat.showMessage(message: "loading...", toView: view)
+            self.showLoading()
             viewModel.searchPersonList(searchText: searchText!).then { (list)  in
                 self.personDataList.removeAll()
                 self.personDataList = list
                 self.tableView.reloadData()
-                MBProgressHUD_JChat.hide(forView: self.view, animated: true)
+                self.hideLoading()
                 }.catch { (error) in
                     DDLogError(error.localizedDescription)
-                    MBProgressHUD_JChat.hide(forView: self.view, animated: true)
+                   self.hideLoading()
                      
             }
         }

+ 3 - 3
o2ios/O2Platform/App/Contact-通讯录/Controller/ContactUnitPickerViewController.swift

@@ -117,7 +117,7 @@ class ContactUnitPickerViewController: UITableViewController {
     
     //获取组织数据 必须先操作面包屑导航数据
     private func loadData() {
-        MBProgressHUD_JChat.showMessage(message: "loading...", toView: view)
+        self.showLoading()
         viewModel.loadUnitList(parent: unitParent, topList: topUnitList, unitType: unitType)
             .then { (list)  in
                 DDLogDebug("loadUnitList 结果: \(list.count)")
@@ -128,10 +128,10 @@ class ContactUnitPickerViewController: UITableViewController {
                 bean.level = self.breadcrumbList.count
                 self.breadcrumbList.append(bean)
                 self.tableView.reloadData()
-                MBProgressHUD_JChat.hide(forView: self.view, animated: true)
+                self.hideLoading()
             }.catch { (error) in
                 DDLogError(error.localizedDescription)
-                MBProgressHUD_JChat.hide(forView: self.view, animated: true)
+                self.hideLoading()
         }
     }
     

+ 0 - 281
o2ios/O2Platform/App/Contact-通讯录/Controller/OOPersonsViewController.swift

@@ -1,281 +0,0 @@
-//
-//  OOPersonsViewController.swift
-//  O2Platform
-//
-//  Created by 刘振兴 on 2018/4/24.
-//  Copyright © 2018年 zoneland. All rights reserved.
-//
-
-import UIKit
-import RxSwift
-import RxCocoa
-import JMessage
-
-private let ooPersonCellIdentifier = "OOContactPersonCell"
-
-class OOPersonsViewController: UIViewController {
-    
-    @IBOutlet weak var tableView: UITableView!
-    
-    private let viewModel = OOPersonListViewModel()
-    
-    private var parameter = CommonPageModel()
-    
-    private var selectedPersons:[OOPersonModel] = []
-    
-    var isSingleSelected:Bool = true
-    
-    private var searchController:UISearchController!
-    
-    
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        navigationItem.rightBarButtonItem = UIBarButtonItem(title: "请选择", style: .plain, target: self, action: #selector(startChart(_:)))
-        setRightItem()
-        //===添加搜索=====
-        searchController = UISearchController.init(searchResultsController: nil)
-        searchController.searchResultsUpdater = self
-        searchController.dimsBackgroundDuringPresentation = false
-        searchController.hidesNavigationBarDuringPresentation = true
-        tableView.tableHeaderView = searchController.searchBar
-        tableView.register(UINib.init(nibName: "OOSelectPersonTableViewCell", bundle: nil), forCellReuseIdentifier: "OOSelectPersonTableViewCell")
-        definesPresentationContext = true
-        searchController.searchBar.delegate = self
-        //单选发起单聊
-        tableView.allowsSelection = true
-        if !isSingleSelected  {
-            tableView.allowsMultipleSelection = true
-        }
-      
-        tableView.register(UINib.init(nibName: "OOContactPersonCell", bundle: nil), forCellReuseIdentifier: ooPersonCellIdentifier)
-        tableView.delegate = self
-        tableView.dataSource = self
-        tableView.mj_header = MJRefreshNormalHeader(refreshingBlock: {
-            self.parameter = CommonPageModel()
-            self.viewModel.getAllPerson(false,self.parameter, callbackCompleted: { (parameter, errorMessage) in
-                self.parameter = parameter
-                self.reloadData()
-                if self.tableView.mj_header.isRefreshing() {
-                    self.tableView.mj_header.endRefreshing()
-                }
-            })
-        })
-        
-        tableView.mj_footer = MJRefreshAutoNormalFooter(refreshingBlock: {
-            if self.parameter.isLast() {
-                self.tableView.mj_footer.endRefreshingWithNoMoreData()
-            }else{
-                self.viewModel.getAllPerson(true,self.parameter, callbackCompleted: { (parameter, errorMessage) in
-                    self.parameter = parameter
-                    self.reloadData()
-                    if self.tableView.mj_footer.isRefreshing() {
-                        self.tableView.mj_footer.endRefreshing()
-                    }
-                })
-            }
-        })
-        
-        MBProgressHUD_JChat.showMessage(message: "loading...", toView: view)
-        viewModel.getAllPerson(false, parameter) { (parameter, errorMessage) in
-            MBProgressHUD_JChat.hide(forView: self.view, animated: true)
-            self.parameter = parameter
-            self.reloadData()
-        }
-    }
-
-    override func didReceiveMemoryWarning() {
-        super.didReceiveMemoryWarning()
-        // Dispose of any resources that can be recreated.
-    }
-    
-    @objc func startChart(_ sender:UIButton){
-        if isSingleSelected {
-            let username = selectedPersons.first?.id
-            MBProgressHUD_JChat.showMessage(message: "创建中...", toView: view)
-            JMSGConversation.createSingleConversation(withUsername: username!) { (result, error) in
-                MBProgressHUD_JChat.hide(forView: self.view, animated: true)
-                if error == nil {
-                    let conv = result as! JMSGConversation
-                    let vc = JCChatViewController(conversation: conv)
-                    NotificationCenter.default.post(name: NSNotification.Name(rawValue: kUpdateConversation), object: nil, userInfo: nil)
-                    self.navigationController?.pushViewController(vc, animated: true)
-                }else{
-                    O2Logger.error(error.debugDescription)
-                    MBProgressHUD_JChat.show(text: "创建会话失败,请重试", view: self.view)
-                }
-            }
-        }else{
-            MBProgressHUD_JChat.showMessage(message: "创建中...", toView: view)
-            let userNames = selectedPersons.map { (p) -> String in
-                return p.id!
-            }
-            JMSGGroup.createGroup(withName: nil, desc: nil, memberArray: userNames, completionHandler: { (result, error) in
-                MBProgressHUD_JChat.hide(forView: self.view, animated: true)
-                if error == nil {
-                    for vc in (self.navigationController?.viewControllers)! {
-                        if vc is JCConversationListViewController {
-                            self.navigationController?.popToViewController(vc, animated: true)
-                            let group = result as! JMSGGroup
-                            JMSGConversation.createGroupConversation(withGroupId: group.gid, completionHandler: { (result, error) in
-                                let conv = JMSGConversation.groupConversation(withGroupId: group.gid)
-                                let chatVC = JCChatViewController(conversation: conv!)
-                                vc.navigationController?.pushViewController(chatVC, animated: true)
-                            })
-                        }
-                    }
-                    
-                } else {
-                    O2Logger.error(error.debugDescription)
-                    MBProgressHUD_JChat.show(text: "创建会话失败,请确保添加的群聊成员都使用过O2移动端应用", view: self.view)
-                }
-            })
-        }
-    }
-    
-    private func reloadData(){
-        //selectedPersons.removeAll()
-        tableView.reloadSections(IndexSet(integer: 1), with: .automatic)
-    }
-    
-    private func setRightItem(){
-        navigationItem.rightBarButtonItem?.isEnabled  = !selectedPersons.isEmpty
-        if !selectedPersons.isEmpty {
-            navigationItem.rightBarButtonItem?.title = "确定(\(selectedPersons.count))"
-        }else{
-            navigationItem.rightBarButtonItem?.title = "请选择"
-        }
-    }
-
-}
-
-extension OOPersonsViewController:UITableViewDataSource,UITableViewDelegate {
-    func numberOfSections(in tableView: UITableView) -> Int {
-        return viewModel.numberOfSections()
-    }
-    
-    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
-        return viewModel.numberOfRowsInSection(section)
-    }
-    
-    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
-        if indexPath.section == 0 {
-            let personCell = tableView.dequeueReusableCell(withIdentifier: "OOSelectPersonTableViewCell", for: indexPath) as! (OOSelectPersonTableViewCell & Configurable)
-            personCell.config(withItem: selectedPersons)
-            return personCell
-        } else if indexPath.section == 1 {
-            let cell = tableView.dequeueReusableCell(withIdentifier: ooPersonCellIdentifier, for: indexPath)
-            let uCell = cell as! (OOContactPersonCell & Configurable)
-            uCell.viewModel = viewModel
-            let item = viewModel.nodeForIndexPath(indexPath)
-            uCell.config(withItem: item)
-            return cell
-        }
-        return UITableViewCell()
-            
-    }
-    
-    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
-        let item = viewModel.nodeForIndexPath(indexPath)
-        if isSingleSelected {
-            //单选直接删除换新
-            selectedPersons.removeAll()
-            selectedPersons.append(item!)
-        }else{
-            if !selectedPersons.contains(item!) {
-                selectedPersons.append(item!)
-            }
-        }
-        tableView.beginUpdates()
-        tableView.reloadSections(IndexSet(integer: 0) , with: .automatic)
-        tableView.endUpdates()
-        tableView.deselectRow(at: indexPath, animated: true)
-        //searchController.isActive = false
-        setRightItem()
-    }
-    
-    
-//    func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
-//        let cell = tableView.cellForRow(at: indexPath)
-//        tableView.beginUpdates()
-//        cell?.accessoryView = nil
-//        tableView.endUpdates()
-//        let item = viewModel.nodeForIndexPath(indexPath)
-//        selectedPersons.removeFirst(item!)
-//        setRightItem()
-//    }
-    
-    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
-        if section == 0 {
-            return "所选择的人员"
-        }else if section == 1 {
-            return "人员列表"
-        }
-        return nil
-    }
-    
-    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
-        if section == 0 {
-            return 30.0
-        }else if section == 1 {
-            return 30.0
-        }
-        return 0.0
-    }
-    
-    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
-        if indexPath.section == 0 {
-            return 70.0
-        }else if indexPath.section == 1 {
-            return 60.0
-        }
-        return 60.0
-    }
-    
-    
-}
-
-extension OOPersonsViewController:UISearchResultsUpdating {
-    func updateSearchResults(for searchController: UISearchController) {
-        if  let searchText = searchController.searchBar.text {
-            viewModel.isSearchActive = searchController.isActive
-            viewModel.filterPerson(searchText) { (errorMessage) in
-                if errorMessage == nil {
-                    self.reloadData()
-                }else{
-                    self.showError(title: errorMessage ?? "")
-                }
-            }
-        }
-    }
-}
-
-extension OOPersonsViewController:UISearchBarDelegate {
-    
-    func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
-        viewModel.isSearchActive = !viewModel.isSearchActive
-        self.reloadData()
-    }
-    
-    func searchBarShouldBeginEditing(_ searchBar: UISearchBar) -> Bool {
-        return true
-    }
-    
-    func searchBarShouldEndEditing(_ searchBar: UISearchBar) -> Bool {
-        return true
-    }
-    
-    func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
-        
-    }
-    
-    func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
-        viewModel.isSearchActive = !viewModel.isSearchActive
-        self.reloadData()
-    }
-    
-    
-    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
-        
-    }
-}
-

+ 0 - 42
o2ios/O2Platform/App/Contact-通讯录/Controller/OOPersonsViewController.xib

@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14109" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
-    <device id="retina4_7" orientation="portrait">
-        <adaptation id="fullscreen"/>
-    </device>
-    <dependencies>
-        <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14088"/>
-        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
-        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
-    </dependencies>
-    <objects>
-        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="OOPersonsViewController" customModule="O2Platform" customModuleProvider="target">
-            <connections>
-                <outlet property="tableView" destination="qtd-Mg-ZY9" id="cTr-RH-ma8"/>
-                <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
-            </connections>
-        </placeholder>
-        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
-        <view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
-            <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
-            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
-            <subviews>
-                <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" style="grouped" rowHeight="60" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" translatesAutoresizingMaskIntoConstraints="NO" id="qtd-Mg-ZY9">
-                    <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
-                    <color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
-                    <color key="separatorColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="calibratedRGB"/>
-                    <inset key="separatorInset" minX="15" minY="0.0" maxX="15" maxY="0.0"/>
-                </tableView>
-            </subviews>
-            <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-            <constraints>
-                <constraint firstItem="qtd-Mg-ZY9" firstAttribute="bottom" secondItem="fnl-2z-Ty3" secondAttribute="bottom" id="91g-5f-cUr"/>
-                <constraint firstItem="qtd-Mg-ZY9" firstAttribute="top" secondItem="i5M-Pr-FkT" secondAttribute="top" id="S4p-b4-EAj"/>
-                <constraint firstItem="qtd-Mg-ZY9" firstAttribute="trailing" secondItem="fnl-2z-Ty3" secondAttribute="trailing" id="UBT-CS-M7z"/>
-                <constraint firstItem="qtd-Mg-ZY9" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" id="viL-bX-d1N"/>
-            </constraints>
-            <viewLayoutGuide key="safeArea" id="fnl-2z-Ty3"/>
-            <point key="canvasLocation" x="-119" y="51"/>
-        </view>
-    </objects>
-</document>

+ 2 - 2
o2ios/O2Platform/App/Login-绑定登录/c/OOBindNodeViewController.swift

@@ -99,7 +99,7 @@ class OOBindNodeViewController:OOBaseViewController,UITableViewDataSource,UITabl
     
     private func nextAction() {
         if let node = selectedNode {
-            MBProgressHUD_JChat.showMessage(message: "绑定中...", toView: self.view)
+            self.showLoading(title: "绑定中...")
             O2AuthSDK.shared.bindMobileToServer(unit: node, mobile: mobile, code: value) { (state, msg) in
                 switch state {
                 case .goToChooseBindServer(_):
@@ -132,7 +132,7 @@ class OOBindNodeViewController:OOBaseViewController,UITableViewDataSource,UITabl
                     }
                     break
                 }
-                MBProgressHUD_JChat.hide(forView: self.view, animated: true)
+                self.hideLoading()
             }
         }else{
             //请选择指定的目标服务

+ 2 - 2
o2ios/O2Platform/App/Login-绑定登录/c/OOBindRegisterController.swift

@@ -80,7 +80,7 @@ class OOBindRegisterController: OOBaseViewController {
             self.showError(title: "请输入验证码!")
             return
         }
-        MBProgressHUD_JChat.showMessage(message: "绑定中...", toView: self.view)
+        self.showLoading(title: "绑定中...")
         O2AuthSDK.shared.bindMobileToSever(mobile: mobile, code: value) { (state, msg) in
             switch state {
             case .goToChooseBindServer(let unitList):
@@ -111,7 +111,7 @@ class OOBindRegisterController: OOBaseViewController {
                 }
                 break
             }
-            MBProgressHUD_JChat.hide(forView: self.view, animated: true)
+            self.hideLoading()
         }
         
     }

+ 0 - 55
o2ios/O2Platform/App/Login-绑定登录/vm/OOLoginViewModel.swift

@@ -90,61 +90,6 @@ extension OOLoginViewModel {
     
     
     
-    // MARK:- Login IM
-    
-    func loginIM() -> Promise<Bool> {
-        return Promise { fulfill,reject in
-            if let account = O2AuthSDK.shared.myInfo() {
-                JMSGUser.login(withUsername: account.id!, password: "QazWsxEdc!@#", completionHandler: { (resultObject, errMsg) in
-                    if errMsg == nil {
-                        O2Logger.info("IM登录成功,user = \(String(describing: resultObject))")
-                        fulfill(true)
-                    }else{
-                        O2Logger.error("IM登录失改,error = \(String(describing: errMsg))")
-                        let loginErr = OOAppError.common(type: "im", message: "im login Fail,\(String(describing: errMsg))", statusCode: 40001)
-                        reject(loginErr)
-                    }
-                })
-            }else {
-                O2Logger.error("IM登录失改,error = 当前登录用户为空!!!")
-                let loginErr = OOAppError.common(type: "im", message: "im login Fail,前登录用户为空!!", statusCode: 40001)
-                reject(loginErr)
-            }
-        }
-    }
-    
-    // MARK:- register IM
-    func registerIM() -> Promise<Bool> {
-        return Promise { fulfill,reject in
-            if let account = O2AuthSDK.shared.myInfo() {
-                let username = account.id
-                let nickname = account.name
-                let gener = account.genderType
-                let info = JMSGUserInfo()
-                info.nickname = nickname!
-                if gener == "f" {
-                    info.gender = .female
-                }else if gener == "m" {
-                    info.gender = .male
-                }else{
-                    info.gender = .unknown
-                }
-
-                JMSGUser.register(withUsername: username!, password: "QazWsxEdc!@#", userInfo: info, completionHandler: { (resultObject, regError) in
-                    if let error = regError {
-                        let registerErr = OOAppError.common(type: "im", message: "im register Fail,\(String(describing: error))", statusCode: 40001)
-                        reject(OOLoginError.imRegisterFail(registerErr))
-                    }else{
-                        fulfill(true)
-                    }
-                })
-            }else {
-                let registerErr = OOAppError.common(type: "im", message: "im register Fail,当前登录用户为空", statusCode: 40001)
-                reject(OOLoginError.imRegisterFail(registerErr))
-            }
-            
-        }
-    }
     
    
     

+ 8 - 7
o2ios/O2Platform/App/NewAttance-考勤打卡/c/OOAttanceCheckInController.swift

@@ -128,21 +128,21 @@ class OOAttanceCheckInController: UITableViewController {
             }
         }
         
-        MBProgressHUD_JChat.showMessage(message: "打卡中...", toView: self.view)
+        self.showLoading(title: "打卡中...")
         checkinForm.checkin_type = self.feature?.checkinType ?? ""
         viewModel.postMyCheckin(checkinForm) { (result) in
-            MBProgressHUD_JChat.hide(forView: self.view, animated: true)
+            self.hideLoading()
             switch result {
             case .ok(_):
                 DispatchQueue.main.async {
-                    MBProgressHUD_JChat.show(text:"打卡成功", view: self.view)
+                    self.showSuccess(title: "打卡成功")
                     self.getCurrentCheckinList()
                     self.getMyRecords()
                 }
                 break
             case .fail(let errorMessage):
                 DispatchQueue.main.async {
-                    MBProgressHUD_JChat.show(text:"打卡失败,\n\(errorMessage)", view: self.view)
+                    self.showError(title: "打卡失败,\n\(errorMessage)")
                 }
                 break
             default:
@@ -201,12 +201,13 @@ class OOAttanceCheckInController: UITableViewController {
         let currentDate = Date().toString("yyyy-MM-dd")
         bean.startDate = currentDate
         bean.endDate = currentDate
-        MBProgressHUD_JChat.showMessage(message: "loading...", toView: self.view)
+        
+        self.showLoading()
         viewModel.getMyCheckinList(model, bean) { (myResult) in
-            MBProgressHUD_JChat.hide(forView: self.view, animated: true)
+            self.hideLoading()
             switch myResult {
             case .fail(let s):
-                MBProgressHUD_JChat.show(text: "错误:\n\(s)", view: self.view, 2)
+                self.showError(title: "错误:\n\(s)")
                 DispatchQueue.main.async {
                     self.tableView.reloadData()
                 }

+ 6 - 6
o2ios/O2Platform/App/NewAttance-考勤打卡/c/OOAttanceSettingController.swift

@@ -101,7 +101,7 @@ class OOAttanceSettingController: UIViewController {
     @objc private func createNewWorkPlace(_ notification:Notification){
         DDLogDebug("接收到消息。。。。。。。。。。。。。。。。。。。。。。")
         if self.isAdmin == false {
-            MBProgressHUD_JChat.show(text: "你不是管理员,无操作权限", view: self.view)
+            self.showError(title: "你不是管理员,无操作权限")
             return
         }
         if let obj = notification.object as? (String,String,String) {
@@ -109,15 +109,15 @@ class OOAttanceSettingController: UIViewController {
             settingBean.placeAlias = obj.1
             settingBean.errorRange = obj.2
         }
-        MBProgressHUD_JChat.showMessage(message: "创建打卡地址...", toView: view)
+        self.showLoading(title: "创建打卡地址...")
         viewModel.postCheckinLocation(settingBean) { (resultType) in
-            MBProgressHUD_JChat.hide(forView: self.view, animated: true)
+            self.hideLoading()
             switch resultType {
             case .ok(_):
-                MBProgressHUD_JChat.show(text: "打卡地址设置成功", view: self.view, 1)
+                self.showSuccess(title:  "打卡地址设置成功")
                 break
             case .fail(let errorMessage):
-                MBProgressHUD_JChat.show(text: "打卡地址设置失败\n\(errorMessage)", view: self.view, 1)
+                self.showError(title: "打卡地址设置失败\n\(errorMessage)" )
                 break
             default:
                 break
@@ -132,7 +132,7 @@ class OOAttanceSettingController: UIViewController {
             let destVC = OOAttandanceWorkPlaceController(nibName: "OOAttandanceWorkPlaceController", bundle: nil)
             self.pushVC(destVC)
         }else {
-            MBProgressHUD_JChat.show(text: "你不是管理员,无操作权限", view: self.view)
+            self.showMessage(msg: "你不是管理员,无操作权限")
         }
     }
     

+ 10 - 6
o2ios/O2Platform/App/NewAttance-考勤打卡/c/OOAttandanceWorkPlaceController.swift

@@ -27,21 +27,24 @@ class OOAttandanceWorkPlaceController: UITableViewController {
     }
     
     private func loadWorkPlace() {
-        MBProgressHUD_JChat.showMessage(message: "loading...", toView: view)
+        self.showLoading()
         models.removeAll()
         viewModel.getLocationWorkPlace { (result) in
-            MBProgressHUD_JChat.hide(forView: self.view, animated: true)
+            
             switch result {
             case .ok(let item):
                 let items = item as? [OOAttandanceWorkPlace]
                 DispatchQueue.main.async {
+                    self.hideLoading()
                     items?.forEach({ (place) in
                         self.models.append(place)
                     })
                 }
                 break
             case .fail(let errorMessage):
-                MBProgressHUD_JChat.show(text: "读取位置列表出错\n,\(errorMessage)", view: self.view, 1)
+                DispatchQueue.main.async {
+                    self.showError(title: "读取位置列表出错\n,\(errorMessage)" )
+                }
                 break
             default:
                 break
@@ -90,19 +93,20 @@ class OOAttandanceWorkPlaceController: UITableViewController {
     
     private func _delete(_ indexPath:IndexPath){
         let item = models[indexPath.row]
-        MBProgressHUD_JChat.showMessage(message: "删除中,请稍候...", toView: view)
+        self.showLoading(title: "删除中,请稍候...")
         viewModel.deleteLocationWorkPlace(item) { (resultType) in
-            MBProgressHUD_JChat.hide(forView: self.view, animated: true)
+             self.hideLoading()
             switch resultType {
             case .reload:
                 DispatchQueue.main.async {
+                    
                     self.models.remove(at: indexPath.row)
                     self.tableView.reloadData()
                 }
                 break
             case .fail(let errorMessage):
                 DispatchQueue.main.async {
-                    MBProgressHUD_JChat.show(text: "删除不成功\n\(errorMessage)", view: self.view, 1)
+                    self.showError(title: "删除不成功\n\(errorMessage)" )
                     self.tableView.reloadData()
                 }
             default:

+ 0 - 7
o2ios/O2Platform/App/Setting-设置/c/SPersonViewController.swift

@@ -222,13 +222,6 @@ class SPersonViewController: FormViewController {
         O2AuthSDK.shared.logout { (result, msg) in
             DDLogInfo("O2 登出 \(result), msg:\(msg ?? "")")
         }
-        JMSGUser.logout { (resultObject, errMsg) in
-            if errMsg == nil {
-                print("IM成功退出")
-            }else{
-                print("IM退出失败,error = \(String(describing: errMsg))")
-            }
-        }
         if O2IsConnect2Collect == false {
             //解除绑定 设备号 内网直连版本
             O2JPushManager.shared.O2JPushUnBind()

+ 120 - 126
o2ios/O2Platform/App/VoiceAI-语音处理/Controller/OOVoiceAIController.swift

@@ -2,8 +2,8 @@
 //  OOVoiceAIController.swift
 //  O2Platform
 //
-//  Created by 刘振兴 on 2018/6/12.
-//  Copyright © 2018年 zoneland. All rights reserved.
+//  Created by FancyLou on 2020/8/27.
+//  Copyright © 2020年 zoneland. All rights reserved.
 //
 
 import UIKit
@@ -21,22 +21,15 @@ class OOVoiceAIController: UIViewController {
     
     var closeVC = false
     var animation = false
-    var lastRecognizeTime = -1 // 没有识别出内容的时间  计算持续多久没识别内容出来了
-    var beginRecognizeFirstTime = -1 //是否有开始识别出内容
+//    var lastRecognizeTime = -1 // 没有识别出内容的时间  计算持续多久没识别内容出来了
+//    var beginRecognizeFirstTime = -1 //是否有开始识别出内容
     
     // 语音合成
     var synthersizer:AVSpeechSynthesizer!
     var voice: AVSpeechSynthesisVoice!
     
-    // 语音识别
-    let recognizeBus = 0
-    var recognizer: SFSpeechRecognizer!
-    var recAudioEngine: AVAudioEngine!
-    var recAudioInputNode: AVAudioInputNode!
-    //
-    var recRequest: SFSpeechAudioBufferRecognitionRequest?
-    var recTask: SFSpeechRecognitionTask?
-    var timer: Timer?
+    //百度语音识别
+    var bdmanager: BDSEventManager? = nil
     
     private lazy var viewModel: OOAIViewModel = {
         return OOAIViewModel()
@@ -55,10 +48,7 @@ class OOVoiceAIController: UIViewController {
         }
         viewModel.aiVoiceControllerDelegate = self
         initSpeak()
-        // init recognizer
-        recognizer = SFSpeechRecognizer(locale: Locale(identifier: "zh_CN"))
-        recAudioEngine = AVAudioEngine()
-        recAudioInputNode = recAudioEngine.inputNode
+        configASR()
     }
     
     override func didReceiveMemoryWarning() {
@@ -88,89 +78,39 @@ class OOVoiceAIController: UIViewController {
         self.navigationController?.popViewController(animated: true)
     }
     
-    //MARK: - recoginzer
+    // MARK: - 语音识别
+    ///初始化语音识别
+   private func configASR() {
+       self.bdmanager = BDSEventManager.createEventManager(withName: BDS_ASR_NAME)
+       self.bdmanager?.setDelegate(self)
+       //百度语音识别 appkey 和 secret
+       self.bdmanager?.setParameter([BAIDU_ASR_APP_KEY, BAIDU_ASR_APP_SECRET], forKey: BDS_ASR_API_SECRET_KEYS)
+       self.bdmanager?.setParameter(BAIDU_ASR_APP_ID, forKey: BDS_ASR_OFFLINE_APP_CODE)
+       // 获取VAD模型的路径
+       let path = Bundle.main.path(forResource: "bds_easr_basic_model", ofType: "dat")
+       self.bdmanager?.setParameter(path, forKey: BDS_ASR_MODEL_VAD_DAT_FILE)
+       self.bdmanager?.setParameter(true, forKey: BDS_ASR_ENABLE_MODEL_VAD)
+       //关闭标点
+       self.bdmanager?.setParameter(true, forKey: BDS_ASR_DISABLE_PUNCTUATION)
+   }
+    
     private func startListen() {
         guard !animation else {
             return
         }
-        
-        //清除任务
-        if recTask != nil {
-            recTask?.cancel()
-            recTask = nil
-        }
-        
-        // 清除定时器
-        if self.timer != nil {
-            self.timer?.invalidate()
-            self.timer = nil
-        }
-        
-        // 录音session
-        let audioSession = AVAudioSession.sharedInstance()
-        do {
-            try audioSession.setCategory(AVAudioSession.Category.playAndRecord, mode: .default, options: .defaultToSpeaker)
-            try audioSession.setActive(true, options: .notifyOthersOnDeactivation) // 这句话很重要,一定要,不然识别不到你的声音
-        } catch {
-            DDLogError("audioSession set failed.")
-        }
-        
-        // 开始设置任务
-        recRequest = SFSpeechAudioBufferRecognitionRequest()
-        recRequest!.shouldReportPartialResults = true // 每个片段都返回 还是识别完成后返回
-        recTask = recognizer.recognitionTask(with: recRequest!, delegate: self)
-        
-        // 监听一个标识位并拼接流文件
-        let format = self.recAudioInputNode.outputFormat(forBus: self.recognizeBus)
-        self.recAudioInputNode.installTap(onBus: self.recognizeBus, bufferSize: 1024, format: format) { (pcmBuffer, time) in
-            self.recRequest?.append(pcmBuffer)
-        }
-        
-        // 准备并启动引擎
-        self.recAudioEngine.prepare()
-        do {
-            try self.recAudioEngine.start()
-        }catch  {
-            DDLogError("录音 识别 异常")
-        }
+        self.bdmanager?.sendCommand(BDS_ASR_CMD_START)
         self.showLabel.text = "等待命令中....."
         animation = true
         voiceView.startAnimation()
-        // 开始计时
-        self.beginRecognizeFirstTime = Int(Date().timeIntervalSince1970)
-        // 开启定时器 判断语音识别
-        self.timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(tickTimer), userInfo: nil, repeats: true)
-        self.timer?.fire()
-    }
-    
-    @objc private func tickTimer() {
-         let cTime = Int(Date().timeIntervalSince1970)
-        if self.lastRecognizeTime < 0 {
-            if self.beginRecognizeFirstTime > 0 && (cTime - self.beginRecognizeFirstTime) > 60 {
-                // 超过60秒结束
-                self.stopListen()
-            }
-        }else {
-            if (cTime - self.lastRecognizeTime) > 3 { //超过3秒没说话
-                self.stopListen()
-            }
-        }
     }
     
+     
     private func stopListen() {
         guard animation else {
             return
         }
-        self.timer?.invalidate()
-        self.timer = nil
-        self.recAudioEngine.stop()
-        self.recAudioInputNode.removeTap(onBus: self.recognizeBus)
-        self.recRequest?.endAudio()
-        self.recRequest = nil
-        self.recTask?.finish()
-        self.recTask = nil
+        self.bdmanager?.sendCommand(BDS_ASR_CMD_STOP)
         animation = false
-        self.beginRecognizeFirstTime = -1
         voiceView.stopAnimation()
     }
     
@@ -189,14 +129,7 @@ class OOVoiceAIController: UIViewController {
         DDLogInfo("speak:\(txt)")
         do {
             let audioSession = AVAudioSession.sharedInstance()
-//            try audioSession.overrideOutputAudioPort(.speaker)
             try audioSession.setCategory(.ambient, mode: .default)
-//            let route = audioSession.currentRoute
-//            route.outputs.forEach { (port) in
-//                DDLogInfo("name:\(port.portName)")
-//                DDLogInfo("type:\(port.portType)")
-//                DDLogInfo("channels:\(String(describing: port.channels?.count))")
-//            }
         }catch {
             DDLogError("异常:\(error)")
         }
@@ -217,6 +150,7 @@ extension OOVoiceAIController: OOAIVoiceControllerDelegate {
     func changeSpeakMessage(message: String?) {
         self.showLabel.text = message
     }
+    
     func changeActivityStatus(status: AIActivityStatus?) {
         switch status! {
         case .listen:
@@ -268,39 +202,99 @@ extension OOVoiceAIController : AVSpeechSynthesizerDelegate {
     }
 }
 
-extension OOVoiceAIController: SFSpeechRecognitionTaskDelegate {
-    func speechRecognitionDidDetectSpeech(_ task: SFSpeechRecognitionTask) {
-        DDLogInfo("did detect speech。。。。。。。")
-    }
-    func speechRecognitionTaskWasCancelled(_ task: SFSpeechRecognitionTask) {
-        DDLogInfo("cancel recognizer....")
-    }
-    func speechRecognitionTask(_ task: SFSpeechRecognitionTask, didHypothesizeTranscription transcription: SFTranscription) {
-        DDLogInfo("hypothesize recognize .....")
-        let c = transcription.formattedString
-        DDLogInfo("选:\(c)")
-        let time = Int(Date().timeIntervalSince1970)
-        self.lastRecognizeTime = time
-    }
-    func speechRecognitionTaskFinishedReadingAudio(_ task: SFSpeechRecognitionTask) {
-        DDLogInfo("finish recognize end reading audio   .....")
-    }
-    func speechRecognitionTask(_ task: SFSpeechRecognitionTask, didFinishRecognition recognitionResult: SFSpeechRecognitionResult) {
-        DDLogInfo("finish recognize result...........")
-        let best = recognitionResult.bestTranscription.formattedString
-        DDLogInfo("最佳:\(best)")
-        let removePunctuation = best.trimmingCharacters(in: CharacterSet.punctuationCharacters)
-        DDLogInfo("最佳去掉标点:\(removePunctuation)")
-        if !self.closeVC {
-            self.viewModel.command = removePunctuation
-            self.lastRecognizeTime = -1
-        }
-    }
-    func speechRecognitionTask(_ task: SFSpeechRecognitionTask, didFinishSuccessfully successfully: Bool) {
-        DDLogInfo("finish recognize task ....... \(successfully)")
-        if !successfully && !self.closeVC {
-             self.viewModel.command = nil
+extension OOVoiceAIController: BDSClientASRDelegate {
+       //EVoiceRecognitionClientWorkStatusStartWorkIng 识别工作开始,开始采集及处理数据 0
+        //EVoiceRecognitionClientWorkStatusStart,                  // 检测到用户开始说话1
+    //    EVoiceRecognitionClientWorkStatusEnd,                    // 本地声音采集结束,等待识别结果返回并结束录音2
+    //    EVoiceRecognitionClientWorkStatusNewRecordData,          // 录音数据回调3
+    //    EVoiceRecognitionClientWorkStatusFlushData,              // 连续上屏4
+    //    EVoiceRecognitionClientWorkStatusFinish,                 // 语音识别功能完成,服务器返回正确结果5
+    //    EVoiceRecognitionClientWorkStatusMeterLevel,             // 当前音量回调6
+    //    EVoiceRecognitionClientWorkStatusCancel,                 // 用户取消7
+    //    EVoiceRecognitionClientWorkStatusError,                  // 发生错误8
+    //    /* 离线引擎状态 */
+    //    EVoiceRecognitionClientWorkStatusLoaded,                 // 离线引擎加载完成9
+    //    EVoiceRecognitionClientWorkStatusUnLoaded,               // 离线引擎卸载完成10
+    //    /* CHUNK状态 */
+    //    EVoiceRecognitionClientWorkStatusChunkThirdData,         // CHUNK: 识别结果中的第三方数据11
+    //    EVoiceRecognitionClientWorkStatusChunkNlu,               // CHUNK: 识别结果中的语义结果12
+    //    EVoiceRecognitionClientWorkStatusChunkEnd,               // CHUNK: 识别过程结束13
+    //    /* LOG */
+    //    EVoiceRecognitionClientWorkStatusFeedback,               // Feedback: 识别过程反馈的打点数据14
+    //    /* Only for iOS */
+    //    EVoiceRecognitionClientWorkStatusRecorderEnd,            // 录音机关闭,页面跳转需检测此时间,规避状态条 (iOS) 15
+    //    /* LONG SPEECH END */
+    //    EVoiceRecognitionClientWorkStatusLongSpeechEnd           // 长语音结束状态16
+    func voiceRecognitionClientWorkStatus(_ workStatus: Int32, obj aObj: Any!) {
+        switch workStatus {
+        case 0: //EVoiceRecognitionClientWorkStatusStartWorkIng 识别工作开始,开始采集及处理数据
+            DDLogInfo("开始识别。。。。。")
+            break
+        case 5: //EVoiceRecognitionClientWorkStatusFinish 语音识别功能完成,服务器返回正确结果
+            if let resDic = aObj as? NSDictionary, let arr = resDic["results_recognition"] as? Array<String> {
+                let first = arr[0]
+                DDLogInfo("识别成功 返回结果 \(first)")
+                DispatchQueue.main.async {
+                    if !self.closeVC {
+                        self.stopListen()
+                        self.viewModel.command = first
+                    }
+                }
+            }else {
+                if !self.closeVC {
+                    self.stopListen()
+                     self.viewModel.command = nil
+                }
+            }
+            break
+        case 8://EVoiceRecognitionClientWorkStatusError,                  // 发生错误8
+            let err = aObj as? Error
+            DDLogError("err : \(String(describing: err?.localizedDescription))")
+            DispatchQueue.main.async {
+                if !self.closeVC {
+                    self.stopListen()
+                     self.viewModel.command = nil
+                }
+            }
+        default:
+            break
         }
     }
-    
 }
+//
+//extension OOVoiceAIController: SFSpeechRecognitionTaskDelegate {
+//    func speechRecognitionDidDetectSpeech(_ task: SFSpeechRecognitionTask) {
+//        DDLogInfo("did detect speech。。。。。。。")
+//    }
+//    func speechRecognitionTaskWasCancelled(_ task: SFSpeechRecognitionTask) {
+//        DDLogInfo("cancel recognizer....")
+//    }
+//    func speechRecognitionTask(_ task: SFSpeechRecognitionTask, didHypothesizeTranscription transcription: SFTranscription) {
+//        DDLogInfo("hypothesize recognize .....")
+//        let c = transcription.formattedString
+//        DDLogInfo("选:\(c)")
+//        let time = Int(Date().timeIntervalSince1970)
+//        self.lastRecognizeTime = time
+//    }
+//    func speechRecognitionTaskFinishedReadingAudio(_ task: SFSpeechRecognitionTask) {
+//        DDLogInfo("finish recognize end reading audio   .....")
+//    }
+//    func speechRecognitionTask(_ task: SFSpeechRecognitionTask, didFinishRecognition recognitionResult: SFSpeechRecognitionResult) {
+//        DDLogInfo("finish recognize result...........")
+//        let best = recognitionResult.bestTranscription.formattedString
+//        DDLogInfo("最佳:\(best)")
+//        let removePunctuation = best.trimmingCharacters(in: CharacterSet.punctuationCharacters)
+//        DDLogInfo("最佳去掉标点:\(removePunctuation)")
+//        if !self.closeVC {
+//            self.viewModel.command = removePunctuation
+//            self.lastRecognizeTime = -1
+//        }
+//    }
+//    func speechRecognitionTask(_ task: SFSpeechRecognitionTask, didFinishSuccessfully successfully: Bool) {
+//        DDLogInfo("finish recognize task ....... \(successfully)")
+//        if !successfully && !self.closeVC {
+//             self.viewModel.command = nil
+//        }
+//    }
+//
+//}

+ 9 - 9
o2ios/O2Platform/App/meeting-会议/Controller/OOMeetingInforController.swift

@@ -77,7 +77,7 @@ class OOMeetingInforController: UIViewController {
     }
 
     func loadData() {
-        MBProgressHUD_JChat.showMessage(message: "loading...", toView: view)
+        self.showLoading()
         all(viewModel.getMeetingsByYearAndMonth(Date()), viewModel.getMeetingByTheDay(Date())).then { (result) in
             DispatchQueue.main.async {
                 self.headerView.eventsByDate = result.0 as? [String: [OOMeetingInfo]]
@@ -86,41 +86,41 @@ class OOMeetingInforController: UIViewController {
                 self.tableView.reloadData()
             }
         }.always {
-            MBProgressHUD_JChat.hide(forView: self.view, animated: true)
+            self.hideLoading()
             if self.tableView.mj_header.isRefreshing() {
                 self.tableView.mj_header.endRefreshing()
             }
             //self.tableView.reloadData()
         }.catch { (myerror) in
             let customError = myerror as! OOAppError
-            MBProgressHUD_JChat.show(text: customError.failureReason ?? "", view: self.view)
+            self.showError(title: customError.failureReason ?? "")
         }
     }
 
 
     func loadCurrentMonthCalendar(_ theDate: Date?) {
-        MBProgressHUD_JChat.showMessage(message: "loading...", toView: view)
+        self.showLoading()
         viewModel.getMeetingsByYearAndMonth(theDate ?? Date()).then { (resultDict) in
             self.headerView.eventsByDate = resultDict as? [String: [OOMeetingInfo]]
         }.always {
-            MBProgressHUD_JChat.hide(forView: self.view, animated: true)
+            self.hideLoading()
         }.catch { (myerror) in
             let customError = myerror as! OOAppError
-            MBProgressHUD_JChat.show(text: customError.failureReason ?? "", view: self.view)
+            self.showError(title:  customError.failureReason ?? "")
         }
     }
 
     func loadtheDayMeetingInfo(_ theDate: Date?) {
-        MBProgressHUD_JChat.showMessage(message: "loading...", toView: view)
+        self.showLoading()
         viewModel.getMeetingByTheDay(theDate ?? Date()).then { (infos) in
             self.viewModel.theMeetingsByDay.removeAll()
             self.viewModel.theMeetingsByDay.append(contentsOf: infos)
             self.tableView.reloadData()
         }.always {
-            MBProgressHUD_JChat.hide(forView: self.view, animated: true)
+            self.hideLoading()
         }.catch { (myerror) in
             let customError = myerror as! OOAppError
-            MBProgressHUD_JChat.show(text: customError.failureReason ?? "", view: self.view)
+            self.showError(title:  customError.failureReason ?? "")
         }
     }
 

+ 3 - 3
o2ios/O2Platform/App/meeting-会议/Controller/OOMeetingMeetingRoomManageController.swift

@@ -90,7 +90,7 @@ class OOMeetingMeetingRoomManageController: UIViewController {
     }
     
     private func loadAllBuildByDate(_ startDate:String,_ endDate:String){
-         MBProgressHUD_JChat.showMessage(message: "loading...", toView: view)
+        self.showLoading()
         viewModel.loadAllBuildByDate(startDate, endDate).then { (builds) in
             DispatchQueue.main.async {
                 self.viewModel.builds.removeAll()
@@ -98,13 +98,13 @@ class OOMeetingMeetingRoomManageController: UIViewController {
                 self.tableView.reloadData()
             }
             }.always {
-                MBProgressHUD_JChat.hide(forView: self.view, animated: true)
+                self.hideLoading()
                 if self.tableView.mj_header.isRefreshing() {
                     self.tableView.mj_header.endRefreshing()
                 }
             }.catch { (myerror) in
                 let customError = myerror as! OOAppError
-                MBProgressHUD_JChat.show(text: customError.failureReason ?? "", view: self.view)
+                self.showError(title: customError.failureReason ?? "")
         }
     }
     

+ 1 - 104
o2ios/O2Platform/AppDelegate.swift

@@ -101,9 +101,6 @@ class AppDelegate: FlutterAppDelegate, JPUSHRegisterDelegate, UNUserNotification
         //JPush
         _setupJPUSH()
         JPUSHService.setup(withOption: launchOptions, appKey: JPUSH_APP_KEY, channel: JPUSH_channel, apsForProduction: isProduction)
-        //JMessage
-        JMessage.setupJMessage(launchOptions, appKey: JPUSH_APP_KEY, channel: JPUSH_channel, apsForProduction: isProduction, category: nil, messageRoaming: true)
-        _setupJMessage()
         
         _mapManager = BMKMapManager()
         BMKMapManager.setCoordinateTypeUsedInBaiduMapSDK(.COORDTYPE_BD09LL)
@@ -140,16 +137,7 @@ class AppDelegate: FlutterAppDelegate, JPUSHRegisterDelegate, UNUserNotification
         JPUSHService.register(forRemoteNotificationConfig: entity, delegate: self)
     }
     
-    // MARK: - private func
-    private func _setupJMessage() {
-//        JMessage.setDebugMode()
-        JMessage.add(self, with: nil)
-        JMessage.register(forRemoteNotificationTypes:
-            UNAuthorizationOptions.badge.rawValue |
-                            UNAuthorizationOptions.sound.rawValue |
-                            UNAuthorizationOptions.alert.rawValue,
-                        categories: nil)
-    }
+ 
     
     //注册 APNs 获得device token
     override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
@@ -157,7 +145,6 @@ class AppDelegate: FlutterAppDelegate, JPUSHRegisterDelegate, UNUserNotification
         DDLogDebug("get the deviceToken  \(deviceToken)")
         NotificationCenter.default.post(name: Notification.Name(rawValue: "DidRegisterRemoteNotification"), object: deviceToken)
         JPUSHService.registerDeviceToken(deviceToken)
-        JMessage.registerDeviceToken(deviceToken)
     }
     
    
@@ -275,93 +262,3 @@ class AppDelegate: FlutterAppDelegate, JPUSHRegisterDelegate, UNUserNotification
     
     
 }
-
-//MARK: - JMessage Delegate
-extension AppDelegate: JMessageDelegate {
-    func onDBMigrateStart() {
-
-    }
-    
-    func onDBMigrateFinishedWithError(_ error: Error!) {
-       // self.showSuccess(title: "数据库升级完成")
-    }
-    
-    func onReceive(_ event: JMSGUserLoginStatusChangeEvent!) {
-        switch event.eventType.rawValue {
-//        case JMSGLoginStatusChangeEventType.eventNotificationLoginKicked.rawValue:
-//            DDLogInfo("被踢 重新登录")
-//            _reLogin()
-//            break
-        case JMSGLoginStatusChangeEventType.eventNotificationLoginKicked.rawValue,
-             JMSGLoginStatusChangeEventType.eventNotificationServerAlterPassword.rawValue,
-             JMSGLoginStatusChangeEventType.eventNotificationUserLoginStatusUnexpected.rawValue:
-            DDLogInfo("被踢 重新登录")
-            _reLogin()
-        default:
-            break
-        }
-    }
-    func onReceive(_ event: JMSGFriendNotificationEvent!) {
-        switch event.eventType.rawValue {
-        case JMSGFriendEventType.eventNotificationReceiveFriendInvitation.rawValue,
-             JMSGFriendEventType.eventNotificationAcceptedFriendInvitation.rawValue,
-             JMSGFriendEventType.eventNotificationDeclinedFriendInvitation.rawValue:
-            cacheInvitation(event: event)
-        case JMSGFriendEventType.eventNotificationDeletedFriend.rawValue,
-             JMSGFriendEventType.eventNotificationReceiveServerFriendUpdate.rawValue:
-            NotificationCenter.default.post(name: Notification.Name(rawValue: kUpdateFriendList), object: nil)
-        default:
-            break
-        }
-    }
-    
-    private func cacheInvitation(event: JMSGNotificationEvent) {
-        let friendEvent =  event as! JMSGFriendNotificationEvent
-        let user = friendEvent.getFromUser()
-        let reason = friendEvent.getReason()
-        let info = JCVerificationInfo.create(username: user!.username, nickname: user?.nickname, appkey: user!.appKey!, resaon: reason, state: JCVerificationType.wait.rawValue)
-        switch event.eventType.rawValue {
-        case JMSGFriendEventType.eventNotificationReceiveFriendInvitation.rawValue:
-            info.state = JCVerificationType.receive.rawValue
-            JCVerificationInfoDB.shareInstance.insertData(info)
-        case JMSGFriendEventType.eventNotificationAcceptedFriendInvitation.rawValue:
-            info.state = JCVerificationType.accept.rawValue
-            JCVerificationInfoDB.shareInstance.updateData(info)
-            NotificationCenter.default.post(name: Notification.Name(rawValue: kUpdateFriendList), object: nil)
-        case JMSGFriendEventType.eventNotificationDeclinedFriendInvitation.rawValue:
-            info.state = JCVerificationType.reject.rawValue
-            JCVerificationInfoDB.shareInstance.updateData(info)
-        default:
-            break
-        }
-        if UserDefaults.standard.object(forKey: kUnreadInvitationCount) != nil {
-            let count = UserDefaults.standard.object(forKey: kUnreadInvitationCount) as! Int
-            UserDefaults.standard.set(count + 1, forKey: kUnreadInvitationCount)
-        } else {
-            UserDefaults.standard.set(1, forKey: kUnreadInvitationCount)
-        }
-        NotificationCenter.default.post(name: Notification.Name(rawValue: kUpdateVerification), object: nil)
-    }
-    
-    func _logout() {
-        JMSGUser.logout(nil)
-        JCVerificationInfoDB.shareInstance.queue = nil
-        UserDefaults.standard.removeObject(forKey: kCurrentUserName)
- 
-    }
-    
-    func _reLogin() {
-        if let account = O2AuthSDK.shared.myInfo() {
-            JMSGUser.login(withUsername: account.id!, password: "QazWsxEdc!@#", completionHandler: { (resultObject, errMsg) in
-                if errMsg == nil {
-                    DDLogInfo("IM登录成功,user = \(String(describing: resultObject))")
-                }else{
-                    DDLogError("IM登录失改,error = \(String(describing: errMsg))")
-                }
-            })
-        }else {
-            DDLogError("_reLogin 。。。。。 IM登录失败,error = 当前登录用户为空!!!")
-        }
-    }
-}
-

+ 12 - 0
o2ios/O2Platform/Extension/String+Extenstion.swift

@@ -32,6 +32,13 @@ extension String {
         }
     }
     
+    public func trim(trimNewline: Bool = false) ->String {
+        if trimNewline {
+            return self.trimmingCharacters(in: .whitespacesAndNewlines)
+        }
+        return self.trimmingCharacters(in: .whitespaces)
+    }
+    
     /// 字符串时间转 Date
     ///
     /// - Parameter formatter: 字符串时间的格式 yyyy-MM-dd/YYYY-MM-dd/HH:mm:ss/yyyy-MM-dd HH:mm:ss
@@ -44,6 +51,11 @@ extension String {
         return date!
     }
     
+    
+    var length: Int {
+        return self.count
+    }
+    
     func subString(from: Int, to: Int? = nil) -> String {
         if from >= self.length {
             return self

+ 24 - 0
o2ios/O2Platform/Extension/UIColor+Extension.swift

@@ -16,6 +16,30 @@ extension UIColor {
         self.init(red: r / 255.0, green: g / 255.0, blue: b / 255.0, alpha: a)
     }
     
+    
+    convenience init(red: Int, green: Int, blue: Int) {
+        assert(red >= 0 && red <= 255, "Invalid red component")
+        assert(green >= 0 && green <= 255, "Invalid green component")
+        assert(blue >= 0 && blue <= 255, "Invalid blue component")
+        
+        self.init(red: CGFloat(red) / 255.0, green: CGFloat(green) / 255.0, blue: CGFloat(blue) / 255.0, alpha: 1.0)
+    }
+    
+   
+    
+    static var random: UIColor {
+            let maxValue: UInt32 = 24
+            return UIColor(red: CGFloat(arc4random() % maxValue) / CGFloat(maxValue),
+                           green: CGFloat(arc4random() % maxValue) / CGFloat(maxValue) ,
+                           blue: CGFloat(arc4random() % maxValue) / CGFloat(maxValue) ,
+                           alpha: 1)
+        }
+        
+   
+        convenience init(netHex:Int) {
+            self.init(red:(netHex >> 16) & 0xff, green:(netHex >> 8) & 0xff, blue:netHex & 0xff)
+        }
+    
     convenience init(hex string: String) {
         var hex = string.hasPrefix("#")
             ? String(string.dropFirst())

+ 102 - 0
o2ios/O2Platform/Extension/UIImage+Extension.swift

@@ -46,6 +46,108 @@ extension UIImage {
             return defaultImage
         }
     }
+    
+    
+    func fixOrientation() -> UIImage {
+        var image = self
+        if self.imageOrientation == .up {
+            return image
+        }
+        var transform = CGAffineTransform.identity
+        switch self.imageOrientation {
+        case .down, .downMirrored:
+            transform = transform.translatedBy(x: image.size.width, y: image.size.height)
+            transform = transform.rotated(by: .pi / 2)
+        case .left, .leftMirrored:
+            transform = transform.translatedBy(x: image.size.width, y: 0)
+            transform = transform.rotated(by: .pi / 2)
+        case .right, .rightMirrored :
+            transform = transform.translatedBy(x: 0, y: image.size.height)
+            transform = transform.rotated(by: -.pi / 2)
+        default:
+            break
+        }
+        
+        switch self.imageOrientation {
+        case .upMirrored, .downMirrored:
+            transform = transform.translatedBy(x: image.size.width,y: 0)
+            transform = transform.scaledBy(x: -1, y: 1)
+        case .rightMirrored, .leftMirrored:
+            transform = transform.translatedBy(x: image.size.height,y: 0)
+            transform = transform.scaledBy(x: -1, y: 1)
+        default:
+            break
+        }
+        
+        let ctx = CGContext(data: nil , width: Int(image.size.width), height: Int(image.size.height), bitsPerComponent: image.cgImage!.bitsPerComponent, bytesPerRow: 0, space: image.cgImage!.colorSpace!, bitmapInfo: image.cgImage!.bitmapInfo.rawValue)
+        
+        ctx!.concatenate(transform)
+        
+        switch image.imageOrientation {
+        case .left, .leftMirrored, .right, .rightMirrored:
+            ctx?.draw(image.cgImage!, in: CGRect(x: 0, y: 0, width: image.size.height, height: image.size.width))
+        default:
+            ctx?.draw(image.cgImage!, in: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height))
+        }
+        
+        let cgImage = ctx!.makeImage()
+        image = UIImage(cgImage: cgImage!)
+        return image
+    }
+
+    static func createImage(color: UIColor, size: CGSize) -> UIImage? {
+
+        var rect = CGRect(origin: CGPoint.zero, size: size)
+        UIGraphicsBeginImageContext(size)
+        defer {
+            UIGraphicsEndImageContext()
+        }
+        let context = UIGraphicsGetCurrentContext()
+        context?.setFillColor(color.cgColor)
+        context?.fill(rect)
+        let image = UIGraphicsGetImageFromCurrentImageContext()
+        return image
+    }
+
+    
+    
+    func resizeImage(_ newSize: CGSize) -> UIImage {
+        UIGraphicsBeginImageContextWithOptions(newSize, false, UIScreen.main.scale)
+        self.draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
+        let newImage = UIGraphicsGetImageFromCurrentImageContext()
+        UIGraphicsEndImageContext()
+        return newImage!
+    }
+    
+    // iOS 9 以后,ImageView.image 设置圆角并不会触发离屏渲染了
+    // 可以异步绘制,再主线刷新
+    func imageCornerRadius(_ radius: CGFloat) -> UIImage? {
+        let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
+        UIGraphicsBeginImageContextWithOptions(self.size, false, UIScreen.main.scale);
+        guard let ctx = UIGraphicsGetCurrentContext() else {
+            return nil
+        }
+        ctx.addPath(UIBezierPath(roundedRect: rect, cornerRadius: radius).cgPath)
+        ctx.clip()
+        draw(in: rect)
+        let image = UIGraphicsGetImageFromCurrentImageContext()
+        UIGraphicsEndImageContext()
+        return image
+    }
+    
+    func scaledImageFrom3x() -> UIImage {
+        let theRate: CGFloat = 1.0 / 3.0
+        let oldSize = self.size
+        let scaleWidth = CGFloat(oldSize.width) * theRate
+        let scaleHeight = CGFloat(oldSize.height) * theRate
+        var scaleRect = CGRect.zero
+        scaleRect.size = CGSize(width: scaleWidth, height: scaleHeight)
+        UIGraphicsBeginImageContextWithOptions(scaleRect.size, false, UIScreen.main.scale)
+        draw(in: scaleRect)
+        let newImage = UIGraphicsGetImageFromCurrentImageContext()!
+        UIGraphicsEndImageContext()
+        return newImage
+    }
 }
  
 

+ 0 - 52
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/Model/JCCEmoticon.swift

@@ -1,52 +0,0 @@
-//
-//  JCCEmotiocon.swift
-//  JChat
-//
-//  Created by deng on 2017/3/9.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-open class JCCEmoticon: JCEmoticon {
-
-    public required init?(object: NSDictionary) {
-        guard let id = object["id"] as? String, let title = object["title"] as? String, let type = object["type"] as? Int else {
-            return nil
-        }
-        
-        self.id = id
-        self.title = title
-        
-        super.init()
-        
-        self.image = object["image"] as? String
-        self.preview = object["preview"] as? String
-        
-        if type == 1 {
-            self.contents = object["contents"]
-        }
-    }
-    
-    public static func emoticons(with objects: NSArray, at directory: String) -> [JCCEmoticon] {
-        return objects.flatMap {
-            guard let dic = $0 as? NSDictionary else {
-                return nil
-            }
-            guard let e = self.init(object: dic) else {
-                return nil
-            }
-            if let name = e.preview {
-                e.contents = UIImage(contentsOfFile: "\(directory)/\(name)")
-            }
-            return e
-        }
-    }
-    
-    var id: String
-    var title: String
-    
-    var image: String?
-    var preview: String?
-    
-}

+ 0 - 49
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/Model/JCCEmoticonGroup.swift

@@ -1,49 +0,0 @@
-//
-//  JCCEmoticonGroup.swift
-//  JChat
-//
-//  Created by deng on 2017/3/9.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-class JCCEmoticonGroup: JCEmoticonGroup {
-    init?(contentsOfFile: String) {
-        guard let dic = NSDictionary(contentsOfFile: contentsOfFile), let arr = dic["emoticons"] as? NSArray else {
-            return nil
-        }
-        let directory = URL(fileURLWithPath: contentsOfFile).deletingLastPathComponent().path
-        
-        super.init()
-        
-        type = JCEmoticonType(rawValue: dic["type"] as? Int ?? 0) ?? .small
-        rows = dic["rows"] as? Int ?? 3
-        columns = dic["columns"] as? Int ?? 7
-        rowsInLandscape = dic["rowsInLandscape"] as? Int ?? 2
-        columnsInLandscape = dic["columnsInLandscape"] as? Int ?? 13
-        
-        if let img = dic["image"] as? String {
-            thumbnail = UIImage(contentsOfFile: "\(directory)/\(img)")
-        }
-        
-        if type.isSmall {
-            emoticons = JCCEmoticon.emoticons(with: arr, at: directory)
-        } else {
-            emoticons = JCCEmoticonLarge.emoticons(with: arr, at: directory)
-        }
-    }
-    
-    convenience init?(identifier : String) {
-        let bundle = Bundle.main
-        guard let path = bundle.path(forResource: "emoticons.bundle/\(identifier)/Info", ofType: "plist") else {
-            return nil
-        }
-        self.init(contentsOfFile: path)
-    }
-    
-    open var rows: Int = 3
-    open var columns: Int = 7
-    open var rowsInLandscape: Int = 3
-    open var columnsInLandscape: Int = 13
-}

+ 0 - 47
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/Model/JCCEmoticonLarge.swift

@@ -1,47 +0,0 @@
-//
-//  JCCEmoticonLarge.swift
-//  JChat
-//
-//  Created by deng on 2017/3/9.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-open class JCCEmoticonLarge: JCCEmoticon {
-    
-    open override func draw(in rect: CGRect, in ctx: CGContext) {
-        guard let image = contents as? UIImage else {
-            return
-        }
-        
-        var nframe1 = rect.inset(by: UIEdgeInsets(top: 0, left: 0, bottom: 20, right: 0))
-        var nframe2 = rect.inset(by: UIEdgeInsets(top: nframe1.height, left: 0, bottom: 0, right: 0))
-        
-        // 图标
-        let scale = min(min(nframe1.width / image.size.width, nframe1.height / image.size.height), 1)
-        let imageSize = CGSize(width: image.size.width * scale, height: image.size.height * scale)
-        
-        nframe1.origin.x = nframe1.minX + (nframe1.width - imageSize.width) / 2
-        nframe1.origin.y = nframe1.minY + (nframe1.height - imageSize.height) / 2
-        nframe1.size.width = imageSize.width
-        nframe1.size.height = imageSize.height
-        
-        image.draw(in: nframe1)
-        
-        // 标题
-        let cfg = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 12),
-                   NSAttributedString.Key.foregroundColor: UIColor.gray]
-        let name = title as NSString
-        
-        let titleSize = name.size(withAttributes: cfg)
-        
-        nframe2.origin.x = nframe2.minX + (nframe2.width - titleSize.width) / 2
-        nframe2.origin.y = nframe2.minY + (nframe2.height - titleSize.height) / 2
-        nframe2.size.width = titleSize.width
-        nframe2.size.height = titleSize.height
-        
-        name.draw(in: nframe2, withAttributes: cfg)
-    }
-    
-}

+ 0 - 62
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/Model/JCDraft.swift

@@ -1,62 +0,0 @@
-//
-//  JCDraft.swift
-//  JChat
-//
-//  Created by deng on 2017/6/2.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-class JCDraft: NSObject {
-    
-    static var draftCache: Dictionary<String, String> = Dictionary()
-    
-    static func update(text: String?, conversation: JMSGConversation) {
-        let id = JCDraft.getDraftId(conversation)
-        if text == nil || (text?.isEmpty)! {
-            UserDefaults.standard.removeObject(forKey: id)
-            draftCache.removeValue(forKey: id)
-            return
-        }
-        UserDefaults.standard.set(text!, forKey: id)
-        draftCache[id] = text!
-    }
-    
-    static func getDraft(_ conversation: JMSGConversation) -> String? {
-        let id = JCDraft.getDraftId(conversation)
-        if let cache = draftCache[id] {
-            return cache
-        }
-        let draft = UserDefaults.standard.object(forKey: id) as? String
-        if draft != nil {
-            draftCache[id] = draft
-        } else {
-            draftCache[id] = ""
-        }
-        return draft
-    }
-    
-    static func getDraftId(_ conversation: JMSGConversation) -> String {
-        var id = ""
-        let me = JMSGUser.myInfo()
-        if me.username.isEmpty {
-            return ""
-        }
-        if conversation.ex.isGroup {
-            guard let group = conversation.target as? JMSGGroup else {
-                return ""
-            }
-            id = "\(me.username)\(me.appKey!)\(group.gid)"
-        } else {
-            guard let user = conversation.target as? JMSGUser else {
-                return ""
-            }
-            guard let appkey = user.appKey else {
-                return ""
-            }
-            id = "\(me.username)\(me.appKey!)\(user.username)\(appkey)"
-        }
-        return id
-    }
-}

+ 0 - 170
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/Model/JCMessage.swift

@@ -1,170 +0,0 @@
-//
-//  JCMessage.swift
-//  JChat
-//
-//  Created by deng on 10/04/2017.
-//  Copyright © 2017 HXHG. All rights reserved.
-//
-
-import UIKit
-import JMessage
-
-open class JCMessage: NSObject, JCMessageType {
-
-    init(content: JCMessageContentType) {
-        self.content = content
-        self.options = JCMessageOptions(with: content)
-        super.init()
-    }
-    
-    public let identifier: UUID = .init()
-    open var msgId = ""
-    open var name: String = "UserName"
-    open var date: Date = .init()
-    open var sender: JMSGUser?
-    open var senderAvator: UIImage?
-    open var receiver: JMSGUser?
-    open var content: JCMessageContentType
-    public let options: JCMessageOptions
-    open var updateSizeIfNeeded: Bool = false
-    open var unreadCount: Int = 0
-    open var targetType: MessageTargetType = .single
-}
-
-extension JMSGMessage {
-    typealias Callback = (JMSGMessage, Data) -> Void
-
-    func parseMessage(_ delegate: JCMessageDelegate, _ updateMediaMessage: Callback? = nil) -> JCMessage {
-
-        var msg: JCMessage!
-        let currentUser = JMSGUser.myInfo()
-        let isCurrent = fromUser.isEqual(to: currentUser)
-        let state = self.ex.state
-        let isGroup = targetType == .group
-
-        switch(contentType) {
-        case .text:
-            if ex.isBusinessCard {
-                let businessCardContent = JCBusinessCardContent()
-                businessCardContent.delegate = delegate
-                businessCardContent.appKey = ex.businessCardAppKey
-                businessCardContent.userName = ex.businessCardName
-                msg = JCMessage(content: businessCardContent)
-            } else {
-                let content = self.content as! JMSGTextContent
-                msg = JCMessage(content: JCMessageTextContent(text: content.text))
-            }
-        case .image:
-            let content = self.content as! JMSGImageContent
-            let imageContent = JCMessageImageContent()
-            imageContent.imageSize = content.imageSize
-            if ex.isLargeEmoticon {
-                imageContent.imageSize = CGSize(width: content.imageSize.width / 3, height: content.imageSize.height / 3)
-            }
-            if state == .sending {
-                content.uploadHandler = {  (percent:Float, msgId:(String?)) -> Void in
-                    imageContent.upload?(percent)
-                }
-            }
-            imageContent.delegate = delegate
-            msg = JCMessage(content: imageContent)
-
-            if let path = content.thumbImageLocalPath {
-                let image = UIImage(contentsOfFile: path)
-                imageContent.image = image
-                msg.content = imageContent
-            } else {
-                content.thumbImageData({ (data, id, error) in
-                    if let data = data {
-                        if let updateMediaMessage = updateMediaMessage {
-                            updateMediaMessage(self, data)
-                        }
-                    }
-                })
-            }
-        case .eventNotification:
-            let content = self.content as! JMSGEventContent
-            let noticeContent = JCMessageNoticeContent(text: content.showEventNotification())
-            msg = JCMessage(content: noticeContent)
-            msg.options.showsTips = false
-        case .voice:
-            let content = self.content as! JMSGVoiceContent
-            let voiceContent = JCMessageVoiceContent()
-            voiceContent.duration = TimeInterval(content.duration.intValue)
-            voiceContent.delegate = delegate
-            msg = JCMessage(content: voiceContent)
-            content.voiceData({ (data, id, error) in
-                if let data = data {
-                    voiceContent.data = data
-                }
-            })
-        case .file:
-            let content = self.content as! JMSGFileContent
-            if ex.isShortVideo {
-                let videoContent = JCMessageVideoContent()
-                videoContent.delegate = delegate
-                msg = JCMessage(content: videoContent)
-                if let path = content.originMediaLocalPath {
-                    let url = URL(fileURLWithPath: path)
-                    videoContent.data = try! Data(contentsOf: url)
-                } else {
-                    content.fileData({ (data, id, error) in
-                        if let data = data {
-                            if let updateMediaMessage = updateMediaMessage {
-                                updateMediaMessage(self, data)
-                            }
-                        }
-                    })
-                }
-                videoContent.fileContent = content
-            } else {
-                let fileContent = JCMessageFileContent()
-                fileContent.delegate = delegate
-                fileContent.fileName = content.fileName
-                fileContent.fileType = ex.fileType
-                fileContent.fileSize = ex.fileSize
-                if let path = content.originMediaLocalPath {
-                    let url = URL(fileURLWithPath: path)
-                    fileContent.data = try! Data(contentsOf: url)
-                }
-                msg = JCMessage(content: fileContent)
-            }
-        case .location:
-            let content = self.content as! JMSGLocationContent
-            let locationContent = JCMessageLocationContent()
-            locationContent.address = content.address
-            locationContent.lat = content.latitude.doubleValue
-            locationContent.lon = content.longitude.doubleValue
-            locationContent.delegate = delegate
-            msg = JCMessage(content: locationContent)
-        case .prompt:
-            let content = self.content as! JMSGPromptContent
-            let noticeContent = JCMessageNoticeContent(text: content.promptText)
-            msg = JCMessage(content: noticeContent)
-            msg.options.showsTips = false
-        default:
-            msg = JCMessage(content: JCMessageNoticeContent.unsupport)
-        }
-        if msg.options.alignment != .center {
-            msg.options.alignment = isCurrent ? .right : .left
-            if isGroup {
-                msg.options.showsCard = !isCurrent
-            }
-        }
-        if isGroup {
-            msg.targetType = .group
-        } else {
-            msg.targetType = .single
-        }
-        msg.msgId = self.msgId
-        msg.options.state = state
-        if isCurrent {
-            msg.senderAvator = UIImage.getMyAvator()
-        }
-        msg.sender = fromUser
-        msg.name = fromUser.displayName()
-        msg.unreadCount = getUnreadCount()
-        return msg
-    }
-}
-

+ 0 - 25
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/Model/JCRemind.swift

@@ -1,25 +0,0 @@
-//
-//  JCRemind.swift
-//  JChat
-//
-//  Created by deng on 2017/7/19.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-class JCRemind: NSObject {
-    
-    var user: JMSGUser?
-    var startIndex: Int
-    var endIndex: Int
-    var length: Int
-    var isAtAll: Bool
-    
-    init(_ user: JMSGUser?, _ startIndex: Int, _ endIndex: Int, _ length: Int, _ isAtAll: Bool) {
-        self.user = user
-        self.startIndex = startIndex
-        self.endIndex = endIndex
-        self.length = length
-        self.isAtAll = isAtAll
-    }
-}

+ 0 - 26
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/Protocols/JCMessageContentViewType.swift

@@ -1,26 +0,0 @@
-//
-//  JCMessageContentViewType.swift
-//  JChat
-//
-//  Created by deng on 10/04/2017.
-//  Copyright © 2017 HXHG. All rights reserved.
-//
-
-import UIKit
-
-@objc public protocol JCMessageContentType: class  {
-    
-    weak var delegate: JCMessageDelegate? { get }
-    var layoutMargins: UIEdgeInsets { get }
-    
-    func sizeThatFits(_ size: CGSize) -> CGSize
-    
-    static var viewType: JCMessageContentViewType.Type { get }
-}
-
-@objc public protocol JCMessageContentViewType: class {
-    
-    init()
-    func apply(_ message: JCMessageType)
-}
-

+ 0 - 81
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/Protocols/JCMessageOptions.swift

@@ -1,81 +0,0 @@
-//
-//  JCMessageOptions.swift
-//  JChat
-//
-//  Created by deng on 2017/3/8.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-import JMessage
-
-/// 消息类型
-@objc public enum JCMessageStyle: Int {
-    case notice
-    case bubble
-}
-
-/// 消息对齐方式
-@objc public enum JCMessageAlignment: Int {
-    case left
-    case right
-    case center
-}
-
-@objc public enum JCMessageState: Int {
-    case sending
-    case sendError
-    case sendSucceed
-    case downloadFailed
-}
-
-/// 消息选项
-@objc open class JCMessageOptions: NSObject {
-    
-    public override init() {
-        super.init()
-    }
-    
-    public convenience init(with content: JCMessageContentType) {
-        self.init()
-        
-        switch content {
-        case is JCMessageNoticeContent:
-            self.style = .notice
-            self.alignment = .center
-            self.showsCard = false
-            self.showsAvatar = false
-            self.showsBubble = true
-            self.isUserInteractionEnabled = false
-            
-        case is JCMessageTimeLineContent:
-            self.style = .notice
-            self.alignment = .center
-            self.showsCard = false
-            self.showsAvatar = false
-            self.showsBubble = false
-            self.isUserInteractionEnabled = false
-            
-//        case is JCMessageImageContent:
-//            self.showsTips = false
-            
-        default:
-            break
-        }
-    }
-    
-    open var style: JCMessageStyle = .bubble
-    open var alignment: JCMessageAlignment = .left
-    
-    open var isUserInteractionEnabled: Bool = true
-    
-    open var showsCard: Bool = false
-    open var showsAvatar: Bool =  true
-    open var showsBubble: Bool = true
-    open var showsTips: Bool = true
-    open var state: JCMessageState = .sendSucceed
-    
-    internal func fix(with content: JCMessageContentType)  {
-    }
-}
-

+ 0 - 45
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/Protocols/JCMessageType.swift

@@ -1,45 +0,0 @@
-//
-//  JCMessageType.swift
-//  JChat
-//
-//  Created by deng on 10/04/2017.
-//  Copyright © 2017 HXHG. All rights reserved.
-//
-
-import Foundation
-import JMessage
-
-@objc public enum MessageTargetType: Int {
-    case single = 0
-    case group
-}
-
-@objc public protocol JCMessageType: class {
-    
-    var name: String { get }
-    var identifier: UUID { get }
-    var msgId: String { get }
-    var date: Date { get }
-    var sender: JMSGUser? { get }
-    var senderAvator: UIImage? { get }
-    var receiver: JMSGUser? { get }
-    var content: JCMessageContentType { get }
-    var options: JCMessageOptions { get }
-    var updateSizeIfNeeded: Bool { get }
-    var unreadCount: Int { get }
-    var targetType: MessageTargetType { get }
-}
-
-@objc public protocol JCMessageDelegate: NSObjectProtocol {
-    @objc optional func message(message: JCMessageType, videoData data: Data?)
-    @objc optional func message(message: JCMessageType, voiceData data: Data?, duration: Double)
-    @objc optional func message(message: JCMessageType, fileData data: Data?, fileName: String?, fileType: String?)
-    @objc optional func message(message: JCMessageType, location address: String?, lat: Double, lon: Double)
-    @objc optional func message(message: JCMessageType, image: UIImage?)
-    // user 对象是为了提高效率,如果 user 已经加载出来了,就直接使用,不需要重新去获取一次
-    @objc optional func message(message: JCMessageType, user: JMSGUser?, businessCardName: String, businessCardAppKey: String)
-    @objc optional func clickTips(message: JCMessageType)
-    @objc optional func tapAvatarView(message: JCMessageType)
-    @objc optional func longTapAvatarView(message: JCMessageType)
-    @objc optional func tapUnreadTips(message: JCMessageType)
-}

+ 0 - 15
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/Protocols/JCUserType.swift

@@ -1,15 +0,0 @@
-//
-//  JCUserType.swift
-//  JChat
-//
-//  Created by deng on 10/04/2017.
-//  Copyright © 2017 HXHG. All rights reserved.
-//
-
-import UIKit
-
-@objc public protocol JCUserType: class {
-    var identifier: String { get }
-    var name: String? { get }
-    var portrait: UIImage? { get }
-}

+ 0 - 132
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/FileCell.swift

@@ -1,132 +0,0 @@
-//
-//  FileCell.swift
-//  JChat
-//
-//  Created by 邓永豪 on 2017/8/28.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-class File {
-    var fileIcon: UIImage
-    var fileName: String
-    var fileSize: String
-    var summary: String
-    
-    init(_ fileIcon: UIImage, _ fileName: String, _ fileSize: String, _ summary: String) {
-        self.fileName = fileName
-        self.fileIcon = fileIcon
-        self.fileSize = fileSize
-        self.summary = summary
-    }
-}
-
-class FileCell: JCTableViewCell {
-    
-    var isEditMode: Bool {
-        get {
-            return !selectView.isHidden
-        }
-        set {
-            selectView.isHidden = !newValue
-            contentView.removeConstraint(selectImageWidthConstraint)
-            if newValue {
-                selectImageWidthConstraint = _JCLayoutConstraintMake(selectView, .width, .equal, nil, .notAnAttribute, 21)
-            } else {
-                selectImageWidthConstraint = _JCLayoutConstraintMake(selectView, .width, .equal, nil, .notAnAttribute, 0)
-            }
-            contentView.addConstraint(selectImageWidthConstraint)
-        }
-    }
-    
-    var isSelectImage: Bool {
-        get {
-            return isSelect
-        }
-        set {
-            if newValue {
-                selectView.image = UIImage.loadImage("com_icon_file_select")
-            } else {
-                selectView.image = UIImage.loadImage("com_icon_file_unselect")
-            }
-            isSelect = newValue
-        }
-    }
-
-    required init?(coder aDecoder: NSCoder) {
-        super.init(coder: aDecoder)
-        _init()
-    }
-    
-    override func awakeFromNib() {
-        super.awakeFromNib()
-        _init()
-    }
-    
-    func bindData(_ file: File) {
-        fileIcon.image = file.fileIcon
-        fileName.text = file.fileName
-        fileSize.text = file.fileSize
-        summary.text = file.summary
-    }
-    
-    private var selectImageWidthConstraint: NSLayoutConstraint!
-    private lazy var selectView: UIImageView = UIImageView()
-    private var isSelect = false
-    private lazy var fileIcon: UIImageView = UIImageView()
-    private lazy var fileName: UILabel = {
-        let fileName = UILabel()
-        fileName.textColor = UIColor(netHex: 0x2C2C2C)
-        fileName.font = UIFont.systemFont(ofSize: 15)
-        return fileName
-    }()
-    private lazy var fileSize: UILabel = {
-        let fileSize = UILabel()
-        fileSize.textColor = UIColor(netHex: 0x2C2C2C)
-        fileSize.font = UIFont.systemFont(ofSize: 12)
-        return fileSize
-    }()
-    private lazy var summary: UILabel = {
-        let summary = UILabel()
-        summary.textColor = UIColor(netHex: 0x999999)
-        summary.font = UIFont.systemFont(ofSize: 12)
-        return summary
-    }()
-    
-    private func _init() {
-        selectView.image = UIImage.loadImage("com_icon_file_unselect")
-        
-        contentView.addSubview(fileIcon)
-        contentView.addSubview(fileName)
-        contentView.addSubview(fileSize)
-        contentView.addSubview(summary)
-        contentView.addSubview(selectView)
-        
-        selectImageWidthConstraint = _JCLayoutConstraintMake(selectView, .width, .equal, nil, .notAnAttribute, 0)
-        contentView.addConstraint(_JCLayoutConstraintMake(selectView, .left, .equal, contentView, .left, 17.5))
-        contentView.addConstraint(_JCLayoutConstraintMake(selectView, .centerY, .equal, contentView, .centerY))
-        contentView.addConstraint(selectImageWidthConstraint)
-        contentView.addConstraint(_JCLayoutConstraintMake(selectView, .height, .equal, nil, .notAnAttribute, 21))
-        
-        contentView.addConstraint(_JCLayoutConstraintMake(fileIcon, .left, .equal, selectView, .right, 17.5))
-        contentView.addConstraint(_JCLayoutConstraintMake(fileIcon, .centerY, .equal, contentView, .centerY))
-        contentView.addConstraint(_JCLayoutConstraintMake(fileIcon, .width, .equal, nil, .notAnAttribute, 50))
-        contentView.addConstraint(_JCLayoutConstraintMake(fileIcon, .height, .equal, nil, .notAnAttribute, 50))
-        
-        contentView.addConstraint(_JCLayoutConstraintMake(fileName, .left, .equal, fileIcon, .right, 12.5))
-        contentView.addConstraint(_JCLayoutConstraintMake(fileName, .top, .equal, contentView, .top, 14.5))
-        contentView.addConstraint(_JCLayoutConstraintMake(fileName, .right, .equal, contentView, .right, -17.5))
-        contentView.addConstraint(_JCLayoutConstraintMake(fileName, .height, .equal, nil, .notAnAttribute, 21))
-        
-        contentView.addConstraint(_JCLayoutConstraintMake(fileSize, .right, .equal, fileName, .right))
-        contentView.addConstraint(_JCLayoutConstraintMake(fileSize, .left, .equal, fileName, .left))
-        contentView.addConstraint(_JCLayoutConstraintMake(fileSize, .top, .equal, fileName, .bottom))
-        contentView.addConstraint(_JCLayoutConstraintMake(fileSize, .height, .equal, nil, .notAnAttribute, 16.5))
-        
-        contentView.addConstraint(_JCLayoutConstraintMake(summary, .left, .equal, fileSize, .left))
-        contentView.addConstraint(_JCLayoutConstraintMake(summary, .right, .equal, fileSize, .right))
-        contentView.addConstraint(_JCLayoutConstraintMake(summary, .top, .equal, fileSize, .bottom))
-        contentView.addConstraint(_JCLayoutConstraintMake(summary, .height, .equal, fileSize, .height))
-    }
-}

+ 0 - 80
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/GroupAvatorCell.swift

@@ -1,80 +0,0 @@
-//
-//  GroupAvatorCell.swift
-//  JChat
-//
-//  Created by 邓永豪 on 2017/9/19.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-class GroupAvatorCell: JCTableViewCell {
-
-    var title: String {
-        get {
-            return self.titleLabel.text!
-        }
-        set {
-            return self.titleLabel.text  = newValue
-        }
-    }
-
-    var avator: UIImage? {
-        get {
-            return avatorView.image
-        }
-        set {
-            avatorView.image = newValue
-        }
-    }
-
-    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
-        super.init(style: style, reuseIdentifier: reuseIdentifier)
-        _init()
-    }
-
-    required init?(coder aDecoder: NSCoder) {
-        super.init(coder: aDecoder)
-        _init()
-    }
-
-    override func awakeFromNib() {
-        super.awakeFromNib()
-        _init()
-    }
-
-    private lazy var titleLabel: UILabel = UILabel()
-    private lazy var avatorView: UIImageView =  UIImageView()
-
-    func bindData(_ group: JMSGGroup) {
-        group.thumbAvatarData { (data, id , error) in
-            if let data = data {
-                let image = UIImage(data: data)
-                self.avatorView.image = image
-            }
-        }
-    }
-
-    //MARK: - private func
-    private func _init() {
-        titleLabel.textAlignment = .left
-        titleLabel.font = UIFont.systemFont(ofSize: 16)
-
-        avatorView.contentMode = .scaleAspectFill
-        avatorView.image = UIImage.loadImage("com_icon_group_36")
-        avatorView.clipsToBounds = true
-
-        contentView.addSubview(avatorView)
-        contentView.addSubview(titleLabel)
-
-        addConstraint(_JCLayoutConstraintMake(titleLabel, .left, .equal, contentView, .left, 15))
-        addConstraint(_JCLayoutConstraintMake(titleLabel, .right, .equal, contentView, .centerX))
-        addConstraint(_JCLayoutConstraintMake(titleLabel, .centerY, .equal, contentView, .centerY))
-        addConstraint(_JCLayoutConstraintMake(titleLabel, .height, .equal, nil, .notAnAttribute, 22.5))
-
-        addConstraint(_JCLayoutConstraintMake(avatorView, .right, .equal, contentView, .right))
-        addConstraint(_JCLayoutConstraintMake(avatorView, .centerY, .equal, contentView, .centerY))
-        addConstraint(_JCLayoutConstraintMake(avatorView, .height, .equal, nil, .notAnAttribute, 36))
-        addConstraint(_JCLayoutConstraintMake(avatorView, .width, .equal, nil, .notAnAttribute, 36))
-    }
-}

+ 0 - 85
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/ImageFileCell.swift

@@ -1,85 +0,0 @@
-//
-//  ImageFileCell.swift
-//  JChat
-//
-//  Created by 邓永豪 on 2017/8/28.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-class ImageFileCell: UICollectionViewCell {
-    
-    var isEditMode: Bool {
-        get {
-            return !selectView.isHidden
-        }
-        set {
-            selectView.isHidden = !newValue
-        }
-    }
-    
-    var isSelectImage: Bool {
-        get {
-            return isSelect
-        }
-        set {
-            if newValue {
-                selectView.image = UIImage.loadImage("com_icon_file_select")
-            } else {
-                selectView.image = UIImage.loadImage("com_icon_file_unselect")
-            }
-            isSelect = newValue
-        }
-    }
-    
-    override init(frame: CGRect) {
-        super.init(frame: frame)
-        _init()
-    }
-    
-    required init?(coder aDecoder: NSCoder) {
-        fatalError("init(coder:) has not been implemented")
-    }
-    
-    func bindDate(_ message: JMSGMessage) {
-        if message.contentType == .image {
-            let content = message.content as! JMSGImageContent
-            content.largeImageData(progress: nil, completionHandler: { (data, msgId, error) in
-                if msgId == message.msgId {
-                    if let data = data {
-                        let image = UIImage(data: data)
-                        self.imageView.image = image
-                    }
-                }
-            })
-        }
-        guard let content = message.content as? JMSGFileContent else {
-            return
-        }
-        content.fileData { (data, msgId, error) in
-            if msgId == message.msgId {
-                if let data = data {
-                    let image = UIImage(data: data)
-                    self.imageView.image = image
-                }
-            }
-        }
-    }
-    
-    lazy var imageView: UIImageView = UIImageView()
-    private var isSelect = false
-    private lazy var selectView: UIImageView = UIImageView()
-
-    private func _init(){
-        imageView.frame = CGRect(x: 0, y: 0, width: self.width, height: self.height)
-        imageView.contentMode = .scaleAspectFit
-        imageView.clipsToBounds = true
-        addSubview(imageView)
-        
-        selectView.isHidden = true
-        selectView.frame = CGRect(x: self.width - 31, y: 5, width: 21, height: 21)
-        selectView.image = UIImage.loadImage("com_icon_file_unselect")
-        addSubview(selectView)
-    }
-}

+ 0 - 29
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/ImageFileHeader.swift

@@ -1,29 +0,0 @@
-//
-//  SHomeHeader.swift
-//
-//  Created by wangjie on 16/5/4.
-//  Copyright © 2016年 wangjie. All rights reserved.
-//
-
-import UIKit
-
-class ImageFileHeader: UICollectionReusableView {
-
-    override init(frame: CGRect) {
-        super.init(frame: frame)
-        _init()
-    }
-
-    required init?(coder aDecoder: NSCoder) {
-        fatalError("init(coder:) has not been implemented")
-    }
-
-    var titleLabel: UILabel!
-
-    private func _init(){
-        titleLabel = UILabel(frame: CGRect(x: 16.5, y: 0, width: self.width, height: self.height))
-        titleLabel.textColor = UIColor(netHex: 0x808080)
-        titleLabel.font = UIFont.systemFont(ofSize: 13)
-        addSubview(titleLabel)
-    }
-}

+ 0 - 494
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCChatView.swift

@@ -1,494 +0,0 @@
-//
-//  JCChatView.swift
-//  JChat
-//
-//  Created by deng on 2017/2/28.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-public protocol JCChatViewDataSource: class {
-    
-    func numberOfItems(in chatView: JCChatView)
-    
-    func chatView(_ chatView: JCChatView, itemAtIndexPath: IndexPath)
-    
-}
-
-var isWait = false
-
-@objc public protocol JCChatViewDelegate: NSObjectProtocol {
-    
-    @objc optional func chatView(_ chatView: JCChatView, shouldShowMenuForItemAt indexPath: IndexPath) -> Bool
-    @objc optional func chatView(_ chatView: JCChatView, canPerformAction action: Selector, forItemAt indexPath: IndexPath, withSender sender: Any?) -> Bool
-    @objc optional func chatView(_ chatView: JCChatView, performAction action: Selector, forItemAt indexPath: IndexPath, withSender sender: Any?)
-    @objc optional func refershChatView(chatView: JCChatView)
-    @objc optional func tapImageMessage(image: UIImage?, indexPath: IndexPath)
-    
-    @objc optional func deleteMessage(message: JCMessageType)
-    @objc optional func copyMessage(message: JCMessageType)
-    @objc optional func forwardMessage(message: JCMessageType)
-    @objc optional func withdrawMessage(message: JCMessageType)
-
-    @objc optional func indexPathsForVisibleItems(chatView: JCChatView, items: [IndexPath])
-}
-
-
-@objc open class JCChatView: UIView {
-    
-    public init(frame: CGRect, chatViewLayout: JCChatViewLayout) {
-        _chatViewData = JCChatViewData()
-        _chatViewLayout = chatViewLayout
-        let containerViewFrame = CGRect(x: 0, y: 0, width: frame.size.width, height: frame.size.height)
-        _chatContainerView = JCChatContainerView(frame: containerViewFrame, collectionViewLayout: chatViewLayout)
-        super.init(frame: frame)
-        _commonInit()
-    }
-    
-    public required init?(coder aDecoder: NSCoder) {
-        // decode layout
-        guard let chatViewLayout = JCChatViewLayout(coder: aDecoder) else {
-            return nil
-        }
-        // decode container view
-        guard let chatContainerView = JCChatContainerView(coder: aDecoder) else {
-            return nil
-        }
-        // init data
-        _chatViewData = JCChatViewData()
-        // init to layout & container view
-        _chatViewLayout = chatViewLayout
-        _chatContainerView = chatContainerView
-        // init super
-        super.init(coder: aDecoder)
-        // init other data
-        _commonInit()
-    }
-    
-    open weak var delegate: JCChatViewDelegate?
-    open weak var dataSource: JCChatViewDataSource?
-    open weak var messageDelegate: JCMessageDelegate?
-    
-    func insert(_ newMessage: JCMessageType, at index: Int) {
-        _batchBegin()
-        _batchItems.append(.insert(newMessage, at: index))
-        _batchCommit()
-    }
-    func insert(contentsOf newMessages: Array<JCMessageType>, at index: Int) {
-        _batchBegin()
-        _batchItems.append(contentsOf: newMessages.map({ .insert($0, at: index) }))
-        _batchCommit(true)
-    }
-    
-    func update(_ newMessage: JCMessageType, at index: Int) {
-        _batchBegin()
-        _batchItems.append(.update(newMessage, at: index))
-        _batchCommit()
-    }
-    
-    func removeAll() {
-        _batchBegin()
-        for index in 0..<_chatViewData.count {
-            _batchItems.append(.remove(at: index))
-        }
-        _batchCommit()
-    }
-    
-    func remove(at index: Int) {
-        _batchBegin()
-        _batchItems.append(.remove(at: index))
-        _batchCommit()
-    }
-    func remove(contentOf indexs: Array<Int>) {
-        _batchBegin()
-        _batchItems.append(contentsOf: indexs.map({ .remove(at: $0) }))
-        _batchCommit()
-    }
-    
-    func move(at index1: Int, to index2: Int) {
-        _batchBegin()
-        _batchItems.append(.move(at: index1, to: index2))
-        _batchCommit()
-    }
-    
-    func append(_ newMessage: JCMessageType) {
-        insert(newMessage, at: _chatViewData.count)
-    }
-    func append(contentsOf newMessages: Array<JCMessageType>) {
-        insert(contentsOf: newMessages, at: _chatViewData.count)
-    }
-    
-    fileprivate func _batchBegin() {
-        _chatContainerView.messageDelegate = self.messageDelegate
-        objc_sync_enter(_batchItems)
-        _batchRequiredCount = max(_batchRequiredCount + 1, 1)
-        objc_sync_exit(_batchItems)
-    }
-    fileprivate func _batchCommit(_ isInsert: Bool = false) {
-        objc_sync_enter(_batchItems)
-        _batchRequiredCount = max(_batchRequiredCount - 1, 0)
-        guard _batchRequiredCount == 0 else {
-            objc_sync_exit(_batchItems)
-            return
-        }
-        let oldData = _chatViewData
-        let newData = JCChatViewData()
-        let updateItems = _batchItems
-        _batchItems.removeAll()
-        objc_sync_exit(_batchItems)
-        
-        _ = _chatContainerView.numberOfItems(inSection: 0)
-        let update = JCChatViewUpdate(newData: newData, oldData: oldData, updateItems: updateItems)
-        // exec
-        _chatViewData = newData
-        _chatContainerView.performBatchUpdates(with: update, isInsert, completion: nil)
-    }
-    
-    fileprivate lazy var _batchItems: Array<JCChatViewUpdateChangeItem> = []
-    fileprivate lazy var _batchRequiredCount: Int = 0
-    
-    private func _commonInit() {
-        
-        backgroundColor = UIColor(netHex: 0xe8edf3)
-        let header = MJRefreshNormalHeader(refreshingTarget: self, refreshingAction: #selector(_onPullToFresh))
-        header?.stateLabel.isHidden = true
-        _chatContainerView.mj_header = header
-        _chatContainerView.allowsSelection = false
-        _chatContainerView.allowsMultipleSelection = false
-        _chatContainerView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
-        _chatContainerView.keyboardDismissMode = .onDrag
-        _chatContainerView.backgroundColor = UIColor(netHex: 0xE8EDF3)
-        _chatContainerView.dataSource = self
-        _chatContainerView.delegate = self
-        
-        addSubview(_chatContainerView)
-        #if READ_VERSION
-        _chatContainerView.addObserver(self, forKeyPath: "contentOffset", options: .new, context: nil)
-        #endif
-    }
-    
-    fileprivate var _chatViewData: JCChatViewData
-    
-    fileprivate var _chatViewLayout: JCChatViewLayout
-    fileprivate var _chatContainerView: JCChatContainerView
-    
-    fileprivate lazy var _chatContainerRegistedTypes: Set<String> = []
-    
-    @objc func _onPullToFresh() {
-        delegate?.refershChatView?(chatView: self)
-    }
-    func stopRefresh() {
-        _chatContainerView.mj_header.endRefreshing()
-    }
-    
-    func scrollToLast(animated: Bool) {
-        let count = _chatContainerView.numberOfItems(inSection: 0)
-        if count > 0 {
-            _chatContainerView.scrollToItem(at: IndexPath(row: count - 1, section: 0), at: .bottom, animated: animated)
-        }
-    }
-
-    deinit {
-        #if READ_VERSION
-        _chatContainerView.removeObserver(self, forKeyPath: "contentOffset")
-        #endif
-    }
-}
-
-internal class JCChatContainerView: UICollectionView {
-    
-    weak var messageDelegate: JCMessageDelegate?
-    
-    var currentUpdate: JCChatViewUpdate? {
-        return _currentUpdate
-    }
-    
-    func performBatchUpdates(with update: JCChatViewUpdate, _ isInsert: Bool = false, completion:((Bool) -> Void)?) {
-        
-        // read changes
-        guard let changes = update.updateChanges else {
-            return
-        }
-        _currentUpdate = update
-        
-        // TODO: 不是最优
-        if update.updateItems.count > 0 {
-            for item in update.updateItems {
-                switch item {
-                case .update:
-                    self.performBatchUpdates({ 
-                        self.reloadItems(at: [IndexPath(row: item.at, section: 0)])
-                    }, completion: nil)
-                    return
-                default:
-                    break
-                }
-            }
-        }
-        
-        
-        var oldContent = self.contentSize
-//        self.contentSize = CGSize(width: self.contentSize.width, height: 3725)
-//        self.setContentOffset(CGPoint(x: 0, y: 3725 - oldContent.height), animated: false)
-//        self.layoutIfNeeded()
-//        self.setContentOffset(CGPoint(x: 0, y: 250232320), animated: false)
-//        self.layoutIfNeeded()
-        // commit changes
-        
-        UIView.animate(withDuration: 0) {
-            if isInsert {
-                self.isHidden = true
-            }
-            self.performBatchUpdates({
-                // apply move
-                changes.filter({ $0.isMove }).forEach({
-                    self.moveItem(at: .init(item: max($0.from, 0), section: 0),
-                                  to: .init(item: max($0.to, 0), section: 0))
-                })
-//                print(oldContent)
-                // apply insert/remove/update
-                self.insertItems(at: changes.filter({ $0.isInsert }).map({ .init(item: max($0.to, 0), section: 0) }))
-                self.reloadItems(at: changes.filter({ $0.isUpdate }).map({ .init(item: max($0.from, 0), section: 0) }))
-                self.deleteItems(at: changes.filter({ $0.isRemove }).map({ .init(item: max($0.from, 0), section: 0) }))
-                
-            }, completion: { finished in
-                if isInsert {
-                    UIView.animate(withDuration: 0, animations: {
-                        if self.contentSize.height > oldContent.height && oldContent.height != 0 {
-                            self.setContentOffset(CGPoint(x: 0, y: self.contentSize.height - oldContent.height), animated: false)
-                            self.layoutIfNeeded()
-                            oldContent = self.contentSize
-                        }
-                    })
-                    self.isHidden = false
-                }
-                
-                completion?(finished)
-            })
-        }
-        
-        _currentUpdate = nil
-    }
-    
-    private var _currentUpdate: JCChatViewUpdate?
-}
-
-
-
-extension JCChatView: UICollectionViewDataSource, JCChatViewLayoutDelegate {
-    
-    open var isRoll: Bool {
-        return _chatContainerView.isDragging || _chatContainerView.isDecelerating
-    }
-    
-    open dynamic var indexPathsForVisibleItems: [IndexPath] {
-        return _chatContainerView.indexPathsForVisibleItems
-    }
-    
-    open dynamic var contentSize: CGSize {
-        set { return _chatContainerView.contentSize = newValue }
-        get { return _chatContainerView.contentSize }
-    }
-    open dynamic var contentOffset: CGPoint {
-        set { return _chatContainerView.contentOffset = newValue }
-        get { return _chatContainerView.contentOffset }
-    }
-    open dynamic var contentInset: UIEdgeInsets {
-        set { return _chatContainerView.contentInset = newValue }
-        get { return _chatContainerView.contentInset }
-    }
-    open dynamic var scrollIndicatorInsets: UIEdgeInsets {
-        set { return _chatContainerView.scrollIndicatorInsets = newValue }
-        get { return _chatContainerView.scrollIndicatorInsets }
-    }
-    
-    open func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
-        return _chatViewData.count
-    }
-    
-    open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
-
-        let message = _chatViewData[indexPath.item]
-        
-//        let options = (message.options.showsCard.hashValue << 0) | (message.options.showsAvatar.hashValue << 1)
-        let alignment = message.options.alignment.rawValue
-        let identifier = NSStringFromClass(type(of: message.content)) + ".\(alignment)"
-        
-        if !_chatContainerRegistedTypes.contains(identifier) {
-            _chatContainerRegistedTypes.insert(identifier)
-            _chatContainerView.register(JCChatViewCell.self, forCellWithReuseIdentifier: identifier)
-        }
-        let cell = _chatContainerView.dequeueReusableCell(withReuseIdentifier: identifier, for: indexPath) as! JCChatViewCell
-        cell.delegate = messageDelegate
-        cell.updateView()
-        return cell
-    }
-    
-    open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, itemAt indexPath: IndexPath) -> JCMessageType {
-        return _chatViewData[indexPath.item]
-    }
-    
-    open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
-        guard let collectionViewLayout = collectionViewLayout as? JCChatViewLayout else {
-            return .zero
-        }
-        guard let layoutAttributesInfo = collectionViewLayout.layoutAttributesInfoForItem(at: indexPath) else {
-            return .zero
-        }
-        let size = layoutAttributesInfo.layoutedBoxRect(with: .all).size
-        return .init(width: collectionView.frame.width, height: size.height)
-    }
-    open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAvatarOf style: JCMessageStyle) -> CGSize {
-        // 78 * 78
-        return .init(width: 40, height: 40)
-    }
-    open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemCardOf style: JCMessageStyle) -> CGSize {
-        return .init(width: 0, height: 18)
-    }
-    
-    public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemTipsOf style: JCMessageStyle) -> CGSize {
-        return .init(width: 100, height: 21)
-    }
-    
-    open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForItemOf style: JCMessageStyle) -> UIEdgeInsets {
-        switch style {
-        case .bubble:
-            // bubble content edg, 2x
-            // +----12--+-+---+
-            // |        | |   |
-            // 16       4 40  16
-            // |        | |   |
-            // +----12--+-+---+
-            return .init(top: 6, left: 8, bottom: 6, right: 2 + 20 + 8)
-            
-        case .notice:
-            // default edg
-            // +----10----+
-            // 20         20
-            // +----10----+
-            return .init(top: 10, left: 20, bottom: 10, right: 20)
-            
-//        default:
-//            // default edg
-//            // +----10----+
-//            // 10         10
-//            // +----10----+
-//            return .init(top: 10, left: 10, bottom: 10, right: 10)
-        }
-    }
-    open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForItemCardOf style: JCMessageStyle) -> UIEdgeInsets {
-        return .init(top: 0, left: 8, bottom: 2, right: 8)
-    }
-    open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForItemAvatarOf style: JCMessageStyle) -> UIEdgeInsets {
-        return .init(top: 0, left: 2, bottom: 2, right: 2)
-    }
-    open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForItemBubbleOf style: JCMessageStyle) -> UIEdgeInsets {
-//        return .init(top: -2, left: 0, bottom: -2, right: 0)
-        return .init(top: 0, left: 8, bottom: 0, right: 0)
-    }
-    open func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForItemContentOf style: JCMessageStyle) -> UIEdgeInsets {
-        switch style {
-        case .bubble:
-            // bubble image edg, scale: 2x, radius: 15
-            // /--------16-------\
-            // |  +-----04-----+ |
-            // 20 04          04 20
-            // |  +-----04-----+ |
-            // \--------16-------/
-//            return .init(top: 8 + 2, left: 10 + 2, bottom: 8 + 2, right: 10 + 2)
-            return .init(top: 2, left: 5 + 2, bottom: 2, right: 2)
-            
-        case .notice:
-            // notice edg
-            // /------4-------\
-            // 10             10
-            // \------4-------/
-            return .init(top: 4, left: 10, bottom: 4, right: 10)
-            
-        }
-    }
-    
-    open func collectionView(_ collectionView: UICollectionView, shouldShowMenuForItemAt indexPath: IndexPath) -> Bool {
-        return true
-    }
-    
-    open func collectionView(_ collectionView: UICollectionView, canPerformAction action: Selector, forItemAt indexPath: IndexPath, withSender sender: Any?) -> Bool {
-        let message = _chatViewData[indexPath.item]
-        if message.content is JCMessageNoticeContent || message.content is JCMessageTimeLineContent  {
-            return false
-        }
-        if let _ = message.content as? JCMessageTextContent {
-            if action == #selector(copyMessage(_:)) {
-                return true
-            }
-        }
-        if action == #selector(deleteMessage(_:)) {
-            return true
-        }
-        
-        if action == #selector(forwardMessage(_:)) {
-            return true
-        }
-        
-        if action == #selector(withdrawMessage(_:)) {
-            if let sender = message.sender {
-                if sender.isEqual(to: JMSGUser.myInfo()) {
-                    return true
-                }
-            }
-            return false
-        }
- 
-        return false
-    }
-    
-    @objc func copyMessage(_ sender: Any) {}
-    @objc func deleteMessage(_ sender: Any) {}
-    @objc func forwardMessage(_ sender: Any) {}
-    @objc func withdrawMessage(_ sender: Any) {}
-    
-    open func collectionView(_ collectionView: UICollectionView, performAction action: Selector, forItemAt indexPath: IndexPath, withSender sender: Any?) {
-        let message = _chatViewData[indexPath.item]
-        if action == #selector(copyMessage(_:)) {
-            if let content = message.content as? JCMessageTextContent {
-                let pas = UIPasteboard.general
-                pas.string = content.text.string
-            }
-        }
-        if action == #selector(deleteMessage(_:)) {
-            remove(at: indexPath.item)
-            delegate?.deleteMessage?(message: message)
-        }
-//        if action == #selector(paste(_:)) {
-//            move(at: indexPath.item, to: _chatViewData.count - 1)
-//        }
-        if action == #selector(forwardMessage(_:)) {
-            delegate?.forwardMessage?(message: message)
-        }
-        
-        if action == #selector(withdrawMessage(_:)) {
-            delegate?.withdrawMessage?(message: message)
-        }
-    }
-}
-
-extension JCChatView {
-    override open func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
-        if keyPath == "contentOffset" {
-            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()) {
-                if !isWait {
-                    isWait = true
-                    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.05) {
-                        self.delegate?.indexPathsForVisibleItems?(chatView: self, items: self._chatContainerView.indexPathsForVisibleItems)
-                        isWait = false
-                    }
-                }
-            }
-        }
-    }
-
-}
-
-extension JCChatView: SAIInputBarScrollViewType {
-}

+ 0 - 364
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCChatViewCell.swift

@@ -1,364 +0,0 @@
-//
-//  JCChatViewCell.swift
-//  JChat
-//
-//  Created by deng on 2017/2/28.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-import CocoaLumberjack
-
-open class JCChatViewCell: UICollectionViewCell, UIGestureRecognizerDelegate {
-    
-    weak var delegate: JCMessageDelegate?
-    
-    public override init(frame: CGRect) {
-        super.init(frame: frame)
-        _commonInit()
-    }
-    
-    public required init?(coder aDecoder: NSCoder) {
-        super.init(coder: aDecoder)
-        _commonInit()
-    }
-    
-    deinit {
-        guard let observer = _menuNotifyObserver else{
-            return
-        }
-        NotificationCenter.default.removeObserver(observer)
-    }
-    
-    func updateView() {
-        guard let message = _layoutAttributes?.message else {
-            return
-        }
-        _tipsView?.apply(message)
-        let tipsView = _tipsView as? JCMessageTipsView
-        if tipsView != nil {
-            tipsView?.delegate = self.delegate
-        }
-        
-        let avatarView = _avatarView as? JCMessageAvatarView
-        if avatarView != nil {
-            avatarView?.delegate = self.delegate
-        }
-        _contentView?.apply(message)
-    }
-    
-    
-    open override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {
-        
-        super.apply(layoutAttributes)
-        guard let _ = layoutAttributes as? JCChatViewLayoutAttributes else {
-            return
-        }
-        _updateViews()
-        _updateViewLayouts()
-        _updateViewValues()
-    }
-
-    open override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
-        guard let rect = _layoutAttributes?.info?.layoutedBoxRect(with: .all) else {
-            return false
-        }
-        return rect.contains(point)
-    }
-    
-    open class var cardViewClass: JCMessageContentViewType.Type {
-        return JCMessageCardView.self
-    }
-    
-    open class var tipsViewClass: JCMessageContentViewType.Type {
-        return JCMessageTipsView.self
-    }
-    
-    open class var avatarViewClass: JCMessageContentViewType.Type {
-        return JCMessageAvatarView.self
-    }
-    
-    
-    private lazy var send_nor = UIImage.loadImage("chat_bubble_send_nor")!.resizableImage(withCapInsets: UIEdgeInsets(top: 25, left: 25, bottom: 25, right: 25))
-    private lazy var send_press = UIImage.loadImage("chat_bubble_send_press")!.resizableImage(withCapInsets: UIEdgeInsets(top: 25, left: 25, bottom: 25, right: 25))
-    
-    private lazy var recive_nor = UIImage.loadImage("chat_bubble_recive_nor")!.resizableImage(withCapInsets: UIEdgeInsets(top: 25, left: 25, bottom: 25, right: 25))
-    private lazy var recive_press = UIImage.loadImage("chat_bubble_recive_press")!.resizableImage(withCapInsets: UIEdgeInsets(top: 25, left: 25, bottom: 25, right: 25))
-    
-    private func _updateViews() {
-
-        guard let message = _layoutAttributes?.message else {
-            return
-        }
-        let options = message.options
-
-        if options.showsBubble {
-            if _bubbleView == nil {
-                _bubbleView = UIImageView()
-            }
-            if let view = _bubbleView, view.superview == nil {
-                insertSubview(view, belowSubview: contentView)
-            }
-        } else {
-            if let view = _bubbleView {
-                view.removeFromSuperview()
-            }
-            _bubbleView = nil
-        }
-        
-        if options.showsCard {
-            if _cardView == nil {
-                _cardView = type(of: self).cardViewClass._init()
-            }
-            if let view = _cardView as? UIView, view.superview == nil {
-                contentView.addSubview(view)
-            }
-        } else {
-            if let view = _cardView as? UIView {
-                view.removeFromSuperview()
-            }
-            _cardView = nil
-        }
-        
-        if options.showsTips {
-            if _tipsView == nil {
-                _tipsView = type(of: self).tipsViewClass._init()
-            }
-            if let view = _tipsView as? UIView, view.superview == nil {
-                contentView.addSubview(view)
-            }
-        } else {
-            if let view = _tipsView as? UIView {
-                view.removeFromSuperview()
-            }
-            _tipsView = nil
-        }
-        
-        
-        if options.showsAvatar {
-            if _avatarView == nil {
-                _avatarView = type(of: self).avatarViewClass._init()
-            }
-            if let view = _avatarView as? UIView, view.superview == nil {
-                contentView.addSubview(view)
-            }
-        } else {
-            if let view = _avatarView as? UIView {
-                view.removeFromSuperview()
-            }
-            _avatarView = nil
-        }
-        
-        if _contentView == nil {
-            // create
-            _contentView = type(of: message.content).viewType._init()
-            // move
-            if let view = _contentView as? UIView, view.superview == nil {
-                contentView.addSubview(view)
-            }
-        }
-    }
-    private func _updateViewLayouts() {
-        // prepare
-        guard let layoutInfo = _layoutAttributes?.info else {
-            return
-        }
-        // update bubble view layout
-        if let view = _bubbleView {
-            view.frame = layoutInfo.layoutedRect(with: .bubble)
-        }
-        // update visit card view layout
-        if let view = _cardView as? UIView {
-            view.frame = layoutInfo.layoutedRect(with: .card)
-        }
-        if let view = _tipsView as? UIView {
-            let frame = layoutInfo.layoutedRect(with: .tips)
-            view.frame = frame
-        }
-        // update avatar view layout
-        if let view = _avatarView as? UIView {
-            view.frame = layoutInfo.layoutedRect(with: .avatar)
-        }
-        
-        // update content view layout
-        if let view = _contentView as? UIView {
-            view.frame = layoutInfo.layoutedRect(with: .content)
-        }
-    }
-    private func _updateViewValues() {
-        guard let message = _layoutAttributes?.message else {
-            return
-        }
-        let options = message.options
-        
-        _cardView?.apply(message)
-        _tipsView?.apply(message)
-        _avatarView?.apply(message)
-        let avatarView = _avatarView as? JCMessageAvatarView
-        if avatarView != nil {
-            avatarView?.delegate = self.delegate
-            let user = message.sender?.username
-            DDLogDebug("更新头像,发送者头像:\(user ?? "")")
-            let urlstr = AppDelegate.o2Collect.generateURLWithAppContextKey(ContactContext.contactsContextKeyV2, query: ContactContext.personIconByNameQueryV2, parameter: ["##name##":user as AnyObject])
-            let url = URL(string: urlstr!)
-            avatarView?.hnk_setImageFromURL(url!)
-        }
-        _contentView?.apply(message)
-        
-        if let view = _bubbleView {
-            switch options.alignment {
-            case .left:
-                view.image = recive_nor
-                view.highlightedImage = recive_press
-                
-            case .right:
-                view.image = send_nor
-                view.highlightedImage = send_press
-                
-            case .center:
-                break
-            }
-        }
-    }
-    
-    open override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
-        guard gestureRecognizer == _menuGesture else {
-            return super.gestureRecognizerShouldBegin(gestureRecognizer)
-        }
-        guard let rect = _layoutAttributes?.info?.layoutedBoxRect(with: .content) else {
-            return false
-        }
-        guard rect.contains(gestureRecognizer.location(in: contentView)) else {
-            return false
-        }
-        return true
-    }
-    
-    func copyMessage(_ sender: Any) {}
-    func deleteMessage(_ sender: Any) {}
-    func forwardMessage(_ sender: Any) {}
-    func withdrawMessage(_ sender: Any) {}
-
-    private dynamic func _handleMenuGesture(_ sender: UILongPressGestureRecognizer) {
-        guard sender.state == .began else {
-            return
-        }
-        guard let view = _contentView as? UIView,
-            let content = _layoutAttributes?.message?.content,
-            let info = _layoutAttributes?.info else {
-                return
-        }
-        
-        let rect = info.layoutedRect(with: .content).inset(by: -content.layoutMargins)
-        let menuController = UIMenuController.shared
-        
-        // set responder
-        NSClassFromString("UICalloutBar")?.setValue(self, forKeyPath: "sharedCalloutBar.responderTarget")
-        
-        
-        menuController.menuItems = [
-            UIMenuItem(title: "复制", action: #selector(copyMessage(_:))),
-            UIMenuItem(title: "转发", action: #selector(forwardMessage(_:))),
-            UIMenuItem(title: "撤回", action: #selector(withdrawMessage(_:))),
-            UIMenuItem(title: "删除", action: #selector(deleteMessage(_:)))
-        ]
-    
-        // set menu display position
-        menuController.setTargetRect(convert(rect, to: view), in: view)
-        menuController.setMenuVisible(true, animated: true)
-        
-        // really show?
-        guard menuController.isMenuVisible else {
-            return
-        }
-        
-        // set selected
-        self.isHighlighted = true
-        self._menuNotifyObserver = NotificationCenter.default.addObserver(forName: UIMenuController.willHideMenuNotification, object: nil, queue: nil) { [weak self] notification in
-            // is release?
-            guard let observer = self?._menuNotifyObserver else {
-                return
-            }
-            NotificationCenter.default.removeObserver(observer)
-            // cancel select
-            self?.isHighlighted = false
-            self?._menuNotifyObserver = nil
-        }
-    }
-    
-    open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
-        // menu bar only process
-        guard sender is UIMenuController else {
-            // other is default process
-            return super.canPerformAction(action, withSender: sender)
-        }
-        // check collectionView and attributes
-        guard let view = _collectionView, let indexPath = _layoutAttributes?.indexPath else {
-            return false
-        }
-        // forward to collectionView
-        guard let result = view.delegate?.collectionView?(view, canPerformAction: action, forItemAt: indexPath, withSender: sender) else {
-            return false
-        }
-        return result
-    }
-    
-    open override func perform(_ action: Selector!, with sender: Any!) -> Unmanaged<AnyObject>! {
-        // menu bar only process
-        guard sender is UIMenuController else {
-            // other is default process
-            return super.perform(action, with: sender)
-        }
-        // check collectionView and attributes
-        guard let view = _collectionView, let indexPath = _layoutAttributes?.indexPath else {
-            return nil
-        }
-        // forward to collectionView
-        view.delegate?.collectionView?(view, performAction: action, forItemAt: indexPath, withSender: sender)
-        
-        return nil
-    }
-    
-    private func _commonInit() {
-    }
-    
-    fileprivate var _bubbleView: UIImageView?
-    
-    fileprivate var _cardView: JCMessageContentViewType?
-    fileprivate var _avatarView: JCMessageContentViewType?
-    fileprivate var _contentView: JCMessageContentViewType?
-    fileprivate var _tipsView: JCMessageContentViewType?
-    
-    fileprivate var _menuNotifyObserver: Any?
-    fileprivate var _menuGesture: UILongPressGestureRecognizer? {
-        return value(forKeyPath: "_menuGesture") as? UILongPressGestureRecognizer
-    }
-    
-    @NSManaged fileprivate var _collectionView: UICollectionView?
-    @NSManaged fileprivate var _layoutAttributes: JCChatViewLayoutAttributes?
-}
-
-
-fileprivate extension JCMessageContentViewType {
-    // 如果是NSObject对象, 直接使用self.init()会导致无法释放内存
-    // 解决方案是转为显式类型再调用cls.init()
-    fileprivate static func _init() -> JCMessageContentViewType {
-        guard let cls = self as? NSObject.Type else {
-            return self.init()
-        }
-        guard let ob = cls.init() as? JCMessageContentViewType else {
-            return self.init()
-        }
-        return ob
-    }
-}
-
-fileprivate extension UICollectionReusableView {
-    @NSManaged fileprivate func _setLayoutAttributes(_ layoutAttributes: UICollectionViewLayoutAttributes)
-}
-
-
-fileprivate prefix func -(edg: UIEdgeInsets) -> UIEdgeInsets {
-    // 取反
-    return .init(top: -edg.top, left: -edg.left, bottom: -edg.bottom, right: edg.right)
-}

+ 0 - 46
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCChatViewData.swift

@@ -1,46 +0,0 @@
-//
-//  JCChatViewData.swift
-//  JChat
-//
-//  Created by deng on 10/04/2017.
-//  Copyright © 2017 HXHG. All rights reserved.
-//
-
-import UIKit
-
-internal class JCChatViewData: NSObject, NSCopying {
-    
-    internal override init() {
-        self.elements = []
-        super.init()
-    }
-    internal init(elements: [JCMessageType]) {
-        self.elements = elements
-        super.init()
-    }
-    
-    internal var count: Int {
-        return elements.count
-    }
-    
-    func copy(with zone: NSZone? = nil) -> Any {
-        return JCChatViewData(elements: self.elements)
-    }
-    
-    
-    internal subscript(index: Int) -> JCMessageType {
-        return elements[index]
-    }
-    
-    
-    internal func subarray(with subrange: Range<Int>) -> Array<JCMessageType> {
-        return Array(elements[subrange])
-    }
-    
-    internal func replaceSubrange(_ subrange: Range<Int>, with collection: Array<JCMessageType>)  {
-        elements.replaceSubrange(subrange, with: collection)
-    }
-    
-    
-    internal var elements: [JCMessageType]
-}

+ 0 - 324
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCChatViewLayout.swift

@@ -1,324 +0,0 @@
-//
-//  JCChatViewLayout.swift
-//  JChat
-//
-//  Created by deng on 2017/2/28.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-@objc open class JCChatViewLayout: UICollectionViewFlowLayout {
-    
-    public override init() {
-        super.init()
-        _commonInit()
-    }
-    public required init?(coder aDecoder: NSCoder) {
-        super.init(coder: aDecoder)
-        _commonInit()
-    }
-    
-    internal weak var _chatView: JCChatView?
-    
-    open override class var layoutAttributesClass: AnyClass {
-        return JCChatViewLayoutAttributes.self
-    }
-    
-    open override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
-        let attributes = super.layoutAttributesForItem(at: indexPath)
-        if let attributes = attributes as? JCChatViewLayoutAttributes, attributes.info == nil {
-            attributes.info = layoutAttributesInfoForItem(at: indexPath)
-        }
-        return attributes
-    }
-    open override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
-        let arr = super.layoutAttributesForElements(in: rect)
-        arr?.forEach({
-            guard let attributes = $0 as? JCChatViewLayoutAttributes, attributes.info == nil else {
-                return
-            }
-            attributes.info = layoutAttributesInfoForItem(at: attributes.indexPath)
-        })
-        return arr
-    }
-    
-    open func layoutAttributesInfoForItem(at indexPath: IndexPath) -> JCChatViewLayoutAttributesInfo? {
-        guard let collectionView = collectionView, let _ = collectionView.delegate as? JCChatViewLayoutDelegate, let message = _message(at: indexPath) else {
-            return nil
-        }
-        let size = CGSize(width: collectionView.frame.width, height: .greatestFiniteMagnitude)
-        if let info = _allLayoutAttributesInfo[message.identifier] {
-            // 这不是合理的做法
-            if !message.updateSizeIfNeeded {
-                return info
-            }
-        }
-        let options = message.options
-        
-        var allRect: CGRect = .zero
-        var allBoxRect: CGRect = .zero
-        
-        var cardRect: CGRect = .zero
-        var cardBoxRect: CGRect = .zero
-        
-        var avatarRect: CGRect = .zero
-        var avatarBoxRect: CGRect = .zero
-        
-        var bubbleRect: CGRect = .zero
-        var bubbleBoxRect: CGRect = .zero
-        
-        var contentRect: CGRect = .zero
-        var contentBoxRect: CGRect = .zero
-        
-        var tipsRect: CGRect = .zero
-        var tipsBoxRect: CGRect = .zero
-        
-        // 计算的时候以左对齐为基准
-        
-        // +---------------------------------------+ r0
-        // |+---------------------------------+ r1 |
-        // ||+---+ <NAME>                     |    |
-        // ||| A | +---------------------\ r4 |    |
-        // ||+---+ |+---------------+ r5 |    |    |
-        // ||      ||    CONTENT    |    |    |    |
-        // ||      |+---------------+    |    |    |
-        // ||      \---------------------/    |    |  +---+ r6
-        // |+---------------------------------+  <-|- | ! |
-        // +---------------------------------------+  +---+
-        
-        let edg0 = _inset(with: options.style, for: .all)
-        var r0 = CGRect(x: 0, y: 0, width: size.width, height: .greatestFiniteMagnitude)
-        var r1 = r0.inset(by: edg0)
-        
-        var x1 = r1.minX
-        var y1 = r1.minY
-        var x2 = r1.maxX
-        var y2 = r1.maxY
-        
-        if options.showsAvatar {
-            let edg = _inset(with: options.style, for: .avatar)
-            let size = _size(with: options.style, for: .avatar)
-            
-            let box = CGRect(x: x1, y: y1, width: edg.left + size.width + edg.right, height: edg.top + size.height + edg.bottom)
-            let rect = box.inset(by: edg)
-            
-            avatarRect = rect
-            avatarBoxRect = box
-            
-            x1 = box.maxX
-        }
-        
-        if options.showsCard {
-            let edg = _inset(with: options.style, for: .card)
-            let size = _size(with: options.style, for: .card)
-            
-            let box = CGRect(x: x1, y: y1, width: x2 - x1, height: edg.top + size.height + edg.bottom)
-            let rect = box.inset(by: edg)
-            
-            cardRect = rect
-            cardBoxRect = box
-            
-            y1 = box.maxY
-        }
-
-        if options.showsBubble {
-            let edg = _inset(with: options.style, for: .bubble)
-            
-            let box = CGRect(x: x1, y: y1, width: x2 - x1, height: y2 - y1)
-            let rect = box.inset(by: edg)
-            
-            bubbleRect = rect
-            bubbleBoxRect = box
-            
-            x1 = rect.minX
-            x2 = rect.maxX
-            y1 = rect.minY
-            y2 = rect.maxY
-        }
-
-        if true {
-            let edg0 = _inset(with: options.style, for: .content)
-            let edg1 = message.content.layoutMargins
-            //
-            let edg = UIEdgeInsets(top: edg0.top + edg1.top, left: edg0.left + edg1.left, bottom: edg0.bottom + edg1.bottom, right: edg0.right + edg1.right)
-            
-            var box = CGRect(x: x1, y: y1, width: x2 - x1, height: y2 - y1)
-            var rect = box.inset(by: edg)
-            
-            // calc content size
-            let size = message.content.sizeThatFits(rect.size)
-            
-            // restore offset
-            box.size.width = edg.left + size.width + edg.right
-            box.size.height = edg.top + size.height + edg.bottom
-            rect.size.width = size.width
-            rect.size.height = size.height
-            
-            contentRect = rect
-            contentBoxRect = box
-            
-            x1 = box.maxX
-            y1 = box.maxY
-        }
-
-        if options.showsBubble {
-            let edg = _inset(with: options.style, for: .bubble)
-            
-            bubbleRect.size.width = contentBoxRect.width
-            bubbleRect.size.height = contentBoxRect.height
-            
-            bubbleBoxRect.size.width = edg.left + contentBoxRect.width + edg.right
-            bubbleBoxRect.size.height = edg.top + contentBoxRect.height + edg.bottom
-        }
-        
-        if options.showsTips {
-            let edg = _inset(with: options.style, for: .tips)
-            let size = _size(with: options.style, for: .tips)
-            
-            let box = CGRect(x: x1 + 3, y: y1 - size.height - edg0.bottom, width: edg.left + size.width + edg.right, height: edg.top + size.height + edg.bottom)
-            let rect = box.inset(by: edg)
-            
-            tipsRect = rect
-            tipsBoxRect = box
-            
-            x1 = box.maxX
-        }
-        
-        // adjust
-        r1.size.width = x1 - r1.minX
-        r1.size.height = y1 - r1.minY
-        r0.size.width = x1
-        r0.size.height = y1 + edg0.bottom
-        
-        allRect = r1
-        allBoxRect = r0
-        
-        // algin
-        switch options.alignment {
-        case .right:
-            // to right
-            allRect.origin.x = size.width - allRect.maxX
-            allBoxRect.origin.x = size.width - allBoxRect.maxX
-            
-            cardRect.origin.x = size.width - cardRect.maxX
-            cardBoxRect.origin.x = size.width - cardBoxRect.maxX
-            
-            avatarRect.origin.x = size.width - avatarRect.maxX
-            avatarBoxRect.origin.x = size.width - avatarBoxRect.maxX
-            
-            bubbleRect.origin.x = size.width - bubbleRect.maxX
-            bubbleBoxRect.origin.x = size.width - bubbleBoxRect.maxX
-            
-            contentRect.origin.x = size.width - contentRect.maxX
-            contentBoxRect.origin.x = size.width - contentBoxRect.maxX
-            
-            tipsRect.origin.x = size.width - tipsRect.maxX
-            tipsBoxRect.origin.x = size.width - tipsBoxRect.maxX
-            
-        case .center:
-            allRect.origin.x = (size.width - allRect.width) / 2
-            allBoxRect.origin.x = (size.width - allBoxRect.width) / 2
-            
-            bubbleRect.origin.x = (size.width - bubbleRect.width) / 2
-            bubbleBoxRect.origin.x = (size.width - bubbleBoxRect.width) / 2
-            
-            contentRect.origin.x = (size.width - contentRect.width) / 2
-            contentBoxRect.origin.x = (size.width - contentBoxRect.width) / 2
-            
-        case .left:
-            break
-        }
-        // save
-        let rects: [JCChatViewLayoutItem: CGRect] = [
-            .all: allRect,
-            .card: cardRect,
-            .avatar: avatarRect,
-            .bubble: bubbleRect,
-            .content: contentRect,
-            .tips: tipsRect
-        ]
-        let boxRects: [JCChatViewLayoutItem: CGRect] = [
-            .all: allBoxRect,
-            .card: cardBoxRect,
-            .avatar: avatarBoxRect,
-            .bubble: bubbleBoxRect,
-            .content: contentBoxRect,
-            .tips: tipsBoxRect
-        ]
-        let info = JCChatViewLayoutAttributesInfo(message: message, size: size, rects: rects, boxRects: boxRects)
-        _allLayoutAttributesInfo[message.identifier] = info
-        return info
-    }
-    
-    private func _size(with style: JCMessageStyle, for item: JCChatViewLayoutItem) -> CGSize {
-        let key = "\(style.rawValue)-\(item.rawValue)"
-        if let size = _cachedAllLayoutSize[key] {
-            return size // hit cache
-        }
-        var size: CGSize?
-        if let collectionView = collectionView, let delegate = collectionView.delegate as? JCChatViewLayoutDelegate {
-            switch item {
-            case .all: size = .zero
-            case .card: size = delegate.collectionView?(collectionView, layout: self, sizeForItemCardOf: style)
-            case .avatar: size = delegate.collectionView?(collectionView, layout: self, sizeForItemAvatarOf: style)
-            case .bubble: size = .zero
-            case .content: size = .zero
-            case .tips: size = delegate.collectionView?(collectionView, layout: self, sizeForItemTipsOf: style)
-            }
-        }
-        _cachedAllLayoutSize[key] = size ?? .zero
-        return size ?? .zero
-    }
-    private func _inset(with style: JCMessageStyle, for item: JCChatViewLayoutItem) -> UIEdgeInsets {
-        let key = "\(style.rawValue)-\(item.rawValue)"
-        if let edg = _cachedAllLayoutInset[key] {
-            return edg // hit cache
-        }
-        var edg: UIEdgeInsets?
-        if let collectionView = collectionView, let delegate = collectionView.delegate as? JCChatViewLayoutDelegate {
-            switch item {
-            case .all: edg = delegate.collectionView?(collectionView, layout: self, insetForItemOf: style)
-            case .card: edg = delegate.collectionView?(collectionView, layout: self, insetForItemCardOf: style)
-            case .tips: edg = delegate.collectionView?(collectionView, layout: self, insetForItemTipsOf: style)
-            case .avatar: edg = delegate.collectionView?(collectionView, layout: self, insetForItemAvatarOf: style)
-            case .bubble: edg = delegate.collectionView?(collectionView, layout: self, insetForItemBubbleOf: style)
-            case .content: edg = delegate.collectionView?(collectionView, layout: self, insetForItemContentOf: style)
-            }
-        }
-        _cachedAllLayoutInset[key] = edg ?? .zero
-        return edg ?? .zero
-    }
-    private func _message(at indexPath: IndexPath) -> JCMessageType? {
-        guard let collectionView = collectionView, let delegate = collectionView.delegate as? JCChatViewLayoutDelegate else {
-            return nil
-        }
-        return delegate.collectionView(collectionView, layout: self, itemAt: indexPath)
-    }
-    
-    private func _commonInit() {
-        minimumLineSpacing = 0
-        minimumInteritemSpacing = 0
-    }
-    
-    private lazy var _cachedAllLayoutSize: [String: CGSize] = [:]
-    private lazy var _cachedAllLayoutInset: [String: UIEdgeInsets] = [:]
-    
-    private lazy var _allLayoutAttributesInfo: [UUID: JCChatViewLayoutAttributesInfo] = [:]
-}
-
-@objc public protocol JCChatViewLayoutDelegate: UICollectionViewDelegateFlowLayout {
-    
-    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, itemAt indexPath: IndexPath) -> JCMessageType
-    
-    @objc optional func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemCardOf style: JCMessageStyle) -> CGSize
-    @objc optional func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemTipsOf style: JCMessageStyle) -> CGSize
-    @objc optional func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAvatarOf style: JCMessageStyle) -> CGSize
-    
-    @objc optional func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForItemOf style: JCMessageStyle) -> UIEdgeInsets
-    @objc optional func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForItemCardOf style: JCMessageStyle) -> UIEdgeInsets
-    @objc optional func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForItemTipsOf style: JCMessageStyle) -> UIEdgeInsets
-    @objc optional func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForItemAvatarOf style: JCMessageStyle) -> UIEdgeInsets
-    @objc optional func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForItemBubbleOf style: JCMessageStyle) -> UIEdgeInsets
-    @objc optional func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForItemContentOf style: JCMessageStyle) -> UIEdgeInsets
-}

+ 0 - 40
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCChatViewLayoutAttributes.swift

@@ -1,40 +0,0 @@
-//
-//  JCChatViewLayoutAttributes.swift
-//  JChat
-//
-//  Created by deng on 2017/3/1.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-@objc public enum JCChatViewLayoutItem: Int {
-    case all
-    case card
-    case avatar
-    case bubble
-    case content
-    case tips
-}
-
-@objc open class JCChatViewLayoutAttributes: UICollectionViewLayoutAttributes {
-    
-    public override init() {
-        super.init()
-    }
-    
-    open override func copy(with zone: NSZone? = nil) -> Any {
-        let new = super.copy(with: zone)
-        if let new = new as? JCChatViewLayoutAttributes {
-            new.info = info
-        }
-        return new
-    }
-    
-    open var message: JCMessageType? {
-        return info?.message
-    }
-    
-    open var info: JCChatViewLayoutAttributesInfo?
-}
-

+ 0 - 38
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCChatViewLayoutAttributesInfo.swift

@@ -1,38 +0,0 @@
-//
-//  JCChatViewLayoutAttributesInfo.swift
-//  JChat
-//
-//  Created by deng on 10/04/2017.
-//  Copyright © 2017 HXHG. All rights reserved.
-//
-
-import UIKit
-
-@objc open class JCChatViewLayoutAttributesInfo: NSObject {
-    
-    public init(message: JCMessageType, size: CGSize, rects: [JCChatViewLayoutItem: CGRect], boxRects: [JCChatViewLayoutItem: CGRect]) {
-        _message = message
-        _cacheSize = size
-        _allLayoutedRects = rects
-        _allLayoutedBoxRects = boxRects
-        super.init()
-    }
-    
-    open var message: JCMessageType {
-        return _message
-    }
-    
-    open func layoutedRect(with item: JCChatViewLayoutItem) -> CGRect {
-        return _allLayoutedRects[item] ?? .zero
-    }
-    open func layoutedBoxRect(with item: JCChatViewLayoutItem) -> CGRect {
-        return _allLayoutedBoxRects[item] ?? .zero
-    }
-    
-    private var _message: JCMessageType
-    private var _cacheSize: CGSize
-    
-    private var _allLayoutedRects: [JCChatViewLayoutItem: CGRect]
-    private var _allLayoutedBoxRects: [JCChatViewLayoutItem: CGRect]
-    
-}

+ 0 - 380
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCChatViewUpdate.swift

@@ -1,380 +0,0 @@
-//
-//  JCChatViewUpdate.swift
-//  JChat
-//
-//  Created by deng on 10/04/2017.
-//  Copyright © 2017 HXHG. All rights reserved.
-//
-
-import UIKit
-
-internal enum JCChatViewUpdateChangeItem {
-    case insert(JCMessageType, at: Int)
-    case update(JCMessageType, at: Int)
-    case remove(at: Int)
-    case move(at: Int,  to: Int)
-    
-    var at: Int {
-        switch self {
-        case .insert(_, let at): return at
-        case .update(_, let at): return at
-        case .remove(let at): return at
-        case .move(let at, _): return at
-        }
-    }
-}
-
-internal enum JCChatViewUpdateChange: CustomStringConvertible {
-    
-    case move(from: Int, to: Int)
-    case update(from: Int, to: Int)
-    case insert(from: Int, to: Int)
-    case remove(from: Int, to: Int)
-    
-    var from: Int {
-        switch self {
-        case .move(let from, _): return from
-        case .insert(let from, _): return from
-        case .update(let from, _): return from
-        case .remove(let from, _): return from
-        }
-    }
-    var to: Int {
-        switch self {
-        case .move(_, let to): return to
-        case .insert(_, let to): return to
-        case .update(_, let to): return to
-        case .remove(_, let to): return to
-        }
-    }
-    
-    var isMove: Bool {
-        switch self {
-        case .move: return true
-        default: return false
-        }
-    }
-    var isUpdate: Bool {
-        switch self {
-        case .update: return true
-        default: return false
-        }
-    }
-    var isRemove: Bool {
-        switch self {
-        case .remove: return true
-        default: return false
-        }
-    }
-    var isInsert: Bool {
-        switch self {
-        case .insert: return true
-        default: return false
-        }
-    }
-    
-    
-    var description: String {
-        let from = self.from >= 0 ? "\(self.from)" : "N"
-        let to = self.to >= 0 ? "\(self.to)" : "N"
-        
-        switch self {
-        case .move: return "M\(from)/\(to)"
-        case .insert: return "A\(from)/\(to)"
-        case .update: return "R\(from)/\(to)"
-        case .remove: return "D\(from)/\(to)"
-        }
-    }
-    
-    func offset(_ offset: Int) -> JCChatViewUpdateChange {
-        let from = self.from + offset + max(min(self.from, 0), -1) * offset
-        let to = self.to + offset + max(min(self.to, 0), -1) * offset
-        // convert
-        switch self {
-        case .move: return .move(from: from, to: to)
-        case .insert: return .insert(from: from, to: to)
-        case .update: return .update(from: from, to: to)
-        case .remove: return .remove(from: from, to: to)
-        }
-    }
-}
-
-internal class JCChatViewUpdate: NSObject {
-    
-    
-    internal init(newData: JCChatViewData, oldData: JCChatViewData, updateItems: Array<JCChatViewUpdateChangeItem>) {
-        self.newData = newData
-        self.oldData = oldData
-        self.updateItems = updateItems
-        super.init()
-        self.updateChanges = _computeItemUpdates(newData, oldData, updateItems)
-    }
-    
-    // MARK: compute
-    internal func _computeItemUpdates(_ newData: JCChatViewData, _ oldData: JCChatViewData, _ updateItems: Array<JCChatViewUpdateChangeItem>) -> Array<JCChatViewUpdateChange> {
-        guard !updateItems.isEmpty else {
-            return []
-        }
-        var allInserts: Array<(Int, JCMessageType)> = []
-        var allUpdates: Array<(Int, JCMessageType)> = []
-        var allRemoves: Array<(Int)> = []
-        var allMoves: Array<(Int, Int)> = []
-        
-        // get max & min
-        let (first, last) = updateItems.reduce((.max, .min)) { result, item -> (Int, Int) in
-            
-            switch item {
-            case .move(let from, let to):
-                // ignore for source equ dest
-                guard abs(from - to) >= 1 else {
-                    return result
-                }
-                // move message
-                allMoves.append((from, to))
-                // splite to insert & remove
-                if let message = _element(at: from) {
-                    allRemoves.append((from))
-                    allInserts.append((to + 1, message))
-                }
-                // from + 1: the selected row will change
-                return (min(min(from, to + 1), result.0), max(max(from + 1, to + 1), result.1))
-                
-            case .remove(let index):
-                // remove message
-                allRemoves.append((index))
-                return (min(index, result.0), max(index + 1, result.1))
-                
-            case .update(let message, let index):
-                // update message
-                allUpdates.append((index, message))
-                return (min(index, result.0), max(index + 1, result.1))
-                
-            case .insert(let message, let index):
-                // insert message
-                allInserts.append((index, message))
-                return (min(index, result.0), max(index, result.1))
-            }
-        }
-        // is empty
-        guard first != .max && last != .min else {
-            return []
-        }
-
-        // sort
-//        allInserts.sort { $0.0 < $1.0 }
-//        allUpdates.sort { $0.0 < $1.0 }
-//        allRemoves.sort { $0 < $1 }
-//        allMoves.sort { $0.0 < $1.0 }
-
-        let count = oldData.count
-        let begin = first - 1 // prev
-        let end = last + 1 // next
-        
-        var ii = allInserts.startIndex
-        var iu = allUpdates.startIndex
-        var ir = allRemoves.startIndex
-//        var im = allMoves.startIndex
-        
-        // priority: insert > remove > update > move
-        
-        var items: Array<JCMessageType> = []
-        
-        // processing
-        (first ... last).forEach { index in
-            // do you need to insert the operation?
-            while ii < allInserts.endIndex && allInserts[ii].0 == index {
-                items.append(allInserts[ii].1)
-                ii += 1
-            }
-            // do you need to do this?
-            guard index < last && index < count else {
-                return
-            }
-            // do you need to remove the operation?
-            while ir < allRemoves.endIndex && allRemoves[ir] == index {
-                // adjust previous tl-message & next tl-message, if needed
-                if let content = _element(at: index - 1)?.content as? JCMessageTimeLineContent {
-                    content.after = nil
-                }
-                if let content = _element(at: index + 1)?.content as? JCMessageTimeLineContent {
-                    content.before = nil
-                }
-                // move to next operator(prevent repeat operation)
-                while ir < allRemoves.endIndex && allRemoves[ir] == index {
-                    ir += 1
-                }
-                // can't update or copy
-                return
-            }
-            // do you need to update the operation?
-            while iu < allUpdates.endIndex && allUpdates[iu].0 == index {
-                let message = allUpdates[iu].1
-                // updating
-                items.append(message)
-                // adjust previous tl-message & next tl-message, if needed
-                if let content = _element(at: index - 1)?.content as? JCMessageTimeLineContent {
-                    content.after = message
-                }
-                if let content = _element(at: index + 1)?.content as? JCMessageTimeLineContent {
-                    content.before = message
-                }
-                // move to next operator(prevent repeat operation)
-                while iu < allUpdates.endIndex && allUpdates[iu].0 == index {
-                    iu += 1
-                }
-                // can't copy
-                return
-            }
-            // copy
-            items.append(oldData[index])
-        }
-        // convert messages and replace specify message
-        let newItems = items as [JCMessageType]
-        let convertedItems = _convert(messages: newItems, first: _element(at: begin), last: _element(at: end - 1))
-        let selectedRange = max(begin, 0) ..< min(end, count)
-        let selectedItems = oldData.subarray(with: selectedRange)
-        
-        // compute index paths
-        let start = selectedRange.lowerBound
-        // lcs
-        let diff = _diff(selectedItems, convertedItems).map { $0.offset(start) }
-        // ::
-        // replace
-        newData.elements = oldData.elements
-        newData.replaceSubrange(selectedRange, with: convertedItems)
-        
-        return diff
-    }
-    
-    // MARK: convert message
-    
-    private func _convert(messages elements: [JCMessageType], first: JCMessageType?, last: JCMessageType?) -> [JCMessageType] {
-        // merge
-        let elements = [first].flatMap({ $0 }) + elements + [last].flatMap({ $0 })
-        // processing
-        return (0 ..< elements.count).reduce(NSMutableArray(capacity: elements.count * 2)) { result, index in
-            let current = elements[index]
-            result.add(current)
-            // continue
-            return result
-        } as! [JCMessageType]
-    }
-
-    internal func _element(at index: Int) -> JCMessageType? {
-        guard index >= 0 && index < oldData.count else {
-            return nil
-        }
-        return oldData[index]
-    }
-    
-
-    // MARK: compare
-    private func _equal<T: JCMessageType>(_ lhs: T, _ rhs: T) -> Bool {
-        return lhs.identifier == rhs.identifier && lhs.options.state == rhs.options.state
-    }
-    
-    private func _diff<T: JCMessageType>(_ src: Array<T>, _ dest: Array<T>) -> Array<JCChatViewUpdateChange> {
-        
-        let len1 = src.count
-        let len2 = dest.count
-        
-        var c = [[Int]](repeating: [Int](repeating: 0, count: len2 + 1), count: len1 + 1)
-        
-        // lcs + 动态规划
-        for i in 1 ..< len1 + 1 {
-            for j in 1 ..< len2 + 1 {
-                if _equal(src[i - 1], (dest[j - 1])) {
-                    c[i][j] = c[i - 1][j - 1] + 1
-                } else {
-                    c[i][j] = max(c[i - 1][j], c[i][j - 1])
-                }
-            }
-        }
-        
-        var i = len1
-        var j = len2
-        
-        var rms: Array<(from: Int, to: Int)> = []
-        var adds: Array<(from: Int, to: Int)> = []
-        
-        // create the optimal path
-        repeat {
-            guard i != 0 else {
-                // the remaining is add
-                while j > 0 {
-                    adds.append((from: i - 1, to: j - 1))
-                    j -= 1
-                }
-                break
-            }
-            guard j != 0 else {
-                // the remaining is remove
-                while i > 0 {
-                    rms.append((from: i - 1, to: j - 1))
-                    i -= 1
-                }
-                break
-            }
-            guard !_equal(src[i - 1], (dest[j - 1])) else {
-                // no change, ignore
-                i -= 1
-                j -= 1
-                continue
-            }
-            // check the weight
-            if c[i - 1][j] > c[i][j - 1] {
-                // is remove
-                rms.append((from: i - 1, to: j - 1))
-                i -= 1
-            } else {
-                // is add
-                adds.append((from: i - 1, to: j - 1))
-                j -= 1
-            }
-        } while i > 0 || j > 0
-        
-        var results: Array<JCChatViewUpdateChange> = []
-        results.reserveCapacity(rms.count + adds.count)
-        
-        // move(f,t): f = remove(f), t = insert(t), new move(f,t): f = remove(f), t = insert(f)
-        // update(f,t): f = remove(f), t = insert(t), new update(f,t): f = remove(f), t = insert(f)
-        
-        // automatic merge delete and update items
-        results.append(contentsOf: rms.map({ item in
-            let from = item.from
-            let delElement = src[from]
-            // can't merge to move item?
-            if let addIndex = adds.index(where: { _equal(dest[$0.to], delElement) }) {
-                let addItem = adds.remove(at: addIndex)
-                return .move(from: from, to: addItem.to)
-            }
-            // can't merge to update item?
-            if let addIndex = adds.index(where: { $0.to == from }) {
-                let addItem = adds[addIndex]
-                let addElement = dest[addItem.to]
-                // the same type is allowed to merge
-                if type(of: delElement.content) == type(of: addElement.content) {
-                    adds.remove(at: addIndex)
-                    return .update(from: from, to: addItem.to)
-                }
-            }
-            return .remove(from: item.from, to: -1)
-        }))
-        // automatic merge insert items
-        results.append(contentsOf: adds.map({ item in
-            return .insert(from: -1, to: item.to)
-        }))
-        
-        // sort
-        return results.sorted { $0.from < $1.from }
-    }
-    
-    // MARK: property
-    internal let newData: JCChatViewData
-    internal let oldData: JCChatViewData
-    
-    internal let updateItems: Array<JCChatViewUpdateChangeItem>
-    internal var updateChanges: Array<JCChatViewUpdateChange>?
-    
-    internal static var minimuxTimeInterval: TimeInterval = 60
-}

+ 0 - 232
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCConversationCell.swift

@@ -1,232 +0,0 @@
-//
-//  JCConversationCell.swift
-//  JChat
-//
-//  Created by deng on 2017/3/22.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-import JMessage
-import CocoaLumberjack
-
-class JCConversationCell: JCTableViewCell {
-    
-    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
-        super.init(style: style, reuseIdentifier: reuseIdentifier)
-        _init()
-    }
-    required init?(coder aDecoder: NSCoder) {
-        super.init(coder: aDecoder)
-        _init()
-    }
-    
-    override func awakeFromNib() {
-        super.awakeFromNib()
-        _init()
-    }
-
-    private lazy var avatorView: UIImageView = {
-        let avatorView = UIImageView()
-        avatorView.contentMode = .scaleToFill
-        return avatorView
-    }()
-    private lazy var statueView: UIImageView = UIImageView()
-    private lazy var titleLabel: UILabel = {
-        let titleLabel = UILabel()
-        titleLabel.font = UIFont.systemFont(ofSize: 16)
-        return titleLabel
-    }()
-    private lazy var msgLabel: UILabel = {
-        let msgLabel = UILabel()
-        msgLabel.textColor = UIColor(netHex: 0x808080)
-        msgLabel.font = UIFont.systemFont(ofSize: 14)
-        return msgLabel
-    }()
-    private lazy var dateLabel: UILabel = {
-        let dateLabel = UILabel()
-        dateLabel.textAlignment = .right
-        dateLabel.font = UIFont.systemFont(ofSize: 12)
-        dateLabel.textColor = UIColor(netHex: 0xB3B3B3)
-        return dateLabel
-    }()
-    private lazy var redPoin: UILabel = {
-        let redPoin = UILabel(frame: CGRect(x: 65 - 17, y: 4.5, width: 20, height: 20))
-        redPoin.textAlignment = .center
-        redPoin.font = UIFont.systemFont(ofSize: 11)
-        redPoin.textColor = .white
-        redPoin.layer.backgroundColor = UIColor(netHex: 0xEB424C).cgColor
-        redPoin.textAlignment = .center
-        return redPoin
-    }()
-    
-    //MARK: - public func
-    open func bindConversation(_ conversation: JMSGConversation) {
-        statueView.isHidden = true
-        let isGroup = conversation.ex.isGroup
-        if conversation.unreadCount != nil && (conversation.unreadCount?.intValue)! > 0 {
-            redPoin.isHidden = false
-            var text = ""
-            if (conversation.unreadCount?.intValue)! > 99 {
-                text = "99+"
-                redPoin.layer.cornerRadius = 9.0
-                redPoin.layer.masksToBounds = true
-                redPoin.frame = CGRect(x: 65 - 28, y: 4.5, width: 33, height: 18)
-            } else {
-                redPoin.layer.cornerRadius = 10.0
-                redPoin.layer.masksToBounds = true
-                redPoin.frame = CGRect(x: 65 - 15, y: 4.5, width: 20, height: 20)
-                text = "\(conversation.unreadCount!)"
-            }
-            redPoin.text = text
-            
-            var isNoDisturb = false
-            if isGroup {
-                if let group = conversation.target as? JMSGGroup {
-                    isNoDisturb = group.isNoDisturb
-                }
-            } else {
-                if let user = conversation.target as? JMSGUser {
-                    isNoDisturb = user.isNoDisturb
-                }
-            }
-            
-            if isNoDisturb {
-                redPoin.layer.cornerRadius = 4.0
-                redPoin.layer.masksToBounds = true
-                redPoin.text = ""
-                redPoin.frame = CGRect(x: 65 - 5, y: 4.5, width: 8, height: 8)
-            }
-        } else {
-            redPoin.isHidden = true
-        }
-        
-        if let latestMessage = conversation.latestMessage {
-            let time = latestMessage.timestamp.intValue / 1000
-            let date = Date(timeIntervalSince1970: TimeInterval(time))
-            dateLabel.text = date.conversationDate()
-        } else {
-            dateLabel.text = ""
-        }
-        
-        msgLabel.text = conversation.latestMessageContentText()
-        if isGroup {
-            if let latestMessage = conversation.latestMessage {
-                let fromUser = latestMessage.fromUser
-                if !fromUser.isEqual(to: JMSGUser.myInfo()) &&
-                    latestMessage.contentType != .eventNotification &&
-                    latestMessage.contentType != .prompt {
-                    msgLabel.text = "\(fromUser.displayName()):\(msgLabel.text!)"
-                }
-                if conversation.unreadCount != nil &&
-                    conversation.unreadCount!.intValue > 0 &&
-                    latestMessage.contentType != .prompt {
-                    if latestMessage.isAtAll() {
-                        msgLabel.attributedText = getAttributString(attributString: "[@所有人]", string: msgLabel.text!)
-                    } else if latestMessage.isAtMe() {
-                        msgLabel.attributedText = getAttributString(attributString: "[有人@我]", string: msgLabel.text!)
-                    }
-                }
-            }
-        }
-        
-        if let draft = JCDraft.getDraft(conversation) {
-            if !draft.isEmpty {
-                msgLabel.attributedText = getAttributString(attributString: "[草稿]", string: draft)
-            }
-        }
-
-        if !isGroup {
-            let user = conversation.target as? JMSGUser
-            titleLabel.text = user?.displayName() ?? ""
-            // 处理头像
-            DDLogDebug("更新头像,发送者头像:\(user?.username ?? "")")
-            let urlstr = AppDelegate.o2Collect.generateURLWithAppContextKey(ContactContext.contactsContextKeyV2, query: ContactContext.personIconByNameQueryV2, parameter: ["##name##":user?.username as AnyObject])
-            let url = URL(string: urlstr!)
-            let bound = self.avatorView.bounds
-            if bound.width <= 0 || bound.height <= 0 {
-                self.avatorView.bounds = CGRect(x: 15, y: 7.5, width: 50, height: 50)
-            }
-            self.avatorView.hnk_setImageFromURL(url!)
-
-//            user?.thumbAvatarData { (data, username, error) in
-//                guard let imageData = data else {
-//                    self.avatorView.image = self.userDefaultIcon
-//                    return
-//                }
-//                let image = UIImage(data: imageData)
-//                self.avatorView.image = image
-//            }
-        } else {
-            if let group = conversation.target as? JMSGGroup {
-                titleLabel.text = group.displayName()
-                if group.isShieldMessage {
-                    statueView.isHidden = false
-                }
-                group.thumbAvatarData({ (data, _, error) in
-                    if let data = data {
-                        self.avatorView.image = UIImage(data: data)
-                    } else {
-                        self.avatorView.image = self.groupDefaultIcon
-                    }
-                })
-            }
-        }
-
-        if conversation.ex.isSticky {
-            backgroundColor = UIColor(netHex: 0xF5F6F8)
-        } else {
-            backgroundColor = .white
-        }
-    }
-    
-    func getAttributString(attributString: String, string: String) -> NSMutableAttributedString {
-        let attr = NSMutableAttributedString(string: "")
-        var attrSearchString: NSAttributedString!
-        attrSearchString = NSAttributedString(string: attributString, attributes: [ NSAttributedString.Key.foregroundColor : UIColor(netHex: 0xEB424C), NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 14.0)])
-        attr.append(attrSearchString)
-        attr.append(NSAttributedString(string: string))
-        return attr
-    }
-    
-    private lazy var groupDefaultIcon = UIImage.loadImage("com_icon_group_50")
-    private lazy var userDefaultIcon = UIImage.loadImage("com_icon_user_50")
-    
-    //MARK: - private func
-    private func _init() {
-        avatorView.image = userDefaultIcon
-        statueView.image = UIImage.loadImage("com_icon_shield")
-        
-        contentView.addSubview(avatorView)
-        contentView.addSubview(statueView)
-        contentView.addSubview(titleLabel)
-        contentView.addSubview(msgLabel)
-        contentView.addSubview(dateLabel)
-        contentView.addSubview(redPoin)
-        
-        addConstraint(_JCLayoutConstraintMake(avatorView, .left, .equal, contentView, .left, 15))
-        addConstraint(_JCLayoutConstraintMake(avatorView, .top, .equal, contentView, .top, 7.5))
-        addConstraint(_JCLayoutConstraintMake(avatorView, .width, .equal, nil, .notAnAttribute, 50))
-        addConstraint(_JCLayoutConstraintMake(avatorView, .height, .equal, nil, .notAnAttribute, 50))
-        
-        addConstraint(_JCLayoutConstraintMake(titleLabel, .left, .equal, avatorView, .right, 10.5))
-        addConstraint(_JCLayoutConstraintMake(titleLabel, .top, .equal, contentView, .top, 10.5))
-        addConstraint(_JCLayoutConstraintMake(titleLabel, .right, .equal, dateLabel, .left, -3))
-        addConstraint(_JCLayoutConstraintMake(titleLabel, .height, .equal, nil, .notAnAttribute, 22.5))
-        
-        addConstraint(_JCLayoutConstraintMake(msgLabel, .left, .equal, titleLabel, .left))
-        addConstraint(_JCLayoutConstraintMake(msgLabel, .top, .equal, titleLabel, .bottom, 1.5))
-        addConstraint(_JCLayoutConstraintMake(msgLabel, .right, .equal, statueView, .left, -5))
-        addConstraint(_JCLayoutConstraintMake(msgLabel, .height, .equal, nil, .notAnAttribute, 20))
-        
-        addConstraint(_JCLayoutConstraintMake(dateLabel, .top, .equal, contentView, .top, 16))
-        addConstraint(_JCLayoutConstraintMake(dateLabel, .right, .equal, contentView, .right, -15))
-        addConstraint(_JCLayoutConstraintMake(dateLabel, .height, .equal, nil, .notAnAttribute, 16.5))
-        addConstraint(_JCLayoutConstraintMake(dateLabel, .width, .equal, nil, .notAnAttribute, 100))
-        
-        addConstraint(_JCLayoutConstraintMake(statueView, .top, .equal, dateLabel, .bottom, 7))
-        addConstraint(_JCLayoutConstraintMake(statueView, .right, .equal, contentView, .right, -16))
-        addConstraint(_JCLayoutConstraintMake(statueView, .height, .equal, nil, .notAnAttribute, 12))
-        addConstraint(_JCLayoutConstraintMake(statueView, .width, .equal, nil, .notAnAttribute, 12))
-    }
-}

+ 0 - 78
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCGroupMemberCell.swift

@@ -1,78 +0,0 @@
-//
-//  JCGroupMemberCell.swift
-//  JChat
-//
-//  Created by deng on 2017/5/10.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-import JMessage
-
-class JCGroupMemberCell: UICollectionViewCell {
-    
-    var avator: UIImage? {
-        get {
-            return avatorView.image
-        }
-        set {
-            nickname.text = ""
-            avatorView.image = newValue
-        }
-    }
-    
-    public override init(frame: CGRect) {
-        super.init(frame: frame)
-        _init()
-    }
-    
-    public required init?(coder aDecoder: NSCoder) {
-        super.init(coder: aDecoder)
-        _init()
-    }
-    
-    private var avatorView: UIImageView = UIImageView()
-    private var nickname: UILabel = UILabel()
-    private lazy var userDefaultIcon = UIImage.loadImage("com_icon_user_50")
-    
-    private func _init() {
-        
-        nickname.font = UIFont.systemFont(ofSize: 12)
-        nickname.textAlignment = .center
-        
-        addSubview(avatorView)
-        addSubview(nickname)
-        
-        addConstraint(_JCLayoutConstraintMake(avatorView, .centerY, .equal, contentView, .centerY, -10))
-        addConstraint(_JCLayoutConstraintMake(avatorView, .width, .equal, nil, .notAnAttribute, 50))
-        addConstraint(_JCLayoutConstraintMake(avatorView, .height, .equal, nil, .notAnAttribute, 50))
-        addConstraint(_JCLayoutConstraintMake(avatorView, .centerX, .equal, contentView, .centerX))
-        
-        addConstraint(_JCLayoutConstraintMake(nickname, .centerX, .equal, contentView, .centerX))
-        addConstraint(_JCLayoutConstraintMake(nickname, .width, .equal, nil, .notAnAttribute, 50))
-        addConstraint(_JCLayoutConstraintMake(nickname, .height, .equal, nil, .notAnAttribute, 15))
-        addConstraint(_JCLayoutConstraintMake(nickname, .top, .equal, avatorView, .bottom, 5))
-        
-    }
-    
-    func bindDate(user: JMSGUser) {
-        nickname.text = user.displayName()
-        let urlstr = AppDelegate.o2Collect.generateURLWithAppContextKey(ContactContext.contactsContextKeyV2, query: ContactContext.personIconByNameQueryV2, parameter: ["##name##":user.username as AnyObject])
-        let url = URL(string: urlstr!)
-        let bound = self.avatorView.bounds
-        if bound.width <= 0 || bound.height <= 0 {
-            self.avatorView.bounds = CGRect(x: 0, y: 0, width: 50, height: 50)
-        }
-        self.avatorView.hnk_setImageFromURL(url!)
-        
-//        user.thumbAvatarData { (data, id, error) in
-//            if let data = data {
-//                let image = UIImage(data: data)
-//                self.avatorView.image = image
-//            } else {
-//                self.avatorView.image = self.userDefaultIcon
-//            }
-//        }
-    }
-    
-}

+ 0 - 215
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCGroupSettingCell.swift

@@ -1,215 +0,0 @@
-//
-//  JCGroupSettingCell.swift
-//  JChat
-//
-//  Created by deng on 2017/4/27.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-import JMessage
-
-@objc public protocol JCGroupSettingCellDelegate: NSObjectProtocol {
-    @objc optional func clickMoreButton(clickButton button: UIButton)
-    @objc optional func clickAddCell(cell: JCGroupSettingCell)
-    @objc optional func clickRemoveCell(cell: JCGroupSettingCell)
-    @objc optional func didSelectCell(cell: JCGroupSettingCell, indexPath: IndexPath)
-}
-
-public class JCGroupSettingCell: UITableViewCell {
-    
-    weak var delegate: JCGroupSettingCellDelegate?
-    
-    var group: JMSGGroup!
-    
-    convenience init(style: UITableViewCell.CellStyle, reuseIdentifier: String?, group: JMSGGroup) {
-        self.init(style: style, reuseIdentifier: reuseIdentifier)
-        self.group = group
-        _init()
-    }
-    
-    override public func awakeFromNib() {
-        super.awakeFromNib()
-        _init()
-    }
-
-    private lazy var moreButton: UIButton = UIButton()
-    fileprivate var count = 0
-    fileprivate var sectionCount = 0
-    fileprivate lazy var users: [JMSGUser] = []
-    fileprivate var isMyGroup = false
-    fileprivate var currentUserCount = 0
-
-    private lazy var flowLayout: UICollectionViewFlowLayout = {
-        let flowLayout = UICollectionViewFlowLayout()
-        flowLayout.scrollDirection = .vertical
-        flowLayout.minimumInteritemSpacing = 0
-        flowLayout.minimumLineSpacing = 0
-        return flowLayout
-    }()
-    private lazy var collectionView: UICollectionView = {
-        let collectionView = UICollectionView(frame: CGRect.zero, collectionViewLayout: self.flowLayout)
-        collectionView.delegate = self
-        collectionView.dataSource = self
-        collectionView.register(JCGroupMemberCell.self, forCellWithReuseIdentifier: "JCGroupMemberCell")
-        collectionView.isScrollEnabled = false
-        collectionView.backgroundColor = UIColor.clear
-        return collectionView
-    }()
-    
-    func bindData(_ group: JMSGGroup) {
-        self.group = group
-        _getData()
-        self.collectionView.reloadData()
-    }
-    
-    private func _init() {
-        
-        _getData()
-
-        addSubview(collectionView)
-
-        let showMore = isMyGroup ? count > 13 : count > 14
-        if showMore {
-            moreButton.addTarget(self, action: #selector(_clickMore), for: .touchUpInside)
-            moreButton.setTitleColor(UIColor(netHex: 0x999999), for: .normal)
-            moreButton.titleLabel?.font = UIFont.systemFont(ofSize: 15)
-            moreButton.setTitle("查看更多 >", for: .normal)
-            self.addSubview(moreButton)
-            
-            addConstraint(_JCLayoutConstraintMake(moreButton, .centerX, .equal, self, .centerX))
-            addConstraint(_JCLayoutConstraintMake(moreButton, .width, .equal, self, .width))
-            addConstraint(_JCLayoutConstraintMake(moreButton, .height, .equal, nil, .notAnAttribute, 26))
-            addConstraint(_JCLayoutConstraintMake(moreButton, .bottom, .equal, self, .bottom, -14))
-        }
-        
-        addConstraint(_JCLayoutConstraintMake(collectionView, .left, .equal, self, .left, 15))
-        addConstraint(_JCLayoutConstraintMake(collectionView, .right, .equal, self, .right, -15))
-        addConstraint(_JCLayoutConstraintMake(collectionView, .top, .equal, self, .top))
-        if isMyGroup {
-            if count > 8 {
-                addConstraint(_JCLayoutConstraintMake(collectionView, .height, .equal, nil, .notAnAttribute, 260))
-            } else if count > 3 {
-                addConstraint(_JCLayoutConstraintMake(collectionView, .height, .equal, nil, .notAnAttribute, 200))
-            } else {
-                addConstraint(_JCLayoutConstraintMake(collectionView, .height, .equal, nil, .notAnAttribute, 100))
-            }
-        } else {
-            if count > 9 {
-                addConstraint(_JCLayoutConstraintMake(collectionView, .height, .equal, nil, .notAnAttribute, 260))
-            } else if count > 4 {
-                addConstraint(_JCLayoutConstraintMake(collectionView, .height, .equal, nil, .notAnAttribute, 200))
-            } else {
-                addConstraint(_JCLayoutConstraintMake(collectionView, .height, .equal, nil, .notAnAttribute, 100))
-            }
-        }
-    }
-    
-    @objc func _clickMore() {
-        delegate?.clickMoreButton?(clickButton: moreButton)
-    }
-    
-    fileprivate func _getData() {
-        users = group.memberArray()
-        
-        currentUserCount = users.count
-        
-        let user = JMSGUser.myInfo()
-//        && group.ownerAppKey == user.appKey!  这里group.ownerAppKey == "" 目测sdk bug
-        if group.owner == user.username  {
-            isMyGroup = true
-        }
-        
-        count = users.count
-        
-        if isMyGroup {
-            if count > 13 {
-                currentUserCount = 13
-            }
-            if count > 8 {
-                sectionCount = 3
-            } else if count > 3 {
-                sectionCount = 2
-            } else {
-                sectionCount = 1
-            }
-        } else {
-            if count > 14 {
-                currentUserCount = 14
-            }
-            if count > 9 {
-                sectionCount = 3
-            } else if count > 4 {
-                sectionCount = 2
-            } else {
-                sectionCount = 1
-            }
-        }
-        
-    }
-
-}
-
-extension JCGroupSettingCell: UICollectionViewDelegate, UICollectionViewDataSource {
-    public func numberOfSections(in collectionView: UICollectionView) -> Int {
-        return sectionCount
-    }
-    
-    public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
-        if isMyGroup {
-            if section == 0 {
-                return count >= 3 ? 5 : count + 2
-            }
-            if section == 1 {
-                return  count >= 8 ? 5 : (count - 3)
-            }
-            return count >= 13 ? 5 : count - 8
-        }
-        if section == 0 {
-            return count >= 4 ? 5 : count + 1
-        }
-        if section == 1 {
-            return  count >= 9 ? 5 : (count - 4)
-        }
-        return count >= 14 ? 5 : count - 9
-    }
-    
-    func collectionView(_ collectionView: UICollectionView,
-                        layout collectionViewLayout: UICollectionViewLayout,
-                        sizeForItemAtIndexPath indexPath: IndexPath) -> CGSize {
-        return CGSize(width:Int(collectionView.frame.size.width / 5), height: Int(collectionView.frame.size.height / CGFloat(sectionCount)))
-    }
-
-    public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
-        return collectionView.dequeueReusableCell(withReuseIdentifier: "JCGroupMemberCell", for: indexPath)
-    }
-    
-    public func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
-        guard let cell = cell as? JCGroupMemberCell else {
-            return
-        }
-        let index = indexPath.section * 5 + indexPath.row
-        if index == currentUserCount {
-            cell.avator = UIImage.loadImage("com_icon_single_add")
-            return
-        }
-        if index == currentUserCount + 1 {
-            cell.avator = UIImage.loadImage("com_icon_remove")
-            return
-        }
-        cell.bindDate(user: users[index])
-    }
-    
-    public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
-        let index = indexPath.section * 5 + indexPath.row
-        if index == currentUserCount {
-            delegate?.clickAddCell?(cell: self)
-            return
-        }
-        if index == currentUserCount + 1 {
-            delegate?.clickRemoveCell?(cell: self)
-            return
-        }
-        delegate?.didSelectCell?(cell: self, indexPath: indexPath)
-    }
-}

+ 0 - 74
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCMessageAvatarView.swift

@@ -1,74 +0,0 @@
-//
-//  JCMessageAvatarView.swift
-//  JChat
-//
-//  Created by deng on 10/04/2017.
-//  Copyright © 2017 HXHG. All rights reserved.
-//
-
-import UIKit
-
-open class JCMessageAvatarView: UIImageView, JCMessageContentViewType {
-    
-    weak var delegate: JCMessageDelegate?
-    
-    public override init(image: UIImage?) {
-        super.init(image: image)
-        _commonInit()
-    }
-    public override init(image: UIImage?, highlightedImage: UIImage?) {
-        super.init(image: image, highlightedImage: highlightedImage)
-        _commonInit()
-    }
-    public override init(frame: CGRect) {
-        super.init(frame: frame)
-        _commonInit()
-    }
-    public required init?(coder aDecoder: NSCoder) {
-        super.init(coder: aDecoder)
-        _commonInit()
-    }
-    
-    open func apply(_ message: JCMessageType) {
-        self.message = message
-        if message.senderAvator != nil {
-            image = message.senderAvator
-            return
-        }
-        weak var weakSelf = self
-        message.sender?.thumbAvatarData({ (data, id, error) in
-            if let data = data {
-                weakSelf?.image = UIImage(data: data)
-            } else {
-                self.image = self.userDefaultIcon
-            }
-        })
-    }
-    
-    private var message: JCMessageType!
-    private lazy var userDefaultIcon = UIImage.loadImage("com_icon_user_36")
-    
-    private func _commonInit() {
-        image = userDefaultIcon
-        isUserInteractionEnabled = true
-        layer.masksToBounds = true
-
-        let tapGR = UITapGestureRecognizer(target: self, action: #selector(_tapHandler))
-        self.addGestureRecognizer(tapGR)
-
-        let longTapGesture = UILongPressGestureRecognizer(target: self, action: #selector(_longTap(_:)))
-        longTapGesture.minimumPressDuration = 0.4
-        addGestureRecognizer(longTapGesture)
-    }
-    
-    @objc func _tapHandler(sender:UITapGestureRecognizer) {
-        delegate?.tapAvatarView?(message: message)
-    }
-
-    @objc func _longTap(_ gestureRecognizer: UILongPressGestureRecognizer)  {
-        if gestureRecognizer.state == .began {
-            delegate?.longTapAvatarView?(message: message)
-        }
-    }
-
-}

+ 0 - 32
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCMessageCardView.swift

@@ -1,32 +0,0 @@
-//
-//  JCMessageCardView.swift
-//  JChat
-//
-//  Created by deng on 10/04/2017.
-//  Copyright © 2017 HXHG. All rights reserved.
-//
-
-import UIKit
-
-open class JCMessageCardView: UILabel, JCMessageContentViewType {
-    
-    public override init(frame: CGRect) {
-        super.init(frame: frame)
-        _commonInit()
-    }
-    public required init?(coder aDecoder: NSCoder) {
-        super.init(coder: aDecoder)
-        _commonInit()
-    }
-    
-    open func apply(_ message: JCMessageType) {
-        let isRight = message.options.alignment == .right
-        text = message.name
-        textAlignment = isRight ? .right : .left
-    }
-    
-    private func _commonInit() {
-        font = UIFont.systemFont(ofSize: 14)
-        textColor = UIColor(netHex: 0xB3B3B3)
-    }
-}

+ 0 - 114
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCMessageTipsView.swift

@@ -1,114 +0,0 @@
-//
-//  JCMessageTipsView.swift
-//  JChat
-//
-//  Created by deng on 2017/4/26.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-open class JCMessageTipsView: UIView, JCMessageContentViewType {
-    
-    weak var delegate: JCMessageDelegate?
-    
-    public override init(frame: CGRect) {
-        super.init(frame: frame)
-        _commonInit()
-    }
-    public required init?(coder aDecoder: NSCoder) {
-        super.init(coder: aDecoder)
-        _commonInit()
-    }
-    
-    open func apply(_ message: JCMessageType) {
-        self.message = message
-        switch message.options.state {
-        case .sending:
-            errorInfoView.isHidden = true
-            activityView.startAnimating()
-        case .sendSucceed:
-            errorInfoView.isHidden = true
-            activityView.stopAnimating()
-        case .sendError:
-            activityView.stopAnimating()
-            errorInfoView.isHidden = false
-        default:
-            activityView.stopAnimating()
-        }
-        if message.content is JCMessageImageContent {
-            activityView.stopAnimating()
-            activityView.isHidden = true
-        }
-
-        #if READ_VERSION
-        if activityView.isHidden && errorInfoView.isHidden && message.options.alignment == .right {
-            unreadCountTips.isHidden = false
-            if message.unreadCount > 0 {
-                unreadCountTips.isEnabled = true
-                unreadCountTips.setTitleColor(UIColor(netHex: 0x2DD0CF), for: .normal)
-                if message.targetType == .single {
-                    unreadCountTips.isEnabled = false
-                    unreadCountTips.setTitle("未读", for: .normal)
-                } else {
-                    unreadCountTips.setTitle("\(message.unreadCount)人未读", for: .normal)
-                }
-            } else {
-                unreadCountTips.isEnabled = false
-                unreadCountTips.setTitleColor(UIColor(netHex: 0x999999), for: .normal)
-                if message.targetType == .single {
-                    unreadCountTips.setTitle("已读", for: .normal)
-                } else {
-                    unreadCountTips.setTitle("全部已读", for: .normal)
-                }
-            }
-        } else {
-            unreadCountTips.isHidden = true
-        }
-        #endif
-    }
-    
-    private lazy var activityView: UIActivityIndicatorView = {
-        let activityView = UIActivityIndicatorView(frame: CGRect(x: 100 - 15, y: 5, width: 10, height: 10))
-        activityView.style = .gray
-        activityView.isUserInteractionEnabled = false
-        return activityView
-    }()
-    private lazy var errorInfoView: UIImageView = {
-        let image = UIImage.loadImage("com_icon_send_error")
-        let errorInfoView = UIImageView(frame: CGRect(x: 100 - 21, y: 0, width: 21, height: 21))
-        errorInfoView.isUserInteractionEnabled = true
-        errorInfoView.image = image
-        errorInfoView.isHidden = true
-        return errorInfoView
-    }()
-    private lazy var unreadCountTips: UIButton = {
-        let unreadCountTips = UIButton(frame: CGRect(x: 0, y: 0, width: 95, height: 21))
-        unreadCountTips.addTarget(self, action: #selector(_clickUnreadCount), for: .touchUpInside)
-        unreadCountTips.setTitle("未读", for: .normal)
-        unreadCountTips.titleLabel?.font = UIFont.systemFont(ofSize: 12)
-        unreadCountTips.setTitleColor(UIColor(netHex: 0x2DD0CF), for: .normal)
-        unreadCountTips.isHidden = true
-        unreadCountTips.contentHorizontalAlignment = .right
-        return unreadCountTips
-    }()
-    private var message: JCMessageType!
-    
-    private func _commonInit() {
-        addSubview(activityView)
-        let tapGR = UITapGestureRecognizer(target: self, action: #selector(_tapHandler))
-        errorInfoView.addGestureRecognizer(tapGR)
-        addSubview(errorInfoView)
-        #if READ_VERSION
-        addSubview(unreadCountTips)
-        #endif
-    }
-    
-    func _clickUnreadCount() {
-        delegate?.tapUnreadTips?(message: message)
-    }
-    
-    func _tapHandler(sender: UITapGestureRecognizer) {
-        delegate?.clickTips?(message: message)
-    }
-}

+ 0 - 56
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCNetworkTipsCell.swift

@@ -1,56 +0,0 @@
-//
-//  JCNetworkTipsCell.swift
-//  JChat
-//
-//  Created by deng on 2017/6/12.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-class JCNetworkTipsCell: UITableViewCell {
-
-    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
-        super.init(style: style, reuseIdentifier: reuseIdentifier)
-        _init()
-    }
-    required init?(coder aDecoder: NSCoder) {
-        super.init(coder: aDecoder)
-        _init()
-    }
-    
-    override func awakeFromNib() {
-        super.awakeFromNib()
-        _init()
-    }
-    
-    private lazy var statueView: UIImageView = {
-        let statueView = UIImageView()
-        statueView.image = UIImage.loadImage("com_icon_send_error")
-        return statueView
-    }()
-    private lazy var tipsLabel: UILabel = {
-        let tipsLabel = UILabel()
-        tipsLabel.text = "当前网络不可用,请检查您的网络设置"
-        tipsLabel.font = UIFont.systemFont(ofSize: 14)
-        return tipsLabel
-    }()
-    
-    //MARK: - private func
-    private func _init() {
-        backgroundColor = UIColor(netHex: 0xFFDFE0)
-
-        contentView.addSubview(statueView)
-        contentView.addSubview(tipsLabel)
-        
-        addConstraint(_JCLayoutConstraintMake(tipsLabel, .left, .equal, statueView, .right, 11.5))
-        addConstraint(_JCLayoutConstraintMake(tipsLabel, .centerY, .equal, contentView, .centerY))
-        addConstraint(_JCLayoutConstraintMake(tipsLabel, .right, .equal, contentView, .right))
-        addConstraint(_JCLayoutConstraintMake(tipsLabel, .height, .equal, contentView, .height))
-
-        addConstraint(_JCLayoutConstraintMake(statueView, .centerY, .equal, contentView, .centerY))
-        addConstraint(_JCLayoutConstraintMake(statueView, .left, .equal, contentView, .left, 15))
-        addConstraint(_JCLayoutConstraintMake(statueView, .height, .equal, nil, .notAnAttribute, 21))
-        addConstraint(_JCLayoutConstraintMake(statueView, .width, .equal, nil, .notAnAttribute, 21))
-    }
-}

+ 0 - 101
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCSelectMemberCell.swift

@@ -1,101 +0,0 @@
-//
-//  JCSelectMemberCell.swift
-//  JChat
-//
-//  Created by deng on 2017/5/11.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-import JMessage
-
-class JCSelectMemberCell: UITableViewCell {
-
-    var icon: UIImage? {
-        get {
-            return avatorView.image
-        }
-        set {
-            avatorView.image = newValue
-        }
-    }
-    
-    var selectIcon: UIImage? {
-        get {
-            return selectIconView.image
-        }
-        set {
-            selectIconView.image = newValue
-        }
-    }
-    
-    var title: String? {
-        get {
-            return usernameLabel.text
-        }
-        set {
-            usernameLabel.text = newValue
-        }
-    }
-    
-    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
-        super.init(style: style, reuseIdentifier: reuseIdentifier)
-        _init()
-    }
-    required init?(coder aDecoder: NSCoder) {
-        super.init(coder: aDecoder)
-        _init()
-    }
-    
-    override func awakeFromNib() {
-        super.awakeFromNib()
-        _init()
-    }
-    
-    private lazy var avatorView: UIImageView = UIImageView()
-    private lazy var usernameLabel: UILabel = UILabel()
-    private lazy var selectIconView: UIImageView = UIImageView()
-    
-    public func bindDate(_ user : JMSGUser) {
-        title = user.displayName()
-        icon = UIImage.loadImage("com_icon_user_36")
-        user.thumbAvatarData({ (data, name, error) in
-            if data != nil {
-                let image = UIImage(data: data!)
-                self.icon = image
-            }
-        })
-    }
-    
-    //MARK: - private func
-    private func _init() {
-        
-        let image = UIImage.loadImage("com_icon_unselect")
-        
-        selectIconView.image = image
-        
-        usernameLabel.textColor = UIColor(netHex: 0x2c2c2c)
-        usernameLabel.font = UIFont.systemFont(ofSize: 14)
-        
-        contentView.addSubview(selectIconView)
-        contentView.addSubview(avatorView)
-        contentView.addSubview(usernameLabel)
-        
-        addConstraint(_JCLayoutConstraintMake(selectIconView, .left, .equal, contentView, .left, 15))
-        addConstraint(_JCLayoutConstraintMake(selectIconView, .centerY, .equal, contentView, .centerY))
-        addConstraint(_JCLayoutConstraintMake(selectIconView, .width, .equal, nil, .notAnAttribute, 20))
-        addConstraint(_JCLayoutConstraintMake(selectIconView, .height, .equal, nil, .notAnAttribute, 20))
-        
-        addConstraint(_JCLayoutConstraintMake(avatorView, .left, .equal, selectIconView, .right, 15))
-        addConstraint(_JCLayoutConstraintMake(avatorView, .top, .equal, contentView, .top, 9.5))
-        addConstraint(_JCLayoutConstraintMake(avatorView, .width, .equal, nil, .notAnAttribute, 36))
-        addConstraint(_JCLayoutConstraintMake(avatorView, .height, .equal, nil, .notAnAttribute, 36))
-        
-        addConstraint(_JCLayoutConstraintMake(usernameLabel, .left, .equal, avatorView, .right, 11))
-        addConstraint(_JCLayoutConstraintMake(usernameLabel, .top, .equal, contentView, .top, 19.5))
-        addConstraint(_JCLayoutConstraintMake(usernameLabel, .right, .equal, contentView, .right, -15))
-        addConstraint(_JCLayoutConstraintMake(usernameLabel, .height, .equal, nil, .notAnAttribute, 16))
-        
-    }
-
-}

+ 0 - 90
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCSingleSettingCell.swift

@@ -1,90 +0,0 @@
-//
-//  JCSingleSettingCell.swift
-//  JChat
-//
-//  Created by deng on 2017/4/27.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-@objc public protocol JCSingleSettingCellDelegate: NSObjectProtocol {
-    @objc optional func singleSettingCell(clickAddButton button: UIButton)
-    @objc optional func singleSettingCell(clickAvatorButton button: UIButton)
-}
-
-class JCSingleSettingCell: UITableViewCell {
-
-    weak var delegate: JCSingleSettingCellDelegate?
-
-    required init?(coder aDecoder: NSCoder) {
-        super.init(coder: aDecoder)
-        _init()
-    }
-    
-    override func awakeFromNib() {
-        super.awakeFromNib()
-        _init()
-    }
-    
-    private lazy var avatorButton: UIButton = {
-        let avatorButton = UIButton()
-        avatorButton.setBackgroundImage(UIImage.loadImage("com_icon_user_50"), for: .normal)
-        avatorButton.addTarget(self, action: #selector(_clickAvator), for: .touchUpInside)
-        return avatorButton
-    }()
-    private lazy var addButton: UIButton = {
-        let addButton = UIButton()
-        addButton.setBackgroundImage(UIImage.loadImage("com_icon_single_add"), for: .normal)
-        addButton.setBackgroundImage(UIImage.loadImage("com_icon_single_add_per"), for: .highlighted)
-        addButton.addTarget(self, action: #selector(_clickAdd), for: .touchUpInside)
-        return addButton
-    }()
-    private lazy var nickname: UILabel = {
-        let nickname = UILabel()
-        nickname.font = UIFont.systemFont(ofSize: 12)
-        nickname.textAlignment = .center
-        nickname.textColor = UIColor(netHex: 0x2C2C2C)
-        return nickname
-    }()
-    
-    func bindData(_ user: JMSGUser) {
-        nickname.text = user.displayName()
-        user.thumbAvatarData { (data, id, error) in
-            if data != nil {
-                let image = UIImage(data: data!)
-                self.avatorButton.setBackgroundImage(image, for: .normal)
-            }
-        }
-    }
-    
-    private func _init() {
-        contentView.addSubview(avatorButton)
-        //contentView.addSubview(addButton)
-        contentView.addSubview(nickname)
-        
-        addConstraint(_JCLayoutConstraintMake(avatorButton, .left, .equal, contentView, .left, 20))
-        addConstraint(_JCLayoutConstraintMake(avatorButton, .width, .equal, nil, .notAnAttribute, 50))
-        addConstraint(_JCLayoutConstraintMake(avatorButton, .height, .equal, nil, .notAnAttribute, 50))
-        addConstraint(_JCLayoutConstraintMake(avatorButton, .top, .equal, contentView, .top, 16.5))
-        
-        addConstraint(_JCLayoutConstraintMake(nickname, .left, .equal, avatorButton, .left))
-        addConstraint(_JCLayoutConstraintMake(nickname, .width, .equal, avatorButton, .width))
-        addConstraint(_JCLayoutConstraintMake(nickname, .height, .equal, nil, .notAnAttribute, 16.5))
-        addConstraint(_JCLayoutConstraintMake(nickname, .top, .equal, avatorButton, .bottom, 3))
-        
-//        addConstraint(_JCLayoutConstraintMake(addButton, .left, .equal, avatorButton, .right, 20))
-//        addConstraint(_JCLayoutConstraintMake(addButton, .width, .equal, nil, .notAnAttribute, 50))
-//        addConstraint(_JCLayoutConstraintMake(addButton, .height, .equal, nil, .notAnAttribute, 50))
-//        addConstraint(_JCLayoutConstraintMake(addButton, .top, .equal, contentView, .top, 16.5))
-    }
-    
-    @objc func _clickAvator() {
-        delegate?.singleSettingCell?(clickAvatorButton: avatorButton)
-    }
-    
-    @objc func _clickAdd() {
-        delegate?.singleSettingCell?(clickAddButton: addButton)
-    }
-
-}

+ 0 - 58
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/JCUpdateMemberCell.swift

@@ -1,58 +0,0 @@
-//
-//  JCUpdateMemberCell.swift
-//  JChat
-//
-//  Created by deng on 2017/5/11.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-import JMessage
-
-class JCUpdateMemberCell: UICollectionViewCell {
-    var avator: UIImage? {
-        get {
-            return avatorView.image
-        }
-        set {
-            avatorView.image = newValue
-        }
-    }
-    
-    public override init(frame: CGRect) {
-        super.init(frame: frame)
-        _init()
-    }
-    
-    public required init?(coder aDecoder: NSCoder) {
-        super.init(coder: aDecoder)
-        _init()
-    }
-    
-    private var avatorView: UIImageView = UIImageView()
-    private lazy var defaultUserIcon = UIImage.loadImage("com_icon_user_36")
-    
-    private func _init() {
-        
-        avatorView.image = defaultUserIcon
-
-        addSubview(avatorView)
-        
-        addConstraint(_JCLayoutConstraintMake(avatorView, .centerY, .equal, contentView, .centerY))
-        addConstraint(_JCLayoutConstraintMake(avatorView, .width, .equal, nil, .notAnAttribute, 36))
-        addConstraint(_JCLayoutConstraintMake(avatorView, .height, .equal, nil, .notAnAttribute, 36))
-        addConstraint(_JCLayoutConstraintMake(avatorView, .centerX, .equal, contentView, .centerX))
-        
-    }
-    
-    func bindDate(user: JMSGUser) {
-        user.thumbAvatarData { (data, id, error) in
-            if let data = data {
-                let image = UIImage(data: data)
-                self.avatorView.image = image
-            } else {
-                self.avatorView.image = self.defaultUserIcon
-            }
-        }
-    }
-}

+ 0 - 83
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JACMessageImageContentView.swift

@@ -1,83 +0,0 @@
-//
-//  JCMessageImageContentView.swift
-//  JChat
-//
-//  Created by deng on 2017/3/9.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-open class JCMessageImageContentView: UIImageView, JCMessageContentViewType {
-    
-    public override init(image: UIImage?) {
-        super.init(image: image)
-        _commonInit()
-    }
-    public override init(image: UIImage?, highlightedImage: UIImage?) {
-        super.init(image: image, highlightedImage: highlightedImage)
-        _commonInit()
-    }
-    public override init(frame: CGRect) {
-        super.init(frame: frame)
-        _commonInit()
-    }
-    public required init?(coder aDecoder: NSCoder) {
-        super.init(coder: aDecoder)
-        _commonInit()
-    }
-
-    open func apply(_ message: JCMessageType) {
-        _message = message
-        weak var weakSelf = self
-        guard let content = message.content as? JCMessageImageContent else {
-            return
-        } 
-        image = content.image
-        _delegate = content.delegate
-        percentLabel.frame = CGRect(x: 0, y: 0, width: self.width, height: self.height)
-        if message.options.state == .sending {
-            percentLabel.backgroundColor = UIColor.black.withAlphaComponent(0.3)
-            percentLabel.isHidden = false
-            percentLabel.textColor = .white
-            content.upload = {  (percent:Float) -> Void in
-                DispatchQueue.main.async {
-                    let p = Int(percent * 100)
-                    weakSelf?.percentLabel.text = "\(p)%"
-                    if percent == 1.0 {
-                        weakSelf?.percentLabel.isHidden = true
-                        weakSelf?.percentLabel.text = ""
-                    }
-                }
-            }
-        } else {
-            percentLabel.textColor = .clear
-            percentLabel.backgroundColor = .clear
-        }
-    }
-    
-    private weak var _delegate: JCMessageDelegate?
-    private var _message: JCMessageType!
-    
-    private lazy var percentLabel: UILabel = {
-        var percentLabel = UILabel(frame: CGRect(x: 20, y: 40, width: 50, height: 20))
-        percentLabel.isUserInteractionEnabled = false
-        percentLabel.textAlignment = .center
-        percentLabel.textColor = .white
-        percentLabel.font = UIFont.systemFont(ofSize: 17)
-        return percentLabel
-    }()
-    
-    private func _commonInit() {
-        let tapGR = UITapGestureRecognizer(target: self, action: #selector(_tapHandler))
-        addGestureRecognizer(tapGR)
-        isUserInteractionEnabled = true
-        layer.cornerRadius = 2
-        layer.masksToBounds = true
-        addSubview(percentLabel)
-    }
-    
-    @objc func _tapHandler(sender:UITapGestureRecognizer) {
-        _delegate?.message?(message: _message, image: image)
-    }
-}

+ 0 - 27
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCBusinessCardContent.swift

@@ -1,27 +0,0 @@
-//
-//  JCBusinessCardContent.swift
-//  JChat
-//
-//  Created by 邓永豪 on 2017/8/31.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-class JCBusinessCardContent: NSObject, JCMessageContentType {
-
-    public weak var delegate: JCMessageDelegate?
-    open var layoutMargins: UIEdgeInsets = .zero
-    
-    open class var viewType: JCMessageContentViewType.Type {
-        return JCBusinessCardContentView.self
-    }
-    
-    open var userName: String?
-    open var appKey: String?
-    
-    open func sizeThatFits(_ size: CGSize) -> CGSize {
-        return .init(width: 200, height: 87)
-    }
-
-}

+ 0 - 125
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCBusinessCardContentView.swift

@@ -1,125 +0,0 @@
-//
-//  JCBusinessCardContentView.swift
-//  JChat
-//
-//  Created by 邓永豪 on 2017/8/31.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-class JCBusinessCardContentView: UIView, JCMessageContentViewType {
-
-    public override init(frame: CGRect) {
-        super.init(frame: frame)
-        _commonInit()
-    }
-    public required init?(coder aDecoder: NSCoder) {
-        super.init(coder: aDecoder)
-        _commonInit()
-    }
-    
-    open func apply(_ message: JCMessageType) {
-        guard let content = message.content as? JCBusinessCardContent else {
-            return
-        }
-        
-        _message = message
-        _delegate = content.delegate
-        _userName = content.userName
-        _appKey = content.appKey
-        
-        userNameLabel.text = "用户名:\(String(describing: _userName!))"
-        
-        if let userName = _userName {
-            JMSGUser.userInfoArray(withUsernameArray: [userName], completionHandler: { (result, error) in
-                let users = result as? [JMSGUser]
-                guard let user = users?.first else {
-                    return
-                }
-                self._user = user
-
-                if user.nickname != nil && !user.nickname!.isEmpty {
-                    self.nickNameLabel.text = user.nickname
-                    self.nickNameLabel.frame = CGRect(x: 62, y: 11.5, width: 126, height: 22.5)
-                } else {
-                    self.userNameLabel.text = ""
-                    self.nickNameLabel.text = user.username
-                    self.nickNameLabel.frame = CGRect(x: 62, y: 22.5, width: 126, height: 22.5)
-                }
-
-                user.thumbAvatarData({ (data, msgId, error) in
-                    if let data = data {
-                        self.imageView.image = UIImage(data: data)
-                    } else {
-                        self.imageView.image = UIImage.loadImage("com_icon_user_40")
-                    }
-                })
-            })
-        }
-    }
-    
-    
-    private weak var _delegate: JCMessageDelegate?
-    
-    private var _userName: String?
-    private var _appKey: String?
-    private var _nickname: String?
-    private var _message: JCMessageType!
-    private var _user: JMSGUser?
-    
-    private lazy var imageView: UIImageView = {
-        let imageView = UIImageView(frame: CGRect(x: 12, y: 13.5, width: 40, height: 40))
-        imageView.image = UIImage.loadImage("com_icon_user_40")
-        return imageView
-    }()
-    private lazy var line: UILabel = {
-        let line = UILabel()
-        line.frame = CGRect(x: 10, y: 66, width: 180, height: 1)
-        line.layer.backgroundColor = UIColor(netHex: 0xE8E8E8).cgColor
-        return line
-    }()
-    private lazy var userNameLabel: UILabel = {
-        let userNameLabel = UILabel()
-        userNameLabel.frame = CGRect(x: 62, y: 37, width: 126, height: 20)
-        userNameLabel.font = UIFont.systemFont(ofSize: 14)
-        userNameLabel.textColor = UIColor(netHex: 0x999999)
-        return userNameLabel
-    }()
-    private lazy var nickNameLabel: UILabel = {
-        let nickNameLabel = UILabel()
-        nickNameLabel.frame = CGRect(x: 62, y: 11.5, width: 126, height: 22.5)
-        nickNameLabel.font = UIFont.systemFont(ofSize: 16)
-        nickNameLabel.textColor = .black
-        return nickNameLabel
-    }()
-    private lazy var tipsLabel: UILabel = {
-        let tipsLabel = UILabel()
-        tipsLabel.frame = CGRect(x: 12, y: 69.5, width: 100, height: 14)
-        tipsLabel.font = UIFont.systemFont(ofSize: 10)
-        tipsLabel.textColor = UIColor(netHex: 0x989898)
-        tipsLabel.text = "个人名片"
-        return tipsLabel
-    }()
-    
-    private func _commonInit() {
-        _tapGesture()
-
-        addSubview(imageView)
-        addSubview(nickNameLabel)
-        addSubview(userNameLabel)
-        addSubview(tipsLabel)
-        addSubview(line)
-    }
-    
-    func _tapGesture() {
-        let tap = UITapGestureRecognizer(target: self, action: #selector(_clickCell))
-        tap.numberOfTapsRequired = 1
-        addGestureRecognizer(tap)
-    }
-    
-    @objc func _clickCell() {
-        _delegate?.message?(message: _message, user: _user, businessCardName: _userName!, businessCardAppKey: _appKey!)
-    }
-
-}

+ 0 - 28
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageFileContent.swift

@@ -1,28 +0,0 @@
-//
-//  JCMessageFileContent.swift
-//  JChat
-//
-//  Created by deng on 2017/7/20.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-class JCMessageFileContent: NSObject, JCMessageContentType {
-
-    public weak var delegate: JCMessageDelegate?
-    open var layoutMargins: UIEdgeInsets = .zero
-    
-    open class var viewType: JCMessageContentViewType.Type {
-        return JCMessageFileContentView.self
-    }
-    
-    open var data: Data?
-    open var fileName: String?
-    open var fileType: String?
-    open var fileSize: String?
-    
-    open func sizeThatFits(_ size: CGSize) -> CGSize {
-        return .init(width: 200, height: 95)
-    }
-}

+ 0 - 127
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageFileContentView.swift

@@ -1,127 +0,0 @@
-//
-//  JCMessageFileContentView.swift
-//  JChat
-//
-//  Created by deng on 2017/7/20.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-class JCMessageFileContentView: UIView, JCMessageContentViewType {
-    
-    public override init(frame: CGRect) {
-        super.init(frame: frame)
-        _commonInit()
-    }
-    public required init?(coder aDecoder: NSCoder) {
-        super.init(coder: aDecoder)
-        _commonInit()
-    }
-    
-    open func apply(_ message: JCMessageType) {
-        guard let content = message.content as? JCMessageFileContent else {
-            return
-        }
-        _message = message
-        _delegate = content.delegate
-        _fileData = content.data
-        _fileName = content.fileName
-        _fileType = content.fileType
-        _fileSize = content.fileSize
-        
-        _updateFileTypeIcon(_fileType)
-
-        fileNameLabel.text = _fileName
-        fileSizeLabel.text = _fileSize
-        if _fileData != nil {
-            fileStatusLabel.text = "己下载"
-        } else {
-            fileStatusLabel.text = "未下载"
-        }
-    }
-    
-    private func _updateFileTypeIcon(_ fileType: String?) {
-        if let type = fileType {
-            switch type.fileFormat() {
-            case .document:
-                imageView.image = UIImage.loadImage("com_icon_file_file")
-            case .video:
-                imageView.image = UIImage.loadImage("com_icon_file_video")
-            case .photo:
-                imageView.image = UIImage.loadImage("com_icon_file_photo")
-            case .voice:
-                imageView.image = UIImage.loadImage("com_icon_file_music")
-            default:
-                imageView.image = UIImage.loadImage("com_icon_file_other")
-            }
-        } else {
-            imageView.image = UIImage.loadImage("com_icon_file_other")
-        }
-    }
-    
-    private weak var _delegate: JCMessageDelegate?
-    
-    private var _fileData: Data?
-    private var _fileName: String?
-    private var _fileType: String?
-    private var _fileSize: String?
-    private var _message: JCMessageType!
-    
-    private lazy var imageView: UIImageView = {
-        let imageView = UIImageView(frame: CGRect(x: 12, y: 18, width: 40, height: 40))
-        imageView.layer.cornerRadius = 2.5
-        imageView.layer.masksToBounds = true
-        return imageView
-    }()
-    private lazy var line: UILabel = {
-        let line = UILabel()
-        line.frame = CGRect(x: 12, y: 74, width: 176, height: 1)
-        line.backgroundColor = UIColor(netHex: 0xE8E8E8)
-        line.layer.backgroundColor = UIColor(netHex: 0xE8E8E8).cgColor
-        return line
-    }()
-    private lazy var fileNameLabel: UILabel = {
-        let fileNameLabel = UILabel()
-        fileNameLabel.frame = CGRect(x: 68, y: 18, width: 120, height: 40)
-        fileNameLabel.numberOfLines = 0
-        fileNameLabel.font = UIFont.systemFont(ofSize: 16)
-        fileNameLabel.textColor = UIColor(netHex: 0x5a5a5a)
-        return fileNameLabel
-    }()
-    private lazy var fileSizeLabel: UILabel = {
-        let fileSizeLabel = UILabel()
-        fileSizeLabel.frame = CGRect(x: 12, y: 75, width: 85, height: 20)
-        fileSizeLabel.font = UIFont.systemFont(ofSize: 12)
-        fileSizeLabel.textColor = UIColor(netHex: 0x989898)
-        return fileSizeLabel
-    }()
-    private lazy var fileStatusLabel: UILabel = {
-        let fileStatusLabel = UILabel()
-        fileStatusLabel.frame = CGRect(x: 103, y: 75, width: 85, height: 20)
-        fileStatusLabel.textAlignment = .right
-        fileStatusLabel.font = UIFont.systemFont(ofSize: 12)
-        fileStatusLabel.textColor = UIColor(netHex: 0x989898)
-        return fileStatusLabel
-    }()
-    
-    private func _commonInit() {
-        _tapGesture()
-
-        addSubview(imageView)
-        addSubview(fileNameLabel)
-        addSubview(fileStatusLabel)
-        addSubview(fileSizeLabel)
-        addSubview(line)
-    }
-    
-    func _tapGesture() {
-        let tap = UITapGestureRecognizer(target: self, action: #selector(_clickCell))
-        tap.numberOfTapsRequired = 1
-        addGestureRecognizer(tap)
-    }
-    
-    @objc func _clickCell() {
-        _delegate?.message?(message: _message, fileData: _fileData, fileName: _fileName, fileType: _fileType)
-    }
-}

+ 0 - 34
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageImageContent.swift

@@ -1,34 +0,0 @@
-//
-//  JCMessageImageContent.swift
-//  JChat
-//
-//  Created by deng on 2017/3/9.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-open class JCMessageImageContent: NSObject, JCMessageContentType {
-    typealias uploadHandle = (_ percent: Float) -> ()
-
-    public weak var delegate: JCMessageDelegate?
-    var upload: uploadHandle?
-    var imageSize: CGSize?
-    open var image: UIImage?
-    open var layoutMargins: UIEdgeInsets = .zero
-    
-    open class var viewType: JCMessageContentViewType.Type {
-        return JCMessageImageContentView.self
-    }
-    
-    open func sizeThatFits(_ size: CGSize) -> CGSize {
-        if image == nil {
-             image = UIImage.createImage(color: UIColor(netHex: 0xCDD0D1), size: imageSize ?? CGSize(width: 160, height: 160))
-        }
-        let size = imageSize ?? (image?.size)!
-        let scale = min(min(160, size.width) / size.width, min(160, size.height) / size.height)
-        let w = size.width * scale
-        let h = size.height * scale
-        return .init(width: w, height: h)
-    }
-}

+ 0 - 26
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageLocationContent.swift

@@ -1,26 +0,0 @@
-//
-//  JCMessageLocationContent.swift
-//  JChat
-//
-//  Created by deng on 2017/4/19.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-class JCMessageLocationContent: NSObject, JCMessageContentType {
-
-    public weak var delegate: JCMessageDelegate?
-    open var layoutMargins: UIEdgeInsets = .zero
-    open class var viewType: JCMessageContentViewType.Type {
-        return JCMessageLocationContentView.self
-    }
-    
-    open var address: String?
-    open var lon: Double?
-    open var lat: Double?
-    
-    open func sizeThatFits(_ size: CGSize) -> CGSize {
-        return .init(width: 141, height: 91)
-    }
-}

+ 0 - 70
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageLocationContentView.swift

@@ -1,70 +0,0 @@
-//
-//  JCMessageLocationContentView.swift
-//  JChat
-//
-//  Created by deng on 2017/4/19.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-class JCMessageLocationContentView: UIImageView, JCMessageContentViewType {
-    public override init(image: UIImage?) {
-        super.init(image: image)
-        _commonInit()
-    }
-    public override init(image: UIImage?, highlightedImage: UIImage?) {
-        super.init(image: image, highlightedImage: highlightedImage)
-        _commonInit()
-    }
-    public override init(frame: CGRect) {
-        super.init(frame: frame)
-        _commonInit()
-    }
-    public required init?(coder aDecoder: NSCoder) {
-        super.init(coder: aDecoder)
-        _commonInit()
-    }
-    
-    open func apply(_ message: JCMessageType) {
-        guard let content = message.content as? JCMessageLocationContent else {
-            return
-        }
-        _message = message
-        _delegate = content.delegate
-        _address = content.address
-        _lon = content.lon
-        _lat = content.lat
-        _addressLabel.text = content.address
-    }
-    
-    private weak var _delegate: JCMessageDelegate?
-    private var _message: JCMessageType!
-    private var _address: String?
-    private var _lon: Double?
-    private var _lat: Double?
-    private var _addressLabel = UILabel(frame: CGRect(x: 10, y: 0, width: 113, height: 40))
-    private lazy var locationImage: UIImage? = UIImage.loadImage("location_address")
-    
-    private func _commonInit() {
-        _addressLabel.font = UIFont.systemFont(ofSize: 13)
-        _addressLabel.numberOfLines = 2
-        addSubview(_addressLabel)
-        isUserInteractionEnabled = true
-        layer.cornerRadius = 2
-        layer.masksToBounds = true
-        image = locationImage
-        _tapGesture()
-    }
-    
-    func _tapGesture() {
-        
-        let tap = UITapGestureRecognizer(target: self, action: #selector(_clickCell))
-        tap.numberOfTapsRequired = 1
-        addGestureRecognizer(tap)
-    }
-    
-    func _clickCell() {
-        _delegate?.message?(message: _message, location: _address, lat: _lat ?? 0, lon: _lon ?? 0)
-    }
-}

+ 0 - 39
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageNoticeContent.swift

@@ -1,39 +0,0 @@
-//
-//  JCMessageNoticeContent.swift
-//  JChat
-//
-//  Created by deng on 2017/3/9.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-open class JCMessageNoticeContent: NSObject, JCMessageContentType {
-    public weak var delegate: JCMessageDelegate?
-    
-    open var layoutMargins: UIEdgeInsets = .zero
-    
-    open class var viewType: JCMessageContentViewType.Type {
-        return JCMessageNoticeContentView.self
-    }
-    
-    public init(text: String) {
-        self.text = text
-        super.init()
-    }
-    
-    open var text: String
-    
-    open func sizeThatFits(_ size: CGSize) -> CGSize {
-        let attributes = [
-            NSAttributedString.Key.font: UIFont.systemFont(ofSize: 12),
-            NSAttributedString.Key.foregroundColor: UIColor.white,
-        ]
-        let attr = NSMutableAttributedString(string: text, attributes: attributes)
-        let mattrSize = attr.boundingRect(with: CGSize(width: 250.0, height: Double(MAXFLOAT)), options: [.usesLineFragmentOrigin,.usesFontLeading], context: nil)
-        let size = CGSize(width: mattrSize.size.width + 11, height: mattrSize.size.height + 4)
-        return size
-    }
-
-    public static let unsupport: JCMessageNoticeContent = JCMessageNoticeContent(text: "The message does not support")
-}

+ 0 - 41
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageNoticeContentView.swift

@@ -1,41 +0,0 @@
-//
-//  JCMessageNoticeContentView.swift
-//  JChat
-//
-//  Created by deng on 2017/3/9.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-open class JCMessageNoticeContentView: UILabel, JCMessageContentViewType {
-    
-    public override init(frame: CGRect) {
-        super.init(frame: frame)
-        _commonInit()
-    }
-    public required init?(coder aDecoder: NSCoder) {
-        super.init(coder: aDecoder)
-        _commonInit()
-    }
-
-    
-    open func apply(_ message: JCMessageType) {
-        guard let content = message.content as? JCMessageNoticeContent else {
-            return
-        }
-        text = content.text
-    }
-    
-    private func _commonInit() {
-        layer.cornerRadius = 2.5
-        layer.borderWidth = 1.0
-        layer.borderColor = UIColor(netHex: 0xD7DCE2).cgColor
-        layer.masksToBounds = true
-        font = UIFont.systemFont(ofSize: 12)
-        backgroundColor = UIColor(netHex: 0xD7DCE2)
-        textColor = .white
-        textAlignment = .center
-        numberOfLines = 0
-    }
-}

+ 0 - 42
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageTextContent.swift

@@ -1,42 +0,0 @@
-//
-//  JCMessageTextContent.swift
-//  JChat
-//
-//  Created by deng on 2017/3/9.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-open class JCMessageTextContent: NSObject, JCMessageContentType {
-    public weak var delegate: JCMessageDelegate?
-    public override init() {
-        let text = "this is a test text"
-        self.text = NSAttributedString(string: text)
-        super.init()
-    }
-    public init(text: String) {
-        self.text = NSAttributedString(string: text)
-        super.init()
-    }
-    public init(attributedText: NSAttributedString) {
-        self.text = attributedText
-        super.init()
-    }
-    
-    open class var viewType: JCMessageContentViewType.Type {
-        return JCMessageTextContentView.self
-    }
-    open var layoutMargins: UIEdgeInsets = .init(top: 9, left: 10, bottom: 9, right: 10)
-    
-    open var text: NSAttributedString
-    
-    open func sizeThatFits(_ size: CGSize) -> CGSize {
-        let mattr = NSMutableAttributedString(attributedString: text)
-        mattr.addAttribute(NSAttributedString.Key.font, value: UIFont.systemFont(ofSize: 16), range: NSMakeRange(0, mattr.length))
-
-        let mattrSize = mattr.boundingRect(with: CGSize(width: 220.0, height: Double(MAXFLOAT)), options: [.usesLineFragmentOrigin,.usesFontLeading], context: nil)
-        self.text = mattr
-        return .init(width: max(mattrSize.width, 15), height: max(mattrSize.height, 15))
-    }
-}

+ 0 - 49
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageTextContentView.swift

@@ -1,49 +0,0 @@
-//
-//  JCMessageTextContentView.swift
-//  JChat
-//
-//  Created by deng on 2017/3/9.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-open class JCMessageTextContentView: KILabel, JCMessageContentViewType {
-
-    public override init(frame: CGRect) {
-        super.init(frame: frame)
-        _commonInit()
-    }
-    public required init?(coder aDecoder: NSCoder) {
-        super.init(coder: aDecoder)
-        _commonInit()
-    }
-
-    open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
-        return super.canPerformAction(action, withSender: sender)
-    }
-    
-    open func apply(_ message: JCMessageType) {
-        guard let content = message.content as? JCMessageTextContent else {
-            return
-        }
-        self.attributedText = content.text
-        self.linkDetectionTypes = KILinkTypeOption.URL
-        self.urlLinkTapHandler = { label, url, range in
-            if let Url = URL(string: url) {
-                if UIApplication.shared.canOpenURL(Url) {
-                    UIApplication.shared.openURL(Url)
-                } else {
-                    let newUrl = URL(string: "https://" + url)
-                    UIApplication.shared.openURL(newUrl!)
-                }
-            }
-        }
-    }
-    
-    private func _commonInit() {
-        self.numberOfLines = 0
-    }
-}
-
-

+ 0 - 93
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageTimeLineContent.swift

@@ -1,93 +0,0 @@
-//
-//  JCMessageTimeLineContent.swift
-//  JChat
-//
-//  Created by deng on 2017/3/9.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-open class JCMessageTimeLineContent: NSObject, JCMessageContentType {
-
-    public weak var delegate: JCMessageDelegate?
-    open var layoutMargins: UIEdgeInsets = .zero
-
-    open class var viewType: JCMessageContentViewType.Type {
-        return JCMessageTimeLineContentView.self
-    }
-    
-    public init(date: Date) {
-        self.date = date
-        super.init()
-    }
-
-    internal var before: JCMessageType?
-    internal var after: JCMessageType?
-    
-    open var date: Date
-    open var text: String {
-        return JCMessageTimeLineContent.dd(after?.date ?? date)
-    }
-
-    // 这个是比较耗时的操作,所以这里设置为全局只创建一次
-    static let defaultFormat = DateFormatter.dateFormat(fromTemplate: "hh:mm", options: 0, locale: nil) ?? "hh:mm"
-    
-    static func dd(_ date: Date) -> String {
-        
-        // yy-MM-dd hh:mm
-        // MM-dd hh:mm
-        // 星期一 hh:mm - 7 * 24小时内
-        // 昨天 hh:mm - 2 * 24小时内
-        // 今天 hh:mm - 24小时内
-        
-        let s1 = TimeInterval(date.timeIntervalSince1970)
-        let s2 = TimeInterval(time(nil))
-        
-        let dz = TimeInterval(TimeZone.current.secondsFromGMT())
-        
-        let formatter = DateFormatter()
-        // 每次都创建会非常耗时
-        let format1 = JCMessageTimeLineContent.defaultFormat
-        
-        let days1 = Int64(s1 + dz) / (24 * 60 * 60)
-        let days2 = Int64(s2 + dz) / (24 * 60 * 60)
-        
-        switch days1 - days2 {
-        case +0:
-            // Today
-            formatter.dateFormat = "\(format1)"
-        case +1:
-            // Tomorrow
-            formatter.dateFormat = "'明天' \(format1)"
-        case +2 ... +7:
-            // 2 - 7 day later
-            formatter.dateFormat = "EEEE \(format1)"
-        case -1:
-            formatter.dateFormat = "'昨天' \(format1)"
-        case -2:
-            formatter.dateFormat = "'前天' \(format1)"
-        case -7 ... -2:
-            // 2 - 7 day ago
-            formatter.dateFormat = "EEEE \(format1)"
-        default:
-            // Distant
-            if date.isThisYear() {
-                formatter.dateFormat = "MM-dd \(format1)"
-            } else {
-                formatter.dateFormat = "yy-MM-dd \(format1)"
-            }
-        }
-        return formatter.string(from: date)
-    }
-    
-    open func sizeThatFits(_ size: CGSize) -> CGSize {
-        
-        let attr = NSMutableAttributedString(string: text, attributes: [
-            NSAttributedString.Key.font: UIFont.systemFont(ofSize: 12),
-            NSAttributedString.Key.foregroundColor: UIColor.white,
-            ])
-        
-        return CGSize(width: attr.size().width + 11, height: 18)
-    }
-}

+ 0 - 39
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageTimeLineContentView.swift

@@ -1,39 +0,0 @@
-//
-//  JCMessageTimeLineContentView.swift
-//  JChat
-//
-//  Created by deng on 2017/3/9.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-open class JCMessageTimeLineContentView: UILabel, JCMessageContentViewType {
-    
-    public override init(frame: CGRect) {
-        super.init(frame: frame)
-        _commonInit()
-    }
-    public required init?(coder aDecoder: NSCoder) {
-        super.init(coder: aDecoder)
-        _commonInit()
-    }
-    
-    open func apply(_ message: JCMessageType) {
-        guard let content = message.content as? JCMessageTimeLineContent else {
-            return
-        }
-        text = content.text
-    }
-    
-    private func _commonInit() {
-        layer.cornerRadius = 2.5
-        layer.borderWidth = 1.0
-        layer.borderColor = UIColor(netHex: 0xD7DCE2).cgColor
-        layer.masksToBounds = true
-        font = UIFont.systemFont(ofSize: 12)
-        backgroundColor = UIColor(netHex: 0xD7DCE2)
-        textColor = .white
-        textAlignment = .center
-    }
-}

+ 0 - 36
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageVideoContent.swift

@@ -1,36 +0,0 @@
-//
-//  JCMessageVideoContent.swift
-//  JChat
-//
-//  Created by deng on 2017/3/9.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-import JMessage
-
-open class JCMessageVideoContent: NSObject, JCMessageContentType {
-
-    public weak var delegate: JCMessageDelegate?
-    open var layoutMargins: UIEdgeInsets = .zero
-    open class var viewType: JCMessageContentViewType.Type {
-        return JCMessageVideoContentView.self
-    }
-    open var data: Data?
-    open var image: UIImage?
-    open var fileContent: JMSGFileContent?
-    
-    open func sizeThatFits(_ size: CGSize) -> CGSize {
-        if data == nil {
-            return .init(width: 140, height: 89)
-        }
-        image = JCVideoManager.getFristImage(data: data!)
-        let size = image?.size ?? .zero
-        
-        let scale = min(min(160, size.width) / size.width, min(160, size.height) / size.height)
-        
-        let w = size.width * scale
-        let h = size.height * scale
-        return .init(width: w, height: h)
-    }
-}

+ 0 - 115
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageVideoContentView.swift

@@ -1,115 +0,0 @@
-//
-//  JCMessageVideoContentView.swift
-//  JChat
-//
-//  Created by deng on 2017/3/9.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-import AVKit
-import AVFoundation
-
-open class JCMessageVideoContentView: UIImageView, JCMessageContentViewType {
-    
-    public override init(image: UIImage?) {
-        super.init(image: image)
-        _commonInit()
-    }
-    public override init(image: UIImage?, highlightedImage: UIImage?) {
-        super.init(image: image, highlightedImage: highlightedImage)
-        _commonInit()
-    }
-    public override init(frame: CGRect) {
-        super.init(frame: frame)
-        _commonInit()
-    }
-    public required init?(coder aDecoder: NSCoder) {
-        super.init(coder: aDecoder)
-        _commonInit()
-    }
-    
-    open func apply(_ message: JCMessageType) {
-        guard message.content is JCMessageVideoContent else {
-            return
-        }
-        _message = message
-        let content = message.content as! JCMessageVideoContent
-        _delegate = content.delegate
-        if content.data != nil {
-            _data = content.data
-            if content.image != nil {
-                self.image = content.image
-            }else {
-                DispatchQueue.main.async {
-                    self.image = JCVideoManager.getFristImage(data: self._data!)
-                }
-            }
-        }else{
-            //self.image = UIImage.createImage(color: UIColor.init(hex: "0xCDD0D1"), size: self.size)
-            content.fileContent?.fileData({ (data, id, error) in
-                if data != nil {
-                    self._data = data
-                    DispatchQueue.main.async {
-                        self.image = JCVideoManager.getFristImage(data: self._data!)
-                    }
-                }
-            })
-        }
-//
-        _playImageView.center = CGPoint(x: self.width/2, y: self.height/2)
-        
-        
-//        guard let content = message.content as? JCMessageVideoContent else {
-//            return
-//        }
-//        _message = message
-//        _delegate = content.delegate
-//        if content.data != nil {
-//            _data = content.data
-//            if content.image != nil {
-//                self.image = content.image
-//            } else {
-//                DispatchQueue.main.async {
-//                    self.image = JCVideoManager.getFristImage(data: self._data!)
-//                }
-//            }
-//        } else {
-//            self.image = UIImage.createImage(color: UIColor(netHex: 0xCDD0D1), size: self.size)
-//            content.fileContent?.fileData({ (data, id, error) in
-//                if data != nil {
-//                    self._data = data
-//                    DispatchQueue.main.async {
-//                        self.image = JCVideoManager.getFristImage(data: self._data!)
-//                    }
-//                }
-//            })
-//        }
-//        _playImageView.center = CGPoint(x: self.width / 2, y: self.height / 2)
-    }
-
-    private weak var _delegate: JCMessageDelegate?
-    private var _data: Data?
-    private var _playImageView: UIImageView!
-    private var _message: JCMessageType!
-    
-    private func _commonInit() {
-        isUserInteractionEnabled = true
-        layer.cornerRadius = 2
-        layer.masksToBounds = true
-        _tapGesture()
-        _playImageView = UIImageView(frame: CGRect(x: 0, y: 50, width: 41, height: 41))
-        _playImageView.image = UIImage.loadImage("com_icon_play")
-        addSubview(_playImageView)
-    }
-    
-    func _tapGesture() {
-        let tap = UITapGestureRecognizer(target: self, action: #selector(_clickCell))
-        tap.numberOfTapsRequired = 1
-        addGestureRecognizer(tap)
-    }
-    
-    @objc func _clickCell() {
-        _delegate?.message?(message: _message, videoData: _data)
-    }
-}

+ 0 - 36
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageVoiceContent.swift

@@ -1,36 +0,0 @@
-//
-//  JCMessageVoiceContent.swift
-//  JChat
-//
-//  Created by deng on 2017/3/9.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-open class JCMessageVoiceContent: NSObject, JCMessageContentType {
-
-    public weak var delegate: JCMessageDelegate?
-    open var layoutMargins: UIEdgeInsets = .init(top: 5, left: 10, bottom: 5, right: 10)
-    open class var viewType: JCMessageContentViewType.Type {
-        return JCMessageVoiceContentView.self
-    }
-    open var data: Data?
-    open var duration: TimeInterval = 9999
-    open var attributedText: NSAttributedString?
-    
-    open func sizeThatFits(_ size: CGSize) -> CGSize {
-        // +---------------+
-        // | |||  99'59''  |
-        // +---------------+
-        let minute = Int(duration) / 60
-        let second = Int(duration) % 60
-        var string = "\(minute)'\(second)''"
-        if minute == 0 {
-            string = "\(second)''"
-        }
-        attributedText = NSAttributedString(string: string, attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 14)])
-        
-        return .init(width: 20 + 38 + 20, height: 26)
-    }
-}

+ 0 - 124
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/Message/JCMessageVoiceContentView.swift

@@ -1,124 +0,0 @@
-//
-//  JCMessageVoiceContentView.swift
-//  JChat
-//
-//  Created by deng on 2017/3/9.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-import AVFoundation
-
-open class JCMessageVoiceContentView: UIView, JCMessageContentViewType {
-    
-    public override init(frame: CGRect) {
-        super.init(frame: frame)
-        _commonInit()
-    }
-    public required init?(coder aDecoder: NSCoder) {
-        super.init(coder: aDecoder)
-        _commonInit()
-    }
-    
-    deinit {
-        JCAudioPlayerHelper.sharedInstance.stopAudio()
-    }
-
-    
-    open func apply(_ message: JCMessageType) {
-        guard let content = message.content as? JCMessageVoiceContent else {
-            return
-        }
-        _duration = Double(content.duration)
-        _message = message
-        _delegate = content.delegate
-        _updateViewLayouts(message.options)
-        _data = content.data
-        _titleLabel.attributedText = content.attributedText
-    }
-    
-    private func _updateViewLayouts(_ options: JCMessageOptions) {
-        guard _alignment != options.alignment else {
-            return
-        }
-        _alignment = options.alignment
-        
-        let aw = CGFloat(20)
-        let tw = bounds.maxX - 8 - aw
-        
-        if _alignment == .left {
-            _titleLabel.textColor = UIColor(netHex: 0x999999)
-            _titleLabel.textAlignment = .right
-            _animationView.image = UIImage.loadImage("chat_voice_receive_icon_3")
-            _animationView.animationImages = [
-                UIImage.loadImage("chat_voice_receive_icon_1"),
-                UIImage.loadImage("chat_voice_receive_icon_2"),
-                UIImage.loadImage("chat_voice_receive_icon_3"),
-            ].flatMap { $0 }
-            
-            _animationView.frame = CGRect(x: bounds.minX, y: 3, width: aw, height: 20)
-            _titleLabel.frame = CGRect(x: bounds.maxX - tw, y: 3, width: tw, height: 20)
-        } else {
-            _titleLabel.textColor = UIColor(netHex: 0x4D9999)
-            _titleLabel.textAlignment = .left
-            _animationView.image = UIImage.loadImage("chat_voice_send_icon_3")
-            _animationView.animationImages = [
-                UIImage.loadImage("chat_voice_send_icon_1"),
-                UIImage.loadImage("chat_voice_send_icon_2"),
-                UIImage.loadImage("chat_voice_send_icon_3"),
-            ].flatMap { $0 }
-            
-            _animationView.frame = CGRect(x: bounds.maxX - aw, y: 3, width: aw, height: 20)
-            _titleLabel.frame = CGRect(x: bounds.minX, y: 3, width: tw, height: 20)
-        }
-    }
-    
-    private func _commonInit() {
-        _animationView.animationDuration = 0.8
-        _animationView.animationRepeatCount = 0
-        addSubview(_animationView)
-        addSubview(_titleLabel)
-        _tapGesture()
-    }
-    
-    func _tapGesture() {
-        let tap = UITapGestureRecognizer(target: self, action: #selector(_clickCell))
-        tap.numberOfTapsRequired = 1
-        addGestureRecognizer(tap)
-    }
-    
-    func _clickCell() {
-//        _delegate?.message?(message: _message, voiceData: _data, duration: _duration)
-
-        // TODO: 这里不就应该把 V 层代码放在这里,需要考虑下这个播放时开启动画的传递方式
-        if let player = JCAudioPlayerHelper.sharedInstance.player {
-            if player.isPlaying {
-                JCAudioPlayerHelper.sharedInstance.stopAudio()
-                return
-            }
-        }
-        JCAudioPlayerHelper.sharedInstance.delegate = self
-        JCAudioPlayerHelper.sharedInstance.managerAudioWithData(_data!, toplay: true)
-        _animationView.startAnimating()
-    }
-
-    private var _duration: Double = 0.0
-    private weak var _delegate: JCMessageDelegate?
-    private var _message: JCMessageType!
-    fileprivate lazy var _animationView: UIImageView = UIImageView()
-    private lazy var _titleLabel: UILabel = UILabel()
-    private var _data: Data?
-    private var _alignment: JCMessageAlignment = .center
-}
-
-extension JCMessageVoiceContentView: JCAudioPlayerHelperDelegate {
-    func didAudioPlayerStopPlay(_ AudioPlayer: AVAudioPlayer) {
-        _animationView.stopAnimating()
-    }
-    func didAudioPlayerBeginPlay(_ AudioPlayer: AVAudioPlayer) {
-        
-    }
-    func didAudioPlayerPausePlay(_ AudioPlayer: AVAudioPlayer) {
-        _animationView.stopAnimating()
-    }
-}

+ 0 - 119
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/View/MorePopupView.swift

@@ -1,119 +0,0 @@
-//
-//  MorePopupView.swift
-//  JChat
-//
-//  Created by deng on 2017/8/15.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-import YHPopupView
-
-@objc protocol MorePopupViewDelegate: NSObjectProtocol {
-    @objc optional func popupView(view: MorePopupView, addFriend addButton: UIButton)
-    @objc optional func popupView(view: MorePopupView, addGroup addButton: UIButton)
-    @objc optional func popupView(view: MorePopupView, addSingle addButton: UIButton)
-    @objc optional func popupView(view: MorePopupView, scanQRCode addButton: UIButton)
-}
-
-class MorePopupView: YHPopupView {
-    
-    weak var delegate: MorePopupViewDelegate?
-    
-    override init(frame: CGRect) {
-        super.init(frame: frame)
-        _init()
-    }
-    
-    required init?(coder aDecoder: NSCoder) {
-        fatalError("init(coder:) has not been implemented")
-    }
-    
-    private lazy var addFriend: UIButton = {
-        var addFriend = UIButton()
-        addFriend.titleLabel?.font = UIFont.systemFont(ofSize: 16)
-        addFriend.addTarget(self, action: #selector(_addFriend), for: .touchUpInside)
-        addFriend.setImage(UIImage.loadImage("com_icon_friend_add"), for: .normal)
-        addFriend.setImage(UIImage.loadImage("com_icon_friend_add"), for: .highlighted)
-        addFriend.setTitle("  添加朋友", for: .normal)
-        return addFriend
-    }()
-    
-    private lazy var addGroup: UIButton = {
-        var addGroup = UIButton()
-        addGroup.titleLabel?.font = UIFont.systemFont(ofSize: 16)
-        addGroup.addTarget(self, action: #selector(_addGroup), for: .touchUpInside)
-        addGroup.setImage(UIImage.loadImage("com_icon_conv_group"), for: .normal)
-        addGroup.setImage(UIImage.loadImage("com_icon_conv_group"), for: .highlighted)
-        addGroup.setTitle("  发起群聊", for: .normal)
-        return addGroup
-    }()
-    
-    private lazy var addSingle: UIButton = {
-        var addSingle = UIButton()
-        addSingle.titleLabel?.font = UIFont.systemFont(ofSize: 16)
-        addSingle.addTarget(self, action: #selector(_addSingle), for: .touchUpInside)
-        addSingle.setImage(UIImage.loadImage("com_icon_conv_single"), for: .normal)
-        addSingle.setImage(UIImage.loadImage("com_icon_conv_single"), for: .highlighted)
-        addSingle.setTitle("  发起单聊", for: .normal)
-        return addSingle
-    }()
-    
-    private lazy var scanQRCode: UIButton = {
-        var scanQRCode = UIButton()
-        scanQRCode.titleLabel?.font = UIFont.systemFont(ofSize: 16)
-        scanQRCode.addTarget(self, action: #selector(_scanQRCode), for: .touchUpInside)
-        scanQRCode.setImage(UIImage.loadImage("com_icon_scan"), for: .normal)
-        scanQRCode.setImage(UIImage.loadImage("com_icon_scan"), for: .highlighted)
-        scanQRCode.setTitle("  扫一扫    ", for: .normal)
-        return scanQRCode
-    }()
-    
-    private func _init() {
-        let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 145, height: 100))
-        imageView.image = UIImage.loadImage("com_icon_selectList")
-        addSubview(imageView)
-        backgroundViewColor = .clear
-        clickBlankSpaceDismiss = true
-        self.theme_backgroundColor = ThemeColorPicker(keyPath: "Base.base_color")
-        
-        let height = Double((self.height - 5) / 2)
-        let width = Double(self.width)
-        let image = UIImage.createImage(color: UIColor(netHex: 0x999999), size: CGSize(width: 140, height: height))
-        
-        scanQRCode.frame = CGRect(x: 0.0, y: 5 + height * 3, width: width, height: height)
-        scanQRCode.setBackgroundImage(image, for: .highlighted)
-        
-        addFriend.frame = CGRect(x: 0.0, y: 5 + height * 2, width: width, height: height)
-        addFriend.setBackgroundImage(image, for: .highlighted)
-        
-        addGroup.frame = CGRect(x: 0.0, y: 5 + height, width: width, height: height)
-        addGroup.setBackgroundImage(image, for: .highlighted)
-        
-        addSingle.frame = CGRect(x: 0.0, y: 5, width: width, height: height)
-        addSingle.setBackgroundImage(image, for: .highlighted)
-    
-        addSubview(addSingle)
-        addSubview(addGroup)
-        // TODO:- 只有群聊和单聊,其它功能暂时不开放
-//        addSubview(addFriend)
-//        addSubview(scanQRCode)
-    }
-    
-    @objc func _addFriend() {
-        delegate?.popupView?(view: self, addFriend: addFriend)
-    }
-    
-    @objc func _addGroup() {
-        delegate?.popupView?(view: self, addGroup: addGroup)
-    }
-    
-    @objc func _addSingle() {
-        delegate?.popupView?(view: self, addSingle: addSingle)
-    }
-    
-    @objc func _scanQRCode() {
-        delegate?.popupView?(view: self, scanQRCode: scanQRCode)
-    }
-    
-}

+ 0 - 248
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/FileManagerViewController.swift

@@ -1,248 +0,0 @@
-//
-//  FileManagerViewController.swift
-//  JChat
-//
-//  Created by 邓永豪 on 2017/8/28.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-protocol FileManagerDelegate {
-    func didSelectFile(_ fileMessage: JMessage)
-    func isEditModel() -> Bool
-}
-
-class FileManagerViewController: UIViewController {
-    
-    var conversation: JMSGConversation!
-
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        _init()
-    }
-    
-    deinit {
-        NotificationCenter.default.removeObserver(self)
-    }
-    
-    fileprivate let imageFileViewController = ImageFileViewController()
-    fileprivate let docFileViewController =  FileViewController()
-    fileprivate let videoFileViewController =  FileViewController()
-    fileprivate let musicFileViewController =  FileViewController()
-    fileprivate let otherFileViewController =  FileViewController()
-    
-    private var allMessage: [JMSGMessage] = []
-    private var imageMessages: [JMSGMessage] = []
-    private var docMessages: [JMSGMessage] = []
-    private var videoMessages: [JMSGMessage] = []
-    private var musicMessages: [JMSGMessage] = []
-    private var otherFileMessages: [JMSGMessage] = []
-    private var selectMessage: [JMSGMessage] = []
-
-    private var topOffset: CGFloat {
-        if isIPhoneX {
-            return 88
-        }
-        return 64
-    }
-    
-    private lazy var tabedSlideView: DLTabedSlideView = {
-        var tabedSlideView = DLTabedSlideView(frame: CGRect(x: 0, y: self.topOffset, width: self.view.width, height: self.view.height - self.topOffset))
-        tabedSlideView.delegate = self
-        tabedSlideView.baseViewController = self
-        tabedSlideView.tabItemNormalColor = .black
-        tabedSlideView.tabItemSelectedColor =  O2ThemeManager.color(for: "Base.base_color")!
-        tabedSlideView.tabbarTrackColor = O2ThemeManager.color(for: "Base.base_color")!
-        tabedSlideView.tabbarBackgroundImage = UIImage.createImage(color: .white, size: CGSize(width: self.view.width, height: 39))
-        tabedSlideView.tabbarBottomSpacing = 3.0
-        return tabedSlideView
-    }()
-    
-    private lazy var navRightButton: UIBarButtonItem = UIBarButtonItem(title: "选择", style: .plain, target: self, action: #selector(_clickNavRightButton))
-    fileprivate var isEditMode = false
-    private lazy var barView: UIView = {
-        var barView = UIView(frame: CGRect(x: 0, y: self.view.height - 45, width: self.view.width, height: 45))
-        let line = UILabel(frame: CGRect(x: 0, y: 0, width: barView.width, height: 0.5))
-        line.layer.backgroundColor = UIColor(netHex: 0xE8E8E8).cgColor
-        barView.addSubview(line)
-        barView.backgroundColor = .white
-        barView.isHidden = true
-        return barView
-    }()
-    private lazy var delButton: UIButton = {
-        var delButton = UIButton()
-        delButton.setTitle("删除", for: .normal)
-        delButton.titleLabel?.font = UIFont.systemFont(ofSize: 16)
-        delButton.layer.cornerRadius = 3
-        delButton.layer.masksToBounds = true
-        delButton.addTarget(self, action: #selector(_delFile), for: .touchUpInside)
-        delButton.backgroundColor = UIColor(netHex: 0xEB424D)
-        return delButton
-    }()
-    
-    private lazy var selectCountLabel: UILabel = {
-        var label = UILabel(frame: CGRect(x: 17.5, y: 11.5, width: 120, height: 22))
-        label.textAlignment = .left
-        label.textColor = UIColor(netHex: 0x999999)
-        label.font = UIFont.systemFont(ofSize: 16)
-        label.isHidden = true
-        return label
-    }()
-    
-    private func _init() {
-        self.title = "聊天文件"
-        view.backgroundColor = UIColor(netHex: 0xe8edf3)
-        
-        view.addSubview(tabedSlideView)
-        let imageItem = DLTabedbarItem(title: "照片", image: nil, selectedImage: nil)
-        let fileItem = DLTabedbarItem(title: "文档", image: nil, selectedImage: nil)
-        let videoItem = DLTabedbarItem(title: "视频", image: nil, selectedImage: nil)
-        let musicItem = DLTabedbarItem(title: "音乐", image: nil, selectedImage: nil)
-        let otherItem = DLTabedbarItem(title: "其它", image: nil, selectedImage: nil)
-        tabedSlideView.tabbarItems = [imageItem!, fileItem!, videoItem!, musicItem!, otherItem!]
-        tabedSlideView.buildTabbar()
-        tabedSlideView.selectedIndex = 0
-        
-        view.addSubview(barView)
-        barView.addSubview(delButton)
-        barView.addSubview(selectCountLabel)
-        delButton.frame = CGRect(x: barView.width - 72 - 16.6, y: 8.5, width: 72, height: 29)
-        _setupNavigation()
-        
-        conversation.allMessages({ (result, error) in
-            if let message = result as? [JMSGMessage] {
-                self.allMessage = message
-                self.classifyMessage(message)
-            }
-        })
-        
-        NotificationCenter.default.addObserver(self, selector: #selector(_didSelectFileMessage), name: NSNotification.Name(rawValue: "kDidSelectFileMessage"), object: nil)
-    }
-    
-    func _didSelectFileMessage() {
-        selectMessage.removeAll()
-        selectMessage.append(contentsOf: imageFileViewController.selectMessages)
-        selectMessage.append(contentsOf: docFileViewController.selectMessages)
-        selectMessage.append(contentsOf: videoFileViewController.selectMessages)
-        selectMessage.append(contentsOf: musicFileViewController.selectMessages)
-        selectMessage.append(contentsOf: otherFileViewController.selectMessages)
-        
-        if selectMessage.count > 0 {
-            selectCountLabel.isHidden = false
-            selectCountLabel.text = "已选(\(selectMessage.count))"
-        } else {
-            selectCountLabel.isHidden = true
-        }
-    }
-    
-    func classifyMessage(_ messages: [JMSGMessage]) {
-        docMessages.removeAll()
-        videoMessages.removeAll()
-        musicMessages.removeAll()
-        imageMessages.removeAll()
-        otherFileMessages.removeAll()
-        for message in messages {
-            if message.contentType == .image {
-                imageMessages.append(message)
-                continue
-            }
-            if !message.ex.isFile {
-                continue
-            }
-            if let fileType = message.ex.fileType {
-                switch fileType.fileFormat() {
-                case .document:
-                    docMessages.append(message)
-                case .video:
-                    videoMessages.append(message)
-                case .voice:
-                    musicMessages.append(message)
-                case .photo:
-                    imageMessages.append(message)
-                default:
-                    otherFileMessages.append(message)
-                }
-            }
-        }
-        reloadAllFileViewController()
-    }
-    
-    func reloadAllFileViewController() {
-        imageFileViewController.messages = imageMessages
-        docFileViewController.messages = docMessages
-        videoFileViewController.messages = videoMessages
-        musicFileViewController.messages = musicMessages
-        otherFileViewController.messages = otherFileMessages
-        
-        imageFileViewController.reloadDate()
-        docFileViewController.reloadDate()
-        videoFileViewController.reloadDate()
-        musicFileViewController.reloadDate()
-        otherFileViewController.reloadDate()
-    }
-    
-    private func _setupNavigation() {
-        self.navigationItem.rightBarButtonItem =  navRightButton
-    }
-    
-    @objc func _clickNavRightButton() {
-        if isEditMode {
-            navRightButton.title = "选择"
-            tabedSlideView.frame = CGRect(x: tabedSlideView.x, y: tabedSlideView.y, width: tabedSlideView.width, height: tabedSlideView.height + 45)
-            barView.isHidden = true
-        } else {
-            navRightButton.title = "取消"
-            tabedSlideView.frame = CGRect(x: tabedSlideView.x, y: tabedSlideView.y, width: tabedSlideView.width, height: tabedSlideView.height - 45)
-            barView.isHidden = false
-        }
-        isEditMode = !isEditMode
-        imageFileViewController.isEditModel = isEditMode
-        otherFileViewController.isEditModel = isEditMode
-        videoFileViewController.isEditModel = isEditMode
-        musicFileViewController.isEditModel = isEditMode
-        docFileViewController.isEditModel = isEditMode
-        selectMessage = []
-    }
-    
-    func _delFile() {
-        if selectMessage.count <= 0 {
-            return
-        }
-        isEditMode = true
-        for message in selectMessage {
-            allMessage = allMessage.filter({ (m) -> Bool in
-                message.msgId != m.msgId
-            })
-            conversation.deleteMessage(withMessageId: message.msgId)
-        }
-        classifyMessage(allMessage)
-        _clickNavRightButton()
-        NotificationCenter.default.post(name: NSNotification.Name(rawValue: kReloadAllMessage), object: nil)
-    }
-}
-
-extension FileManagerViewController: DLTabedSlideViewDelegate {
-    func numberOfTabs(in sender: DLTabedSlideView!) -> Int {
-        return 5
-    }
-    
-    func dlTabedSlideView(_ sender: DLTabedSlideView!, controllerAt index: Int) -> UIViewController! {
-        switch index {
-        case 0:
-            return imageFileViewController
-        case 1:
-            docFileViewController.fileType = .doc
-            return docFileViewController
-        case 2:
-            videoFileViewController.fileType = .video
-            return videoFileViewController
-        case 3:
-            musicFileViewController.fileType = .music
-            return musicFileViewController
-        default:
-            otherFileViewController.fileType = .other
-            return otherFileViewController
-        }
-    }
-}

+ 0 - 203
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/FileViewController.swift

@@ -1,203 +0,0 @@
-//
-//  FileViewController.swift
-//  JChat
-//
-//  Created by 邓永豪 on 2017/8/28.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-enum FileType {
-    case doc
-    case music
-    case video
-    case other
-}
-
-class FileViewController: UIViewController {
-    
-    var isEditModel: Bool {
-        get {
-            return isEdit
-        } set {
-            isEdit = newValue
-            selectMessages = []
-            tableView.reloadData()
-        }
-    }
-
-    
-    var fileType = FileType.doc // default
-    var messages: [JMSGMessage] = []
-    var selectMessages: [JMSGMessage] = []
-
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        _init()
-    }
-    
-    func reloadDate() {
-        sortMessage()
-        tableView.reloadData()
-    }
-    
-    fileprivate var isEdit = false
-    fileprivate var tableView: UITableView = UITableView(frame: .zero, style: .grouped)
-    fileprivate lazy var data: Dictionary<String, [JMSGMessage]> = Dictionary()
-    fileprivate lazy var keys: [String] = []
-    
-    fileprivate lazy var documentInteractionController = UIDocumentInteractionController()
-    
-    private func _init() {
-        view.backgroundColor = UIColor(netHex: 0xe8edf3)
-        tableView.backgroundColor = UIColor(netHex: 0xe8edf3)
-        tableView.delegate = self
-        tableView.dataSource = self
-        tableView.separatorStyle = .none
-        tableView.register(FileCell.self, forCellReuseIdentifier: "FileCell")
-        view.addSubview(tableView)
-        view.addConstraint(_JCLayoutConstraintMake(tableView, .left, .equal, view, .left))
-        view.addConstraint(_JCLayoutConstraintMake(tableView, .top, .equal, view, .top))
-        view.addConstraint(_JCLayoutConstraintMake(tableView, .right, .equal, view, .right))
-        view.addConstraint(_JCLayoutConstraintMake(tableView, .bottom, .equal, view, .bottom))
-    }
-    
-    func sortMessage() {
-        keys.removeAll()
-        data.removeAll()
-        for message in messages {
-            let formatter = DateFormatter()
-            formatter.dateFormat = "yyyy-MM";
-            let date = Date(timeIntervalSince1970: TimeInterval(message.timestamp.intValue / 1000))
-            let key = formatter.string(from: date)
-            var array = data[key]
-            if array == nil {
-                array = [message]
-            } else {
-                array?.append(message)
-            }
-            if !keys.contains(key) {
-                keys.append(key)
-            }
-            data[key] = array
-        }
-        keys = keys.sorted(by: { (str1, str2) -> Bool in
-            str1 > str2
-        })
-    }
-}
-
-//Mark: -
-extension FileViewController: UITableViewDelegate, UITableViewDataSource {
-    
-    func numberOfSections(in tableView: UITableView) -> Int {
-        return keys.count
-    }
-    
-    public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
-        return data[keys[section]]!.count
-    }
-    
-    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
-        return keys[section]
-    }
-    
-    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
-        return 84
-    }
-    
-    func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
-        return 26
-    }
-    
-    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
-        return 0.001
-    }
-    
-    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
-        return tableView.dequeueReusableCell(withIdentifier: "FileCell", for: indexPath)
-    }
-    
-    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
-        guard let cell = cell as? FileCell else {
-            return
-        }
-        let message = data[keys[indexPath.section]]![indexPath.row]
-        let content = message.content as! JMSGFileContent
-        var image = UIImage()
-        switch fileType {
-        case .doc:
-            image = UIImage.loadImage("com_icon_file_file")!
-        case .music:
-            image = UIImage.loadImage("com_icon_file_music")!
-        case .video:
-            image = UIImage.loadImage("com_icon_file_video")!
-        default:
-            image = UIImage.loadImage("com_icon_file_other")!
-        }
-        let file = File(image, content.fileName, message.ex.fileSize ?? "", "\(message.fromName) \(keys[indexPath.section])")
-        cell.bindData(file)
-        cell.isEditMode = isEdit
-        if !isEditModel {
-            cell.isSelectImage = false
-        }
-    }
-    
-    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
-        tableView.deselectRow(at: indexPath, animated: true)
-        guard let cell = tableView.cellForRow(at: indexPath) as? FileCell else {
-            return
-        }
-        let message = data[keys[indexPath.section]]![indexPath.row]
-        if cell.isEditMode {
-            if cell.isSelectImage {
-                selectMessages = selectMessages.filter({ (m) -> Bool in
-                    message.msgId != m.msgId
-                })
-            } else {
-                selectMessages.append(message)
-            }
-            cell.isSelectImage = !cell.isSelectImage
-            NotificationCenter.default.post(name: NSNotification.Name(rawValue: "kDidSelectFileMessage"), object: nil)
-        } else {
-            let content = message.content as! JMSGFileContent
-            let type = message.ex.fileType
-            let fileName = content.fileName
-            switch fileType {
-            case .doc:
-                content.fileData({ (data, msgId, error) in
-                    let vc = JCDocumentViewController()
-                    vc.title = fileName
-                    vc.fileData = data
-                    vc.filePath = content.originMediaLocalPath
-                    vc.fileType = type
-                    DispatchQueue.main.async {
-                        self.navigationController?.pushViewController(vc, animated: true)
-                    }
-                })
-                
-            case .video, .music:
-                let url = URL(fileURLWithPath: content.originMediaLocalPath ?? "")
-                try! JCVideoManager.playVideo(data: Data(contentsOf: url), type ?? "", currentViewController: self)
-            default:
-                let url = URL(fileURLWithPath: content.originMediaLocalPath ?? "")
-                documentInteractionController.url = url
-                documentInteractionController.presentOptionsMenu(from: .zero, in: self.view, animated: true)
-            }
-        }
-    }
-}
-
-extension FileViewController: UIDocumentInteractionControllerDelegate {
-    func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
-        return self
-    }
-    func documentInteractionControllerViewForPreview(_ controller: UIDocumentInteractionController) -> UIView? {
-        return view
-    }
-    func documentInteractionControllerRectForPreview(_ controller: UIDocumentInteractionController) -> CGRect {
-        return view.frame
-    }
-}
-

+ 0 - 276
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/FriendsBusinessCardViewController.swift

@@ -1,276 +0,0 @@
-//
-//  FriendsBusinessCardViewController.swift
-//  JChat
-//
-//  Created by 邓永豪 on 2017/9/21.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-class FriendsBusinessCardViewController: UIViewController {
-
-    var conversation: JMSGConversation!
-
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        _init()
-    }
-
-    fileprivate lazy var toolView: UIView = UIView(frame: CGRect(x: 0, y: 64, width: self.view.width, height: 55))
-    fileprivate lazy var tableView: UITableView = {
-        let tableView = UITableView(frame: .zero, style: .grouped)
-        tableView.delegate = self
-        tableView.dataSource = self
-        tableView.keyboardDismissMode = .onDrag
-        tableView.sectionIndexColor = UIColor(netHex: 0x2dd0cf)
-        tableView.sectionIndexBackgroundColor = .clear
-        tableView.register(JCContacterCell.self, forCellReuseIdentifier: "JCContacterCell")
-        tableView.frame = CGRect(x: 0, y: 31 + 64, width: self.view.width, height: self.view.height - 31 - 64)
-        return tableView
-    }()
-    fileprivate lazy var searchView: UISearchBar = UISearchBar.default
-
-    fileprivate lazy var users: [JMSGUser] = []
-    fileprivate lazy var keys: [String] = []
-    fileprivate lazy var data: Dictionary<String, [JMSGUser]> = Dictionary()
-
-    fileprivate lazy var filteredUsersArray: [JMSGUser] = []
-    fileprivate var searchUser: JMSGUser?
-    fileprivate var selectUser: JMSGUser!
-
-    private lazy var navLeftButton: UIBarButtonItem = UIBarButtonItem(title: "取消", style: .plain, target: self, action: #selector(_clickNavLeftButton))
-
-    fileprivate lazy var tipsView: UIView = {
-        let view = UIView(frame: CGRect(x: 0, y: 64 + 31 + 5, width: self.view.width, height: self.view.height - 31 - 64 - 5))
-        view.backgroundColor = .white
-        let tips = UILabel(frame: CGRect(x: 0, y: 0, width: view.width, height: 50))
-        tips.font = UIFont.systemFont(ofSize: 16)
-        tips.textColor = UIColor(netHex: 0x999999)
-        tips.textAlignment = .center
-        tips.text = "未搜索到用户"
-        view.addSubview(tips)
-        view.isHidden = true
-        return view
-    }()
-
-    private func _init() {
-        self.title = "发送名片"
-        view.backgroundColor = .white
-        automaticallyAdjustsScrollViewInsets = false
-
-        view.addSubview(toolView)
-        view.addSubview(tableView)
-        view.addSubview(tipsView)
-
-        _classify([], isFrist: true)
-
-        searchView.frame = CGRect(x: 0, y: 0, width: toolView.width, height: 31)
-        searchView.delegate = self
-
-        toolView.addSubview(searchView)
-
-        _setupNavigation()
-    }
-
-    private func _setupNavigation() {
-        navigationItem.leftBarButtonItem =  navLeftButton
-    }
-
-    @objc func _clickNavLeftButton() {
-        dismiss(animated: true, completion: nil)
-    }
-
-
-    fileprivate func _classify(_ users: [JMSGUser], isFrist: Bool = false) {
-
-        if users.count > 0 {
-            tipsView.isHidden = true
-        }
-
-        if isFrist {
-
-            JMSGConversation.allConversations { (result, error) in
-                if error == nil {
-                    if let conversations = result as? [JMSGConversation] {
-                        for conv in conversations {
-                            if let user = conv.target as? JMSGUser {
-                                self.users.append(user)
-                            }
-                        }
-                    }
-                }
-            }
-
-            JMSGFriendManager.getFriendList { (result, error) in
-                if error == nil {
-                    for item in result as! [JMSGUser] {
-                        if !self.users.contains(item) {
-                            self.users.append(item)
-                        }
-                    }
-                    for item in self.users {
-                        var key = item.displayName().firstCharacter()
-                        if !key.isLetterOrNum() {
-                            key = "#"
-                        }
-                        var array = self.data[key]
-                        if array == nil {
-                            array = [item]
-                        } else {
-                            array?.append(item)
-                        }
-                        if !self.keys.contains(key) {
-                            self.keys.append(key)
-                        }
-                        self.data[key] = array
-                    }
-                    self.filteredUsersArray = self.users
-                    self.keys = self.keys.sortedKeys()
-                    self.tableView.reloadData()
-                }
-            }
-        } else {
-            filteredUsersArray = users
-            keys.removeAll()
-            data.removeAll()
-            for item in users {
-                var key = item.displayName().firstCharacter()
-                if !key.isLetterOrNum() {
-                    key = "#"
-                }
-                var array = data[key]
-                if array == nil {
-                    array = [item]
-                } else {
-                    array?.append(item)
-                }
-                if !keys.contains(key) {
-                    keys.append(key)
-                }
-
-                data[key] = array
-            }
-            keys = keys.sortedKeys()
-            tableView.reloadData()
-        }
-    }
-
-    fileprivate func filter(_ searchString: String) {
-        if searchString.isEmpty || searchString == "" {
-            _classify(users)
-            return
-        }
-        let searchString = searchString.uppercased()
-        filteredUsersArray = _JCFilterUsers(users: users, string: searchString)
-        _classify(filteredUsersArray)
-    }
-}
-
-//Mark: -
-extension FriendsBusinessCardViewController: UITableViewDelegate, UITableViewDataSource {
-
-    func numberOfSections(in tableView: UITableView) -> Int {
-        if filteredUsersArray.count > 0 {
-            return keys.count
-        }
-        return 0
-    }
-
-    public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
-        return data[keys[section]]!.count
-    }
-
-    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
-        return keys[section]
-    }
-
-    func sectionIndexTitles(for tableView: UITableView) -> [String]? {
-        return keys
-    }
-
-    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
-        return 55
-    }
-
-
-    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
-        if section == 0 {
-            return 30
-        }
-        return 10
-    }
-
-
-    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
-        return tableView.dequeueReusableCell(withIdentifier: "JCContacterCell", for: indexPath)
-    }
-
-    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
-        guard let cell = cell as? JCContacterCell else {
-            return
-        }
-        let user = data[keys[indexPath.section]]?[indexPath.row]
-        cell.bindDate(user!)
-    }
-
-    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
-        tableView.deselectRow(at: indexPath, animated: true)
-        selectUser = data[keys[indexPath.section]]?[indexPath.row]
-        var displayName = ""
-        if conversation.ex.isGroup {
-            let group = conversation.target as! JMSGGroup
-            displayName = group.displayName()
-        } else {
-            displayName = conversation.title ?? ""
-        }
-        JCAlertView.bulid().setTitle("发送给:\(displayName)")
-            .setMessage(selectUser.displayName() + "的名片")
-            .setDelegate(self)
-            .addCancelButton("取消")
-            .addButton("确定")
-            .show()
-    }
-}
-
-extension FriendsBusinessCardViewController: UIAlertViewDelegate {
-    func alertView(_ alertView: UIAlertView, clickedButtonAt buttonIndex: Int) {
-        if buttonIndex != 1 {
-            return
-        }
-
-        let message = JMSGMessage.ex.createBusinessCardMessage(conversation, selectUser.username, selectUser.appKey ?? "")
-        JMSGMessage.send(message, optionalContent: JMSGOptionalContent.ex.default)
-        MBProgressHUD_JChat.show(text: "已发送", view: view, 2)
-        weak var weakSelf = self
-        let time: TimeInterval = 2
-        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1) {
-            NotificationCenter.default.post(name: NSNotification.Name(rawValue: kReloadAllMessage), object: nil)
-        }
-        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + time) {
-            weakSelf?.dismiss(animated: true, completion: nil)
-        }
-    }
-}
-
-extension FriendsBusinessCardViewController: UISearchBarDelegate {
-    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
-        filter(searchText)
-    }
-
-//    func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
-//        // 搜索非好友
-//        let searchText = searchBar.text!
-//        JMSGUser.userInfoArray(withUsernameArray: [searchText]) { (result, error) in
-//            if error == nil {
-//                let users = result as! [JMSGUser]
-//                self.searchUser = users.first
-//                self._classify([self.searchUser!])
-//                self.tipsView.isHidden = true
-//            } else {
-//                // 未查询到该用户的信息
-//                self.tipsView.isHidden = false
-//            }
-//        }
-//    }
-}

+ 0 - 136
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/GroupAvatorViewController.swift

@@ -1,136 +0,0 @@
-//
-//  GroupAvatorViewController.swift
-//  JChat
-//
-//  Created by 邓永豪 on 2017/9/19.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-class GroupAvatorViewController: UIViewController {
-
-    var group: JMSGGroup!
-
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        _init()
-    }
-
-    override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
-        navigationController?.navigationBar.shadowImage = UIImage()
-    }
-
-    override func viewWillDisappear(_ animated: Bool) {
-        super.viewWillDisappear(animated)
-        navigationController?.navigationBar.setBackgroundImage(nil, for: .default)
-        navigationController?.navigationBar.shadowImage = nil
-        navigationController?.navigationBar.barTintColor = O2ThemeManager.color(for: "Base.base_color")!
-    }
-
-    fileprivate lazy var imagePicker: UIImagePickerController = {
-        var picker = UIImagePickerController()
-        picker.sourceType = .camera
-        picker.cameraCaptureMode = .photo
-        picker.allowsEditing = true
-        picker.delegate = self
-        return picker
-    }()
-
-    fileprivate lazy var imageView: UIImageView = {
-        var imageView = UIImageView()
-        imageView.frame = UIScreen.main.bounds
-        imageView.contentMode = .scaleAspectFit
-        imageView.contentScaleFactor = UIScreen.main.scale
-        imageView.image = UIImage.loadImage("com_icon_group_50")
-        return imageView
-    }()
-
-    private func _init() {
-        self.title = "群头像"
-        view.backgroundColor = .black
-        _setupNavigation()
-
-        view.addSubview(imageView)
-
-        group.largeAvatarData { (data, id, error) in
-            if let data = data {
-                let image = UIImage(data: data)
-                self.imageView.image = image
-            }
-        }
-    }
-
-    private func _setupNavigation() {
-        let navButton = UIButton(frame: CGRect(x: 0, y: 0, width: 18, height: 18))
-        navButton.setImage(UIImage.loadImage("com_icon_file_more"), for: .normal)
-        navButton.addTarget(self, action: #selector(_more), for: .touchUpInside)
-        let item = UIBarButtonItem(customView: navButton)
-        navigationItem.rightBarButtonItems =  [item]
-    }
-
-    @objc func _more() {
-        let actionSheet = UIActionSheet(title: nil, delegate: self, cancelButtonTitle: "取消", destructiveButtonTitle: nil, otherButtonTitles: "从相册中选择", "拍照")
-        actionSheet.show(in: self.view)
-    }
-}
-
-extension GroupAvatorViewController: UIActionSheetDelegate {
-    func actionSheet(_ actionSheet: UIActionSheet, clickedButtonAt buttonIndex: Int) {
-        switch buttonIndex {
-        case 1:
-            let picker = UIImagePickerController()
-            picker.delegate = self
-            picker.sourceType = .photoLibrary
-            let temp_mediaType = UIImagePickerController.availableMediaTypes(for: picker.sourceType)
-            picker.mediaTypes = temp_mediaType!
-            picker.allowsEditing = true
-            picker.modalTransitionStyle = .coverVertical
-            present(picker, animated: true, completion: nil)
-        case 2:
-            present(imagePicker, animated: true, completion: nil)
-        default:
-            break
-        }
-    }
-}
-
-extension GroupAvatorViewController: UINavigationControllerDelegate, UIImagePickerControllerDelegate {
-
-    // MARK: - UIImagePickerControllerDelegate
-    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
-        picker.dismiss(animated: true, completion: nil)
-    }
-
-    
-    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
-
-        var image = info[UIImagePickerController.InfoKey.editedImage] as! UIImage?
-        image = image?.fixOrientation()
-        if image != nil {
-            MBProgressHUD_JChat.showMessage(message: "正在上传", toView: view)
-
-            guard let imageData = image?.jpegData(compressionQuality: 0.8) else {
-                return
-            }
-            let info = JMSGGroupInfo()
-            info.avatarData = imageData
-            JMSGGroup.updateInfo(withGid: group.gid, groupInfo: info, completionHandler: { (result, error) in
-                DispatchQueue.main.async(execute: { () -> Void in
-                    MBProgressHUD_JChat.hide(forView: self.view, animated: true)
-                    if error == nil {
-                        MBProgressHUD_JChat.show(text: "上传成功", view: self.view)
-                        self.imageView.image = image
-                        NotificationCenter.default.post(name: NSNotification.Name(rawValue: kUpdateGroupInfo), object: nil)
-                    } else {
-                        MBProgressHUD_JChat.show(text: "上传失败", view: self.view)
-                    }
-                })
-            })
-        }
-
-        picker.dismiss(animated: true, completion: nil)
-    }
-}

+ 0 - 160
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/ImageFileViewController.swift

@@ -1,160 +0,0 @@
-//
-//  ImageFileViewController.swift
-//  JChat
-//
-//  Created by 邓永豪 on 2017/8/28.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-var messages: [JMessage] = []
-
-class ImageFileViewController: UIViewController {
-    
-    var isEditModel: Bool {
-        get {
-            return isEdit
-        } set {
-            isEdit = newValue
-            selectMessages = []
-            collectionView.reloadData()
-        }
-    }
-
-    var messages: [JMSGMessage] = []
-    var selectMessages: [JMSGMessage] = []
-    
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        _init()
-    }
-    
-    func reloadDate() {
-        sortMessage()
-        collectionView.reloadData()
-    }
-    
-    fileprivate var isEdit = false
-    private lazy var layout: UICollectionViewFlowLayout = {
-        var layout = UICollectionViewFlowLayout()
-//        layout.sectionInset = UIEdgeInsetsMake(5, 5, 5, 5);
-        layout.minimumInteritemSpacing = 1
-        layout.minimumLineSpacing = 1
-        layout.itemSize = CGSize(width: (self.view.width - 4)  / 4, height: (self.view.width - 4) / 4)
-        return layout
-    }()
-    private lazy var collectionView: UICollectionView = {
-        var collectionView = UICollectionView(frame: .zero, collectionViewLayout: self.layout)
-        collectionView.register(ImageFileCell.self, forCellWithReuseIdentifier:"ImageFileCell")
-        collectionView.delegate = self;
-        collectionView.dataSource = self;
-        collectionView.backgroundColor = UIColor(netHex: 0xe8edf3)
-        return collectionView
-    }()
-    let headerHeight = 30
-    let headerIdentifier = "headView"
-    
-    fileprivate lazy var data: Dictionary<String, [JMSGMessage]> = Dictionary()
-    fileprivate lazy var keys: [String] = []
-    
-    private func _init() {
-        view.backgroundColor = UIColor(netHex: 0xe8edf3)
-        
-        view.addSubview(collectionView)
-        collectionView.register(ImageFileHeader.classForCoder(), forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: headerIdentifier)
-        
-        view.addConstraint(_JCLayoutConstraintMake(collectionView, .left, .equal, view, .left))
-        view.addConstraint(_JCLayoutConstraintMake(collectionView, .top, .equal, view, .top))
-        view.addConstraint(_JCLayoutConstraintMake(collectionView, .right, .equal, view, .right))
-        view.addConstraint(_JCLayoutConstraintMake(collectionView, .bottom, .equal, view, .bottom))
-        
-    }
-    
-    func sortMessage() {
-        for message in messages {
-            let formatter = DateFormatter()
-            formatter.dateFormat = "yyyy-MM";
-            let date = Date(timeIntervalSince1970: TimeInterval(message.timestamp.intValue / 1000))
-            let key = formatter.string(from: date)
-            var array = data[key]
-            if array == nil {
-                array = [message]
-            } else {
-                array?.append(message)
-            }
-            if !keys.contains(key) {
-                keys.append(key)
-            }
-            
-            data[key] = array
-        }
-        keys = keys.sorted(by: { (str1, str2) -> Bool in
-            str1 > str2
-        })
-    }
-}
-
-
-extension ImageFileViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
-
-    func numberOfSections(in collectionView: UICollectionView) -> Int {
-        
-        return keys.count
-    }
-    
-    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
-        return data[keys[section]]!.count
-    }
-    
-    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
-        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ImageFileCell", for: indexPath) as! ImageFileCell
-        let message = data[keys[indexPath.section]]![indexPath.row]
-        cell.bindDate(message)
-        cell.isEditMode = isEdit
-        if !isEditModel {
-            cell.isSelectImage = false
-        }
-        return cell
-    }
-    
-    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize{
-        return CGSize(width: view.width, height: 26)
-    }
-    
-    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView{
-        var v = ImageFileHeader()
-        if kind == UICollectionView.elementKindSectionHeader{
-            v = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerIdentifier, for: indexPath) as! ImageFileHeader
-            
-            v.titleLabel?.text = keys[indexPath.section]
-        }
-        return v
-    }
-    
-    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
-        guard let cell = collectionView.cellForItem(at: indexPath) as? ImageFileCell else {
-            return
-        }
-        let message = data[keys[indexPath.section]]![indexPath.row]
-        if cell.isEditMode {
-            if cell.isSelectImage {
-                selectMessages = selectMessages.filter({ (m) -> Bool in
-                    message.msgId != m.msgId
-                })
-            } else {
-                selectMessages.append(message)
-            }
-            cell.isSelectImage = !cell.isSelectImage
-            NotificationCenter.default.post(name: NSNotification.Name(rawValue: "kDidSelectFileMessage"), object: nil)
-        } else {
-            if let image = cell.imageView.image {
-                let browserImageVC = JCImageBrowserViewController()
-                browserImageVC.imageArr = [image]
-                browserImageVC.imgCurrentIndex = 0
-                self.present(browserImageVC, animated: true) {}
-            }
-        }
-    }
-    
-}

+ 0 - 1347
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/JCChatViewController.swift

@@ -1,1347 +0,0 @@
-//
-//  JCChatViewController.swift
-//  JChat
-//
-//  Created by deng on 2017/2/28.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-import YHPhotoKit
-import MobileCoreServices
-
-class JCChatViewController: UIViewController {
-    
-    open var conversation: JMSGConversation
-    fileprivate var isGroup = false
-    
-    //MARK - life cycle
-    public required init(conversation: JMSGConversation) {
-        self.conversation = conversation
-        super.init(nibName: nil, bundle: nil)
-        automaticallyAdjustsScrollViewInsets = false;
-        if let draft = JCDraft.getDraft(conversation) {
-            self.draft = draft
-        }
-    }
-    
-    required init?(coder aDecoder: NSCoder) {
-        fatalError("init(coder:) has not been implemented")
-    }
-
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        _init()
-    }
-    
-    override func loadView() {
-        super.loadView()
-        // y:64 - y:0
-        let frame = CGRect(x: 0, y: 0, width: self.view.width, height: self.view.height - 64)
-        chatView = JCChatView(frame: frame, chatViewLayout: chatViewLayout)
-        chatView.delegate = self
-        chatView.messageDelegate = self
-        toolbar.translatesAutoresizingMaskIntoConstraints = false
-        toolbar.delegate = self
-        toolbar.text = draft
-    }
-    
-    override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        toolbar.isHidden = false
-    }
-    
-    override func viewWillDisappear(_ animated: Bool) {
-        super.viewWillDisappear(animated)
-        NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
-    }
-    
-    override func viewDidAppear(_ animated: Bool) {
-        super.viewDidAppear(animated)
-        NotificationCenter.default.addObserver(self, selector: #selector(keyboardFrameChanged(_:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
-        if let group = conversation.target as? JMSGGroup {
-            self.title = group.displayName()
-        }
-        navigationController?.interactivePopGestureRecognizer?.delegate = self
-        navigationController?.navigationBar.barTintColor = base_color
-        navigationController?.navigationBar.tintColor = navbar_tint_color
-    }
-    
-    override func viewDidDisappear(_ animated: Bool) {
-        super.viewDidDisappear(animated)
-//        navigationController?.navigationBar.isTranslucent = true
-        JCDraft.update(text: toolbar.text, conversation: conversation)
-    }
-    
-    deinit {
-        NotificationCenter.default.removeObserver(self)
-        JMessage.remove(self, with: conversation)
-    }
-    
-    private var draft: String?
-    fileprivate lazy var toolbar: SAIInputBar = SAIInputBar(type: .default)
-    fileprivate lazy var inputViews: [String: UIView] = [:]
-    fileprivate weak var inputItem: SAIInputItem?
-    var chatViewLayout: JCChatViewLayout = .init()
-    var chatView: JCChatView!
-    fileprivate lazy var reminds: [JCRemind] = []
-    fileprivate lazy var documentInteractionController = UIDocumentInteractionController()
-    
-    fileprivate lazy var imagePicker: UIImagePickerController = {
-        var picker = UIImagePickerController()
-        picker.sourceType = .camera
-        picker.cameraCaptureMode = .photo
-        picker.delegate = self
-        return picker
-    }()
-    
-    fileprivate lazy var videoPicker: UIImagePickerController = {
-        var picker = UIImagePickerController()
-        picker.mediaTypes = [kUTTypeMovie as String]
-        picker.sourceType = .camera
-        picker.cameraCaptureMode = .video
-        picker.videoMaximumDuration = 10
-        picker.delegate = self
-        return picker
-    }()
-    
-    fileprivate lazy var _emoticonGroups: [JCCEmoticonGroup] = {
-        var groups: [JCCEmoticonGroup] = []
-        if let group = JCCEmoticonGroup(identifier: "com.apple.emoji") {
-            groups.append(group)
-        }
-        if let group = JCCEmoticonGroup(identifier: "cn.jchat.guangguang") {
-            groups.append(group)
-        }
-        return groups
-    }()
-    fileprivate lazy var _emoticonSendBtn: UIButton = {
-        var button = UIButton()
-        button.titleLabel?.font = UIFont.systemFont(ofSize: 15)
-        button.contentEdgeInsets = UIEdgeInsets(top: 0, left: 10 + 8, bottom: 0, right: 8)
-        button.setTitle("发送", for: .normal)
-        button.setTitleColor(.white, for: .normal)
-        button.setBackgroundImage(UIImage.loadImage("chat_emoticon_btn_send_blue"), for: .normal)
-        button.setBackgroundImage(UIImage.loadImage("chat_emoticon_btn_send_gray"), for: .disabled)
-        button.addTarget(self, action: #selector(_sendHandler), for: .touchUpInside)
-        return button
-    }()
-    fileprivate lazy var emoticonView: JCEmoticonInputView = {
-        let emoticonView = JCEmoticonInputView(frame: CGRect(x: 0, y: 0, width: self.view.width, height: 275))
-        emoticonView.delegate = self
-        emoticonView.dataSource = self
-        return emoticonView
-    }()
-    
-    fileprivate lazy var toolboxView: SAIToolboxInputView = {
-        var toolboxView = SAIToolboxInputView(frame: CGRect(x: 0, y: 0, width: self.view.width, height: 197))
-        toolboxView.delegate = self
-        toolboxView.dataSource = self
-        return toolboxView
-    }()
-    fileprivate lazy var _toolboxItems: [SAIToolboxItem] = {
-        return [
-            SAIToolboxItem("page:pic", "照片", UIImage.loadImage("chat_tool_pic")),
-            SAIToolboxItem("page:camera", "拍照", UIImage.loadImage("chat_tool_camera")),
-            SAIToolboxItem("page:video_s", "小视频", UIImage.loadImage("chat_tool_video_short")),
-            SAIToolboxItem("page:location", "位置", UIImage.loadImage("chat_tool_location")),
-            SAIToolboxItem("page:businessCard", "名片", UIImage.loadImage("chat_tool_businessCard")),
-            ]
-    }()
-    
-    fileprivate var myAvator: UIImage?
-    lazy var messages: [JCMessage] = []
-    fileprivate let currentUser = JMSGUser.myInfo()
-    fileprivate var messagePage = 0
-    fileprivate var currentMessage: JCMessageType!
-    fileprivate var maxTime = 0
-    fileprivate var minTime = 0
-    fileprivate var minIndex = 0
-    fileprivate var jMessageCount = 0
-    fileprivate var isFristLaunch = true
-    fileprivate var recordingHub: JCRecordingView!
-    fileprivate lazy var recordHelper: JCRecordVoiceHelper = {
-        let recordHelper = JCRecordVoiceHelper()
-        recordHelper.delegate = self
-        return recordHelper
-    }()
-    fileprivate lazy var leftButton: UIButton = {
-        let leftButton = UIButton(frame: CGRect(x: 0, y: 0, width: 90, height: 65 / 3))
-        leftButton.setImage(UIImage.loadImage("com_icon_back"), for: .normal)
-        leftButton.setImage(UIImage.loadImage("com_icon_back"), for: .highlighted)
-        leftButton.addTarget(self, action: #selector(_back), for: .touchUpInside)
-        leftButton.setTitle("会话", for: .normal)
-        leftButton.titleLabel?.font = UIFont.systemFont(ofSize: 16)
-        leftButton.contentHorizontalAlignment = .left
-        return leftButton
-    }()
-    
-    private func _init() {
-        myAvator = UIImage.getMyAvator()
-        isGroup = conversation.ex.isGroup
-        _updateTitle()
-        view.backgroundColor = .white
-        JMessage.add(self, with: conversation)
-        _setupNavigation()
-        _loadMessage(messagePage)
-        let tap = UITapGestureRecognizer(target: self, action: #selector(_tapView))
-        tap.delegate = self
-        chatView.addGestureRecognizer(tap)
-        view.addSubview(chatView)
-        
-        _updateBadge()
-        
-        NotificationCenter.default.addObserver(self, selector: #selector(keyboardFrameChanged(_:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
-        NotificationCenter.default.addObserver(self, selector: #selector(_removeAllMessage), name: NSNotification.Name(rawValue: kDeleteAllMessage), object: nil)
-        NotificationCenter.default.addObserver(self, selector: #selector(_reloadMessage), name: NSNotification.Name(rawValue: kReloadAllMessage), object: nil)
-        NotificationCenter.default.addObserver(self, selector: #selector(_updateFileMessage(_:)), name: NSNotification.Name(rawValue: kUpdateFileMessage), object: nil)
-    }
-    
-    @objc func _updateFileMessage(_ notification: Notification) {
-        let userInfo = notification.userInfo
-        let msgId = userInfo?[kUpdateFileMessage] as! String
-        let message = conversation.message(withMessageId: msgId)!
-        let content = message.content as! JMSGFileContent
-        let url = URL(fileURLWithPath: content.originMediaLocalPath ?? "")
-        let data = try! Data(contentsOf: url)
-        updateMediaMessage(message, data: data)
-    }
-    
-    private func _updateTitle() {
-        if let group = conversation.target as? JMSGGroup {
-            title = group.displayName()
-        } else {
-            title = conversation.title
-        }
-    }
-
-
-    @objc func _reloadMessage() {
-        _removeAllMessage()
-        messagePage = 0
-        _loadMessage(messagePage)
-        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1) {
-            self.chatView.scrollToLast(animated: false)
-        }
-    }
-    
-    @objc func _removeAllMessage() {
-        jMessageCount = 0
-        messages.removeAll()
-        chatView.removeAll()
-    }
-    
-    @objc func _tapView() {
-        view.endEditing(true)
-        toolbar.resignFirstResponder()
-    }
-    
-    private func _setupNavigation() {
-        let navButton = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
-        if isGroup {
-            navButton.setImage(UIImage.loadImage("com_icon_group_w"), for: .normal)
-            navButton.addTarget(self, action: #selector(_getGroupInfo), for: .touchUpInside)
-        } else {
-            navButton.setImage(UIImage.loadImage("com_icon_user_w"), for: .normal)
-            navButton.addTarget(self, action: #selector(_getSingleInfo), for: .touchUpInside)
-        }
-        let item1 = UIBarButtonItem(customView: navButton)
-        navigationItem.rightBarButtonItems =  [item1]
-
-        let item2 = UIBarButtonItem(customView: leftButton)
-        navigationItem.leftBarButtonItems =  [item2]
-       
-        navigationController?.interactivePopGestureRecognizer?.isEnabled = true
-        navigationController?.interactivePopGestureRecognizer?.delegate = self
-    }
-    
-    @objc func _back() {
-        navigationController?.popViewController(animated: true)
-    }
-    
-    fileprivate func _loadMessage(_ page: Int) {
-
-        let messages = conversation.messageArrayFromNewest(withOffset: NSNumber(value: jMessageCount), limit: NSNumber(value: 17))
-        if messages.count == 0 {
-            return
-        }
-        var msgs: [JCMessage] = []
-        for index in 0..<messages.count {
-            let message = messages[index]
-            let msg = _parseMessage(message)
-            msgs.insert(msg, at: 0)
-            if isNeedInsertTimeLine(message.timestamp.intValue) || index == messages.count - 1 {
-                let timeContent = JCMessageTimeLineContent(date: Date(timeIntervalSince1970: TimeInterval(message.timestamp.intValue / 1000)))
-                let m = JCMessage(content: timeContent)
-                m.options.showsTips = false
-                msgs.insert(m, at: 0)
-            }
-        }
-        if page != 0 {
-            minIndex = minIndex + msgs.count
-            chatView.insert(contentsOf: msgs, at: 0)
-        } else {
-            minIndex = msgs.count - 1
-            chatView.append(contentsOf: msgs)
-        }
-        self.messages.insert(contentsOf: msgs, at: 0)
-    }
-    
-    private func isNeedInsertTimeLine(_ time: Int) -> Bool {
-        if maxTime == 0 || minTime == 0 {
-            maxTime = time
-            minTime = time
-            return true
-        }
-        if (time - maxTime) >= 5 * 60000 {
-            maxTime = time
-            return true
-        }
-        if (minTime - time) >= 5 * 60000 {
-            minTime = time
-            return true
-        }
-        return false
-    }
-    
-    // MARK: - parse message
-    fileprivate func _parseMessage(_ message: JMSGMessage, _ isNewMessage: Bool = true) -> JCMessage {
-        if isNewMessage {
-            jMessageCount += 1
-        }
-        return message.parseMessage(self, { [weak self] (message, data) in
-            self?.updateMediaMessage(message, data: data)
-        })
-    }
-
-    // MARK: - send message
-    func send(_ message: JCMessage, _ jmessage: JMSGMessage) {
-        if isNeedInsertTimeLine(jmessage.timestamp.intValue) {
-            let timeContent = JCMessageTimeLineContent(date: Date(timeIntervalSince1970: TimeInterval(jmessage.timestamp.intValue / 1000)))
-            let m = JCMessage(content: timeContent)
-            m.options.showsTips = false
-            messages.append(m)
-            chatView.append(m)
-        }
-        message.msgId = jmessage.msgId
-        message.name = currentUser.displayName()
-        message.senderAvator = myAvator
-        message.sender = currentUser
-        message.options.alignment = .right
-        message.options.state = .sending
-        if let group = conversation.target as? JMSGGroup {
-            message.targetType = .group
-            message.unreadCount = group.memberArray().count - 1
-        } else {
-            message.targetType = .single
-            message.unreadCount = 1
-        }
-        chatView.append(message)
-        messages.append(message)
-        chatView.scrollToLast(animated: false)
-        conversation.send(jmessage, optionalContent: JMSGOptionalContent.ex.default)
-    }
-
-    func send(forText text: NSAttributedString) {
-        let message = JCMessage(content: JCMessageTextContent(attributedText: text))
-        let content = JMSGTextContent(text: text.string)
-        let msg = JMSGMessage.ex.createMessage(conversation, content, reminds)
-        reminds.removeAll()
-        send(message, msg)
-    }
-    
-    func send(forLargeEmoticon emoticon: JCCEmoticonLarge) {
-        guard let image = emoticon.contents as? UIImage else {
-            return
-        }
-        let messageContent = JCMessageImageContent()
-        messageContent.image = image
-        messageContent.delegate = self
-        let message = JCMessage(content: messageContent)
-        
-        let content = JMSGImageContent(imageData: image.pngData()!)
-        let msg = JMSGMessage.ex.createMessage(conversation, content!, nil)
-        msg.ex.isLargeEmoticon = true
-        message.options.showsTips = true
-        send(message, msg)
-    }
-    
-    func send(forImage image: UIImage) {
-        let data = image.jpegData(compressionQuality: 1)
-        let content = JMSGImageContent(imageData: data!)
-
-        let message = JMSGMessage.ex.createMessage(conversation, content!, nil)
-        let imageContent = JCMessageImageContent()
-        imageContent.delegate = self
-        imageContent.image = image
-        content?.uploadHandler = {  (percent:Float, msgId:(String?)) -> Void in
-            imageContent.upload?(percent)
-        }
-        let msg = JCMessage(content: imageContent)
-        send(msg, message)
-    }
-    
-    func send(voiceData: Data, duration: Double) {
-        let voiceContent = JCMessageVoiceContent()
-        voiceContent.data = voiceData
-        voiceContent.duration = duration
-        voiceContent.delegate = self
-        let content = JMSGVoiceContent(voiceData: voiceData, voiceDuration: NSNumber(value: duration))
-        let message = JMSGMessage.ex.createMessage(conversation, content, nil)
-        
-        let msg = JCMessage(content: voiceContent)
-        send(msg, message)
-    }
-    
-    func send(fileData: Data) {
-        let videoContent = JCMessageVideoContent()
-        videoContent.data = fileData
-        videoContent.delegate = self
-        
-        let content = JMSGFileContent(fileData: fileData, fileName: "小视频")
-        let message = JMSGMessage.ex.createMessage(conversation, content, nil)
-        message.ex.isShortVideo = true
-        let msg = JCMessage(content: videoContent)
-        send(msg, message)
-    }
-    
-    func send(address: String, lon: NSNumber, lat: NSNumber) {
-        let locationContent = JCMessageLocationContent()
-        locationContent.address = address
-        locationContent.lat = lat.doubleValue
-        locationContent.lon = lon.doubleValue
-        locationContent.delegate = self
-        
-        let content = JMSGLocationContent(latitude: lat, longitude: lon, scale: NSNumber(value: 1), address: address)
-        let message = JMSGMessage.ex.createMessage(conversation, content, nil)
-        let msg = JCMessage(content: locationContent)
-        send(msg, message)
-    }
-    
-    @objc func keyboardFrameChanged(_ notification: Notification) {
-        let dic = NSDictionary(dictionary: (notification as NSNotification).userInfo!)
-        let keyboardValue = dic.object(forKey: UIResponder.keyboardFrameEndUserInfoKey) as! NSValue
-        let bottomDistance = UIScreen.main.bounds.size.height - keyboardValue.cgRectValue.origin.y
-        let duration = Double(dic.object(forKey: UIResponder.keyboardAnimationDurationUserInfoKey) as! NSNumber)
-        
-        UIView.animate(withDuration: duration, animations: {
-        }) { (finish) in
-            if (bottomDistance == 0 || bottomDistance == self.toolbar.height) && !self.isFristLaunch {
-                return
-            }
-            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()) {
-                self.chatView.scrollToLast(animated: false)
-            }
-            self.isFristLaunch = false
-        }
-    }
-    
-    @objc func _sendHandler() {
-        let text = toolbar.attributedText
-        if text != nil && (text?.length)! > 0 {
-            send(forText: text!)
-            toolbar.attributedText = nil
-        }
-    }
-    
-    @objc func _getSingleInfo() {
-//        let vc = JCSingleSettingViewController()
-//        vc.user = conversation.target as? JMSGUser
-//        navigationController?.pushViewController(vc, animated: true)
-        guard let uid = (conversation.target as? JMSGUser)?.username else {
-            return
-        }
-        goToPerson(uid: uid)
-    }
-    
-    @objc func _getGroupInfo() {
-        let vc = JCGroupSettingViewController()
-        let group = conversation.target as? JMSGGroup
-        vc.group = group
-        navigationController?.pushViewController(vc, animated: true)
-    }
-}
-
-//MARK: - JMSGMessage Delegate
-extension JCChatViewController: JMessageDelegate {
-    
-    fileprivate func updateMediaMessage(_ message: JMSGMessage, data: Data) {
-        DispatchQueue.main.async {
-            if let index = self.messages.index(message) {
-                let msg = self.messages[index]
-                switch(message.contentType) {
-                case .file:
-                    if message.ex.isShortVideo {
-                        let videoContent = msg.content as! JCMessageVideoContent
-                        videoContent.data = data
-                        videoContent.delegate = self
-                        msg.content = videoContent
-                    } else {
-                        let fileContent = msg.content as! JCMessageFileContent
-                        fileContent.data = data
-                        fileContent.delegate = self
-                        msg.content = fileContent
-                    }
-                case .image:
-                    let imageContent = msg.content as! JCMessageImageContent
-                    let image = UIImage(data: data)
-                    imageContent.image = image
-                    msg.content = imageContent
-                default: break
-                }
-                msg.updateSizeIfNeeded = true
-                self.chatView.update(msg, at: index)
-                msg.updateSizeIfNeeded = false
-//                self.chatView.update(msg, at: index)
-            }
-        }
-    }
-    
-    func _updateBadge() {
-        JMSGConversation.allConversations { (result, error) in
-            guard let conversations = result as? [JMSGConversation] else {
-                return
-            }
-            let count = conversations.unreadCount
-            if count == 0 {
-                self.leftButton.setTitle("会话", for: .normal)
-            } else {
-                self.leftButton.setTitle("会话(\(count))", for: .normal)
-            }
-        }
-    }
-    
-    func onReceive(_ message: JMSGMessage!, error: Error!) {
-        if error != nil {
-            return
-        }
-        let message = _parseMessage(message)
-        // TODO: 这个判断是sdk bug导致的,暂时只能这么改
-        if messages.contains(where: { (m) -> Bool in
-            return m.msgId == message.msgId
-        }) {
-            let indexs = chatView.indexPathsForVisibleItems
-            for index in indexs {
-                var m = messages[index.row]
-                if !m.msgId.isEmpty {
-                    m = _parseMessage(conversation.message(withMessageId: m.msgId)!, false)
-                    chatView.update(m, at: index.row)
-                }
-            }
-            return
-        }
-        
-        messages.append(message)
-        chatView.append(message)
-        updateUnread([message])
-        conversation.clearUnreadCount()
-        if !chatView.isRoll {
-            chatView.scrollToLast(animated: true)
-        }
-        _updateBadge()
-    }
-    
-    func onSendMessageResponse(_ message: JMSGMessage!, error: Error!) {
-        if let error = error as NSError? {
-            if error.code == 803009 {
-                MBProgressHUD_JChat.show(text: "发送失败,消息中包含敏感词", view: view, 2.0)
-            }
-            if error.code == 803005 {
-                MBProgressHUD_JChat.show(text: "您已不是群成员", view: view, 2.0)
-            }
-        }
-        if let index = messages.index(message) {
-            let msg = messages[index]
-            msg.options.state = message.ex.state
-            chatView.update(msg, at: index)
-        }
-    }
-    
-    func onReceive(_ retractEvent: JMSGMessageRetractEvent!) {
-        if let index = messages.index(retractEvent.retractMessage) {
-            let msg = _parseMessage(retractEvent.retractMessage, false)
-            messages[index] = msg
-            chatView.update(msg, at: index)
-        }
-    }
-    
-    func onSyncOfflineMessageConversation(_ conversation: JMSGConversation!, offlineMessages: [JMSGMessage]!) {
-        let msgs = offlineMessages.sorted(by: { (m1, m2) -> Bool in
-            return m1.timestamp.intValue < m2.timestamp.intValue
-        })
-        for item in msgs {
-            let message = _parseMessage(item)
-            messages.append(message)
-            chatView.append(message)
-            updateUnread([message])
-            conversation.clearUnreadCount()
-            if !chatView.isRoll {
-                chatView.scrollToLast(animated: true)
-            }
-        }
-        _updateBadge()
-    }
-    
-    func onReceive(_ receiptEvent: JMSGMessageReceiptStatusChangeEvent!) {
-        for message in receiptEvent.messages! {
-            if let index = messages.index(message) {
-                let msg = messages[index]
-                msg.unreadCount = message.getUnreadCount()
-                chatView.update(msg, at: index)
-            }
-        }
-    }
-}
-
-// MARK: - JCEmoticonInputViewDataSource & JCEmoticonInputViewDelegate
-extension JCChatViewController: JCEmoticonInputViewDataSource, JCEmoticonInputViewDelegate {
-    
-    open func numberOfEmotionGroups(in emoticon: JCEmoticonInputView) -> Int {
-        return _emoticonGroups.count
-    }
-
-    open func emoticon(_ emoticon: JCEmoticonInputView, emotionGroupForItemAt index: Int) -> JCEmoticonGroup {
-        return _emoticonGroups[index]
-    }
-
-    open func emoticon(_ emoticon: JCEmoticonInputView, numberOfRowsForGroupAt index: Int) -> Int {
-        return _emoticonGroups[index].rows
-    }
-
-    open func emoticon(_ emoticon: JCEmoticonInputView, numberOfColumnsForGroupAt index: Int) -> Int {
-        return _emoticonGroups[index].columns
-    }
-
-    open func emoticon(_ emoticon: JCEmoticonInputView, moreViewForGroupAt index: Int) -> UIView? {
-        if _emoticonGroups[index].type.isSmall {
-            return _emoticonSendBtn
-        } else {
-            return nil
-        }
-    }
-
-    open func emoticon(_ emoticon: JCEmoticonInputView, insetForGroupAt index: Int) -> UIEdgeInsets {
-        return UIEdgeInsets(top: 12, left: 10, bottom: 12 + 24, right: 10)
-    }
-
-    open func emoticon(_ emoticon: JCEmoticonInputView, didSelectFor item: JCEmoticon) {
-        if item.isBackspace {
-            toolbar.deleteBackward()
-            return
-        }
-        if let emoticon = item as? JCCEmoticonLarge {
-            send(forLargeEmoticon: emoticon)
-            return
-        }
-        if let code = item.contents as? String {
-            return toolbar.insertText(code)
-        }
-        if let image = item.contents as? UIImage {
-            let d = toolbar.font?.descender ?? 0
-            let h = toolbar.font?.lineHeight ?? 0
-            let attachment = NSTextAttachment()
-            attachment.image = image
-            attachment.bounds = CGRect(x: 0, y: d, width: h, height: h)
-            toolbar.insertAttributedText(NSAttributedString(attachment: attachment))
-            return
-        }
-    }
-}
-
-// MARK: - SAIToolboxInputViewDataSource & SAIToolboxInputViewDelegate
-extension JCChatViewController: SAIToolboxInputViewDataSource, SAIToolboxInputViewDelegate {
-    
-    open func numberOfToolboxItems(in toolbox: SAIToolboxInputView) -> Int {
-        return _toolboxItems.count
-    }
-    open func toolbox(_ toolbox: SAIToolboxInputView, toolboxItemForItemAt index: Int) -> SAIToolboxItem {
-        return _toolboxItems[index]
-    }
-    
-    open func toolbox(_ toolbox: SAIToolboxInputView, numberOfRowsForSectionAt index: Int) -> Int {
-        return 2
-    }
-    open func toolbox(_ toolbox: SAIToolboxInputView, numberOfColumnsForSectionAt index: Int) -> Int {
-        return 4
-    }
-    open func toolbox(_ toolbox: SAIToolboxInputView, insetForSectionAt index: Int) -> UIEdgeInsets {
-        return UIEdgeInsets(top: 12, left: 10, bottom: 12, right: 10)
-    }
-    open func toolbox(_ toolbox: SAIToolboxInputView, shouldSelectFor item: SAIToolboxItem) -> Bool {
-        return true
-    }
-    private func _pushToSelectPhotos() {
-//        let vc = YHPhotoPickerViewController()
-//        vc.maxPhotosCount = 9;
-//        vc.pickerDelegate = self
-//        present(vc, animated: true)
-        
-        
-        let vc = FileBSImagePickerViewController().bsImagePicker()
-        presentImagePicker(vc, select: { (asset: PHAsset) -> Void in
-                                            // User selected an asset.
-                                            // Do something with it, start upload perhaps?
-        }, deselect: { (asset: PHAsset) -> Void in
-            // User deselected an assets.
-            // Do something, cancel upload?
-        }, cancel: { (assets: [PHAsset]) -> Void in
-            // User cancelled. And this where the assets currently selected.
-        }, finish: { (assets: [PHAsset]) -> Void in
-//            for item in photos {
-//                guard let photo = item as? UIImage else {
-//                    return
-//                }
-//                DispatchQueue.main.async {
-//                    self.send(forImage: photo)
-//                }
-//            }
-            
-            for asset in assets {
-                if asset.mediaType == .image {
-                    let options = PHImageRequestOptions()
-                    options.isSynchronous = true
-                    options.deliveryMode = .fastFormat
-                    options.resizeMode = .none
-                    PHImageManager.default().requestImage(for: asset, targetSize: PHImageManagerMaximumSize, contentMode: .default, options: options, resultHandler: { (image, array) in
-                        guard let uiimage = image else {
-                            return
-                        }
-                        DispatchQueue.main.async {
-                            self.send(forImage: uiimage)
-                        }
-                    })
-                }
-            }
-        }, completion: nil)
-        
-        
-        
-        
-        
-    }
-    open func toolbox(_ toolbox: SAIToolboxInputView, didSelectFor item: SAIToolboxItem) {
-        toolbar.resignFirstResponder()
-        switch item.identifier {
-        case "page:pic":
-            if PHPhotoLibrary.authorizationStatus() != .authorized {
-                PHPhotoLibrary.requestAuthorization({ (status) in
-                    DispatchQueue.main.sync {
-                        if status != .authorized {
-                            self.gotoApplicationSettings(alertMessage: "无权限访问照片,请在设备的设置中允许访问照片?")
-                        } else {
-                            self._pushToSelectPhotos()
-                        }
-                    }
-                })
-            } else {
-                self._pushToSelectPhotos()
-            }
-        case "page:camera":
-            present(imagePicker, animated: true, completion: nil)
-        case "page:video_s":
-            present(videoPicker, animated: true, completion: nil)
-        case "page:location":
-            let vc = JCAddMapViewController()
-            vc.addressBlock = { (dict: Dictionary?) in
-                if dict != nil {
-                    let lon = Float(dict?["lon"] as! String)
-                    let lat = Float(dict?["lat"] as! String)
-                    let address = dict?["address"] as! String
-                    self.send(address: address, lon: NSNumber(value: lon!), lat: NSNumber(value: lat!))
-                }
-            }
-            navigationController?.pushViewController(vc, animated: true)
-        case "page:businessCard":
-            let vc = FriendsBusinessCardViewController()
-            vc.conversation = conversation
-            let nav = JCNavigationController(rootViewController: vc)
-            present(nav, animated: true, completion: {
-                self.toolbar.isHidden = true
-            })
-        default:
-            break
-        }
-    }
-    
-    open override func present(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)? = nil) {
-        super.present(viewControllerToPresent, animated: flag, completion: completion)
-    }
-}
-
-// MARK: - UIImagePickerControllerDelegate & YHPhotoPickerViewControllerDelegate
-extension JCChatViewController: YHPhotoPickerViewControllerDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
-    func selectedPhotoBeyondLimit(_ count: Int32, currentView view: UIView!) {
-        MBProgressHUD_JChat.show(text: "最多选择\(count)张图片", view: nil)
-    }
-    
-    func yhPhotoPickerViewController(_ PhotoPickerViewController: YHSelectPhotoViewController!, selectedPhotos photos: [Any]!) {
-        for item in photos {
-            guard let photo = item as? UIImage else {
-                return
-            }
-            DispatchQueue.main.async {
-                self.send(forImage: photo)
-            }
-        }
-    }
-    
-    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
-        picker.dismiss(animated: true, completion: nil)
-    }
-    
-    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
-        picker.dismiss(animated: true, completion: nil)
-        let image = info[UIImagePickerController.InfoKey.originalImage] as! UIImage?
-        if let image = image?.fixOrientation() {
-            send(forImage: image)
-        }
-        let videoUrl = info[UIImagePickerController.InfoKey.mediaURL] as! URL?
-        if videoUrl != nil {
-            let data = try! Data(contentsOf: videoUrl!)
-            send(fileData: data)
-        }
-    }
-}
-
-// MARK: - JCMessageDelegate
-extension JCChatViewController: JCMessageDelegate {
-
-    func message(message: JCMessageType, videoData data: Data?) {
-        if let data = data {
-            JCVideoManager.playVideo(data: data, currentViewController: self)
-        }
-    }
-
-    func message(message: JCMessageType, location address: String?, lat: Double, lon: Double) {
-        let vc = JCAddMapViewController()
-        vc.isOnlyShowMap = true
-        vc.lat = lat
-        vc.lon = lon
-        navigationController?.pushViewController(vc, animated: true)
-    }
-    
-    func message(message: JCMessageType, image: UIImage?) {
-        let browserImageVC = JCImageBrowserViewController()
-        browserImageVC.messages = messages
-        browserImageVC.conversation = conversation
-        browserImageVC.currentMessage = message
-        present(browserImageVC, animated: true) {
-            self.toolbar.isHidden = true
-        }
-    }
-    
-    func message(message: JCMessageType, fileData data: Data?, fileName: String?, fileType: String?) {
-        if data == nil {
-            let vc = JCFileDownloadViewController()
-            vc.title = fileName
-            let msg = conversation.message(withMessageId: message.msgId)
-            vc.fileSize = msg?.ex.fileSize
-            vc.message = msg
-            navigationController?.pushViewController(vc, animated: true)
-        } else {
-            guard let fileType = fileType else {
-                return
-            }
-            let msg = conversation.message(withMessageId: message.msgId)!
-            let content = msg.content as! JMSGFileContent
-            switch fileType.fileFormat() {
-            case .document:
-                let vc = JCDocumentViewController()
-                vc.title = fileName
-                vc.fileData = data
-                vc.filePath = content.originMediaLocalPath
-                vc.fileType = fileType
-                navigationController?.pushViewController(vc, animated: true)
-            case .video, .voice:
-                let url = URL(fileURLWithPath: content.originMediaLocalPath ?? "")
-                try! JCVideoManager.playVideo(data: Data(contentsOf: url), fileType, currentViewController: self)
-            case .photo:
-                let browserImageVC = JCImageBrowserViewController()
-                let image = UIImage(contentsOfFile: content.originMediaLocalPath ?? "")
-                browserImageVC.imageArr = [image!]
-                browserImageVC.imgCurrentIndex = 0
-                present(browserImageVC, animated: true) {
-                    self.toolbar.isHidden = true
-                }
-            default:
-                let url = URL(fileURLWithPath: content.originMediaLocalPath ?? "")
-                documentInteractionController.url = url
-                documentInteractionController.presentOptionsMenu(from: .zero, in: self.view, animated: true)
-            }
-        }
-    }
-
-    func message(message: JCMessageType, user: JMSGUser?, businessCardName: String, businessCardAppKey: String) {
-        if let user = user {
-            let vc = JCUserInfoViewController()
-            vc.user = user
-            navigationController?.pushViewController(vc, animated: true)
-        }
-    }
-    
-    func clickTips(message: JCMessageType) {
-        currentMessage = message
-//        let alertView = UIAlertView(title: "重新发送", message: "是否重新发送该消息?", delegate: self, cancelButtonTitle: "取消", otherButtonTitles: "发送")
-        let okAction = UIAlertAction(title: "发送", style: .default) { (action) in
-            if let index = self.messages.index(self.currentMessage) {
-                self.messages.remove(at: index)
-                self.chatView.remove(at: index)
-                let msg = self.conversation.message(withMessageId: self.currentMessage.msgId)
-                self.currentMessage.options.state = .sending
-                
-                if let msg = msg {
-                    if let content = self.currentMessage.content as? JCMessageImageContent,
-                        let imageContent = msg.content as? JMSGImageContent
-                    {
-                        imageContent.uploadHandler = {  (percent:Float, msgId:(String?)) -> Void in
-                            content.upload?(percent)
-                        }
-                    }
-                }
-                self.messages.append(self.currentMessage as! JCMessage)
-                self.chatView.append(self.currentMessage)
-                self.conversation.send(msg!, optionalContent: JMSGOptionalContent.ex.default)
-                self.chatView.scrollToLast(animated: true)
-            }
-        }
-        let cancelAction = UIAlertAction(title: "取消", style: .cancel) { (action) in
-            //
-        }
-        self.showDefaultConfirm(title: "重新发送", message: "是否重新发送该消息?", okAction: okAction, cancelAction: cancelAction)
-//        alertView.show()
-    }
-    
-    func tapAvatarView(message: JCMessageType) {
-        toolbar.resignFirstResponder()
-        if message.options.alignment == .right {
-            navigationController?.pushViewController(SPersonViewController(), animated: true)
-        } else {
-            guard let uid = message.sender?.username else {
-                return
-            }
-            goToPerson(uid: uid)
-            
-        }
-    }
-
-    func longTapAvatarView(message: JCMessageType) {
-        if !isGroup || message.options.alignment == .right {
-            return
-        }
-        toolbar.becomeFirstResponder()
-        if let user = message.sender {
-            toolbar.text.append("@")
-            handleAt(toolbar, NSMakeRange(toolbar.text.length - 1, 0), user, false, user.displayName().length)
-        }
-    }
-
-    func tapUnreadTips(message: JCMessageType) {
-        let vc = UnreadListViewController()
-        let msg = conversation.message(withMessageId: message.msgId)
-        vc.message = msg
-        navigationController?.pushViewController(vc, animated: true)
-    }
-    
-    private func goToPerson(uid: String) {
-        let storyBoard = UIStoryboard(name: "contacts", bundle: nil)
-        guard let personVC = storyBoard.instantiateViewController(withIdentifier: "ContactPersonInfoV2") as?  ContactPersonInfoV2ViewController else {
-            return
-        }
-        let person = PersonV2()
-        person.id = uid
-        personVC.person = person
-        navigationController?.pushViewController(personVC, animated: true)
-    }
-}
-
-extension JCChatViewController: JCChatViewDelegate {
-    func refershChatView( chatView: JCChatView) {
-        messagePage += 1
-        _loadMessage(messagePage)
-        chatView.stopRefresh()
-    }
-    
-    func deleteMessage(message: JCMessageType) {
-        conversation.deleteMessage(withMessageId: message.msgId)
-        if let index = messages.index(message) {
-            jMessageCount -= 1
-            messages.remove(at: index)
-            if let message = messages.last {
-                if message.content is JCMessageTimeLineContent {
-                    messages.removeLast()
-                    chatView.remove(at: messages.count)
-                }
-            }
-        }
-    }
-    
-    func forwardMessage(message: JCMessageType) {
-        if let message = conversation.message(withMessageId: message.msgId) {
-            let vc = JCForwardViewController()
-            vc.message = message
-            let nav = JCNavigationController(rootViewController: vc)
-            self.present(nav, animated: true, completion: {
-                self.toolbar.isHidden = true
-            })
-        }
-    }
-    
-    func withdrawMessage(message: JCMessageType) {
-        guard let message = conversation.message(withMessageId: message.msgId) else {
-            return
-        }
-        JMSGMessage.retractMessage(message, completionHandler: { (result, error) in
-            if error == nil {
-                if let index = self.messages.index(message) {
-                    let msg = self._parseMessage(self.conversation.message(withMessageId: message.msgId)!, false)
-                    self.messages[index] = msg
-                    self.chatView.update(msg, at: index)
-                }
-            } else {
-                MBProgressHUD_JChat.show(text: "发送时间过长,不能撤回", view: self.view)
-            }
-        })
-    }
-
-    func indexPathsForVisibleItems(chatView: JCChatView, items: [IndexPath]) {
-        for item in items {
-            if item.row <= minIndex {
-                var msgs: [JCMessage] = []
-                for index in item.row...minIndex  {
-                    msgs.append(messages[index])
-                }
-                updateUnread(msgs)
-                minIndex = item.row
-            }
-        }
-    }
-
-    fileprivate func updateUnread(_ messages: [JCMessage]) {
-        for message in messages {
-            if message.options.alignment != .left {
-                continue
-            }
-            if let msg = conversation.message(withMessageId: message.msgId) {
-                if msg.isHaveRead {
-                    continue
-                }
-                msg.setMessageHaveRead({ _,_  in
-
-                })
-            }
-        }
-    }
-}
-
-//extension JCChatViewController: UIAlertViewDelegate {
-//
-//    func alertView(_ alertView: UIAlertView, clickedButtonAt buttonIndex: Int) {
-//        if alertView.tag == 10001 {
-//            if buttonIndex == 1 {
-//                JCAppManager.openAppSetter()
-//            }
-//            return
-//        }
-//        switch buttonIndex {
-//        case 1:
-//            if let index = messages.index(currentMessage) {
-//                messages.remove(at: index)
-//                chatView.remove(at: index)
-//                let msg = conversation.message(withMessageId: currentMessage.msgId)
-//                currentMessage.options.state = .sending
-//
-//                if let msg = msg {
-//                    if let content = currentMessage.content as? JCMessageImageContent,
-//                        let imageContent = msg.content as? JMSGImageContent
-//                    {
-//                        imageContent.uploadHandler = {  (percent:Float, msgId:(String?)) -> Void in
-//                            content.upload?(percent)
-//                        }
-//                    }
-//                }
-//                messages.append(currentMessage as! JCMessage)
-//                chatView.append(currentMessage)
-//                conversation.send(msg!, optionalContent: JMSGOptionalContent.ex.default)
-//                chatView.scrollToLast(animated: true)
-//            }
-//        default:
-//            break
-//        }
-//    }
-//}
-
-// MARK: - SAIInputBarDelegate & SAIInputBarDisplayable
-extension JCChatViewController: SAIInputBarDelegate, SAIInputBarDisplayable {
-    
-    open override var inputAccessoryView: UIView? {
-        return toolbar
-    }
-    open var scrollView: SAIInputBarScrollViewType {
-        return chatView
-    }
-    open override var canBecomeFirstResponder: Bool {
-        return true
-    }
-    
-    open func inputView(with item: SAIInputItem) -> UIView? {
-        if let view = inputViews[item.identifier] {
-            return view
-        }
-        switch item.identifier {
-        case "kb:emoticon":
-            let view = JCEmoticonInputView()
-            view.delegate = self
-            view.dataSource = self
-            inputViews[item.identifier] = view
-            return view
-        case "kb:toolbox":
-            let view = SAIToolboxInputView()
-            view.delegate = self
-            view.dataSource = self
-            inputViews[item.identifier] = view
-            return view
-        default:
-            return nil
-        }
-    }
-    
-    open func inputViewContentSize(_ inputView: UIView) -> CGSize {
-        return CGSize(width: view.frame.width, height: 216)
-    }
-    
-    func inputBar(_ inputBar: SAIInputBar, shouldDeselectFor item: SAIInputItem) -> Bool {
-        return true
-    }
-    open func inputBar(_ inputBar: SAIInputBar, shouldSelectFor item: SAIInputItem) -> Bool {
-        if item.identifier == "kb:audio" {
-            return true
-        }
-        guard let _ = inputView(with: item) else {
-            return false
-        }
-        return true
-    }
-    open func inputBar(_ inputBar: SAIInputBar, didSelectFor item: SAIInputItem) {
-        inputItem = item
-        
-        if item.identifier == "kb:audio" {
-            inputBar.deselectBarAllItem()
-            return
-        }
-        if let kb = inputView(with: item) {
-            inputBar.setInputMode(.selecting(kb), animated: true)
-        }
-    }
-    open func inputBar(didChangeMode inputBar: SAIInputBar) {
-        if inputItem?.identifier == "kb:audio" {
-            return
-        }
-        if let item = inputItem, !inputBar.inputMode.isSelecting {
-            inputBar.deselectBarItem(item, animated: true)
-        }
-    }
-    
-    open func inputBar(didChangeText inputBar: SAIInputBar) {
-        _emoticonSendBtn.isEnabled = inputBar.attributedText.length != 0
-    }
-    
-    public func inputBar(shouldReturn inputBar: SAIInputBar) -> Bool {
-        if inputBar.attributedText.length == 0 {
-            return false
-        }
-        send(forText: inputBar.attributedText)
-        inputBar.attributedText = nil
-        return false
-    }
-    
-    func inputBar(_ inputBar: SAIInputBar, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
-        let currentIndex = range.location
-        if !isGroup {
-            return true
-        }
-        if string == "@" {
-            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()) {
-                let vc = JCRemindListViewController()
-                vc.finish = { (user, isAtAll, length) in
-                    self.handleAt(inputBar, range, user, isAtAll, length)
-                }
-                vc.group = self.conversation.target as? JMSGGroup
-                let nav = JCNavigationController(rootViewController: vc)
-                self.present(nav, animated: true, completion: {})
-            }
-        } else {
-            return updateRemids(inputBar, string, range, currentIndex)
-        }
-        return true
-    }
-
-    func handleAt(_ inputBar: SAIInputBar, _ range: NSRange, _ user: JMSGUser?, _ isAtAll: Bool, _ length: Int) {
-        let text = inputBar.text!
-        let currentIndex = range.location
-        var displayName = "所有成员"
-
-        if let user = user {
-            displayName = user.displayName()
-        }
-        let remind = JCRemind(user, currentIndex, currentIndex + 2 + displayName.length, displayName.length + 2, isAtAll)
-        if text.length == currentIndex + 1 {
-            inputBar.text = text + displayName + " "
-        } else {
-            let index1 = text.index(text.endIndex, offsetBy: currentIndex - text.length + 1)
-            let prefix = text.substring(with: (text.startIndex..<index1))
-            let index2 = text.index(text.startIndex, offsetBy: currentIndex + 1)
-            let suffix = text.substring(with: (index2..<text.endIndex))
-            inputBar.text = prefix + displayName + " " + suffix
-            let _ = self.updateRemids(inputBar, "@" + displayName + " ", range, currentIndex)
-        }
-        self.reminds.append(remind)
-        self.reminds.sort(by: { (r1, r2) -> Bool in
-            return r1.startIndex < r2.startIndex
-        })
-    }
-    
-    func updateRemids(_ inputBar: SAIInputBar, _ string: String, _ range: NSRange, _ currentIndex: Int) -> Bool {
-        for index in 0..<reminds.count {
-            let remind = reminds[index]
-            let length = remind.length
-            let startIndex = remind.startIndex
-            let endIndex = remind.endIndex
-            // Delete
-            if currentIndex == endIndex - 1 && string.length == 0 {
-                for _ in 0..<length {
-                    inputBar.deleteBackward()
-                }
-                // Move Other Index
-                for subIndex in (index + 1)..<reminds.count {
-                    let subTemp = reminds[subIndex]
-                    subTemp.startIndex -= length
-                    subTemp.endIndex -= length
-                }
-                reminds.remove(at: index)
-                return false;
-            } else if currentIndex > startIndex && currentIndex < endIndex {
-                // Delete Content
-                if string.length == 0 {
-                    for subIndex in (index + 1)..<reminds.count {
-                        let subTemp = reminds[subIndex]
-                        subTemp.startIndex -= 1
-                        subTemp.endIndex -= 1
-                    }
-                    reminds.remove(at: index)
-                    return true
-                }
-                // Add Content
-                else {
-                    for subIndex in (index + 1)..<reminds.count {
-                        let subTemp = reminds[subIndex]
-                        subTemp.startIndex += string.length
-                        subTemp.endIndex += string.length
-                    }
-                    reminds.remove(at: index)
-                    return true
-                }
-            }
-        }
-        for index in 0..<reminds.count {
-            let tempDic = reminds[index]
-            let startIndex = tempDic.startIndex
-            if currentIndex <= startIndex {
-                if string.count == 0 {
-                    for subIndex in index..<reminds.count {
-                        let subTemp = reminds[subIndex]
-                        subTemp.startIndex -= 1
-                        subTemp.endIndex -= 1
-                    }
-                    return true
-                } else {
-                    for subIndex in index..<reminds.count {
-                        let subTemp = reminds[subIndex]
-                        subTemp.startIndex += string.length
-                        subTemp.endIndex += string.length
-                    }
-                    return true
-                }
-            }
-        }
-        return true
-    }
-    
-    func inputBar(touchDown recordButton: UIButton, inputBar: SAIInputBar) {
-        if recordingHub != nil {
-            recordingHub.removeFromSuperview()
-        }
-        recordingHub = JCRecordingView(frame: CGRect.zero)
-        recordHelper.updateMeterDelegate = recordingHub
-        recordingHub.startRecordingHUDAtView(view)
-        recordingHub.frame = CGRect(x: view.centerX - 70, y: view.centerY - 70, width: 136, height: 136)
-        recordHelper.startRecordingWithPath(String.getRecorderPath()) {
-        }
-    }
-    
-    func inputBar(dragInside recordButton: UIButton, inputBar: SAIInputBar) {
-        recordingHub.pauseRecord()
-    }
-    
-    func inputBar(dragOutside recordButton: UIButton, inputBar: SAIInputBar) {
-        recordingHub.resaueRecord()
-    }
-    
-    func inputBar(touchUpInside recordButton: UIButton, inputBar: SAIInputBar) {
-        if recordHelper.recorder ==  nil {
-            return
-        }
-        recordHelper.finishRecordingCompletion()
-        if (recordHelper.recordDuration! as NSString).floatValue < 1 {
-            recordingHub.showErrorTips()
-            let time: TimeInterval = 1.5
-            let hub = recordingHub
-            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + time) {
-                hub?.removeFromSuperview()
-            }
-            return
-        } else {
-            recordingHub.removeFromSuperview()
-        }
-        let data = try! Data(contentsOf: URL(fileURLWithPath: recordHelper.recordPath!))
-        send(voiceData: data, duration: Double(recordHelper.recordDuration!)!)
-    }
-    
-    func inputBar(touchUpOutside recordButton: UIButton, inputBar: SAIInputBar) {
-        recordHelper.cancelledDeleteWithCompletion()
-        recordingHub.removeFromSuperview()
-    }
-}
-
-// MARK: - JCRecordVoiceHelperDelegate
-extension JCChatViewController: JCRecordVoiceHelperDelegate {
-    public func beyondLimit(_ time: TimeInterval) {
-        recordHelper.finishRecordingCompletion()
-        recordingHub.removeFromSuperview()
-        let data = try! Data(contentsOf: URL(fileURLWithPath: recordHelper.recordPath!))
-        send(voiceData: data, duration: Double(recordHelper.recordDuration!)!)
-    }
-}
-
-extension JCChatViewController: UIGestureRecognizerDelegate {
-    public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
-        guard let view = touch.view else {
-            return true
-        }
-        if view.isKind(of: JCMessageTextContentView.self) {
-            return false
-        }
-        return true
-    }
-}
-
-extension JCChatViewController: UIDocumentInteractionControllerDelegate {
-    func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
-        return self
-    }
-    func documentInteractionControllerViewForPreview(_ controller: UIDocumentInteractionController) -> UIView? {
-        return view
-    }
-    func documentInteractionControllerRectForPreview(_ controller: UIDocumentInteractionController) -> CGRect {
-        return view.frame
-    }
-}

+ 0 - 613
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/JCConversationListViewController.swift

@@ -1,613 +0,0 @@
-//
-//  JCConversationListViewController.swift
-//  JChat
-//
-//  Created by deng on 2017/2/16.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-import JMessage
-import YHPopupView
-import Alamofire
-import AlamofireObjectMapper
-import SwiftyJSON
-import ObjectMapper
-import CocoaLumberjack
-
-class JCConversationListViewController: UIViewController {
-    
-    
-    fileprivate var isConnecting = false
-    
-    private lazy var addButton = UIButton(frame: CGRect(x: 0, y: 0, width: 36, height: 36))
-    
-//    private lazy var searchController: JCSearchController = JCSearchController(searchResultsController: JCNavigationController(rootViewController: JCSearchResultViewController()))
-    
-    private lazy var searchView: UIView = UIView(frame: CGRect(x: 0, y: 0, width: self.view.width, height: 36))
-    
-    fileprivate lazy var tableview: UITableView = {
-        var tableview = UITableView(frame: CGRect(x: 0, y: 0, width: self.view.width, height: self.view.height))
-        tableview.delegate = self
-        tableview.dataSource = self
-        tableview.backgroundColor = UIColor(netHex: 0xe8edf3)
-        tableview.register(JCConversationCell.self, forCellReuseIdentifier: "JCConversationCell")
-        tableview.separatorStyle = .none
-        return tableview
-    }()
-    
-    fileprivate lazy var errorTips: JCNetworkTipsCell = JCNetworkTipsCell()
-    
-    fileprivate var showNetworkTips = false
-    
-    fileprivate lazy var emptyView: UIView = {
-        let view = UIView(frame: CGRect(x: 0, y: 36, width: self.view.width, height: self.view.height - 36))
-        view.isHidden = true
-        view.backgroundColor = .white
-        let tips = UILabel()
-        tips.text = "暂无会话"
-        tips.textColor = UIColor(netHex: 0x666666)
-        tips.sizeToFit()
-        tips.center = CGPoint(x: view.centerX, y: view.height / 2 - 60)
-        view.addSubview(tips)
-        return view
-    }()
-    
-    fileprivate lazy var titleTips: UILabel = {
-        var tips = UILabel(frame: CGRect(x: 23, y: 0, width: 67, height: 44))
-        tips.font = UIFont.systemFont(ofSize: 18)
-        tips.textColor = UIColor.white
-        tips.textAlignment = .left
-        tips.backgroundColor = UIColor(netHex: 0x5AD4D3)
-        return tips
-    }()
-    
-    
-    fileprivate lazy var titleTipsView: UIView = {
-        var view = UIView(frame: CGRect(x: self.view.width / 2 - 45, y: 20, width: 90, height: 44))
-        view.backgroundColor =  UIColor(netHex: 0x5AD4D3)
-        let activityView = UIActivityIndicatorView(frame: CGRect(x: 0, y: 12, width: 20, height: 20))
-        view.addSubview(activityView)
-        activityView.startAnimating()
-        view.addSubview(self.titleTips)
-        view.isHidden = true
-        return view
-    }()
-    
-    
-    var datas: [JMSGConversation] = []
-    
-    //MARK: - life cycle
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        _init()
-    }
-    
-    override func viewDidAppear(_ animated: Bool) {
-        super.viewDidAppear(animated)
-        if isConnecting {
-            titleTips.text = "连接中"
-            titleTipsView.isHidden = false
-        } else {
-            titleTipsView.isHidden = true
-        }
-        _getConversations()
-    }
-    
-    override func viewWillDisappear(_ animated: Bool) {
-        titleTipsView.isHidden = true
-    }
-    
-    deinit {
-        NotificationCenter.default.removeObserver(self)
-        JMessage.remove(self, with: nil)
-    }
-    
-    
-    //Mark: - private func
-    private func _init() {
-        view.backgroundColor = UIColor(netHex: 0xe8edf3)
-        if #available(iOS 10.0, *) {
-            navigationController?.tabBarItem.badgeColor = UIColor(netHex: 0xEB424C)
-        }
-        
-        let appDelegate = UIApplication.shared.delegate
-        let window = appDelegate?.window!
-        window?.addSubview(titleTipsView)
-        
-        _setupNavigation()
-        JMessage.add(self, with: nil)
-//        let nav = searchController.searchResultsController as! JCNavigationController
-//        let vc = nav.topViewController as! JCSearchResultViewController
-//        searchController.delegate = self
-//        searchController.searchResultsUpdater = vc
-//        searchView.addSubview(searchController.searchBar)
-//        searchView.backgroundColor = UIColor(netHex: 0xF0F0F0)
-//        tableview.tableHeaderView = searchView
-        view.addSubview(tableview)
-        view.addSubview(emptyView)
-        
-        definesPresentationContext = true
-        
-        NotificationCenter.default.addObserver(self, selector: #selector(reachabilityChanged(note:)), name: NSNotification.Name(rawValue: "kNetworkReachabilityChangedNotification"), object: nil)
-        
-        _getConversations()
-        NotificationCenter.default.addObserver(self, selector: #selector(_getConversations), name: NSNotification.Name(rawValue: kUpdateConversation), object: nil)
-        NotificationCenter.default.addObserver(self, selector: #selector(connectClose), name: NSNotification.Name.jmsgNetworkDidClose, object: nil)
-        NotificationCenter.default.addObserver(self, selector: #selector(connectSucceed), name: NSNotification.Name.jmsgNetworkDidLogin, object: nil)
-        NotificationCenter.default.addObserver(self, selector: #selector(connecting), name: NSNotification.Name.jmsgNetworkIsConnecting, object: nil)
-    }
-    
-    @objc func reachabilityChanged(note: NSNotification) {
-        if let curReach = note.object as? Reachability {
-            let status = curReach.currentReachabilityStatus()
-            switch status {
-            case NotReachable:
-                notReachable()
-            default :
-                reachable()
-            }
-        }
-    }
-    
-    private func _setupNavigation() {
-        addButton.addTarget(self, action: #selector(_clickNavRightButton(_:)), for: .touchUpInside)
-        addButton.setImage(UIImage.loadImage("com_icon_add"), for: .normal)
-        let item = UIBarButtonItem(customView: addButton)
-        navigationItem.rightBarButtonItem =  item
-    }
-    
-    func _updateBadge() {
-        let count = datas.unreadCount
-        if count > 99 {
-            navigationController?.tabBarItem.badgeValue = "99+"
-        } else {
-            navigationController?.tabBarItem.badgeValue = count == 0 ? nil : "\(count)"
-        }
-    }
-    
-    @objc func _getConversations() {
-        JMSGConversation.allConversations { (result, error) in
-            guard let conversatios = result else {
-                return
-            }
-            self.datas = conversatios as! [JMSGConversation]
-            self.datas = self.sortConverstaions(self.datas)
-            DispatchQueue.main.async {
-                self.tableview.reloadData()
-                if self.datas.count == 0 {
-                    self.emptyView.isHidden = false
-                } else {
-                    self.emptyView.isHidden = true
-                }
-                self._updateBadge()
-            }
-            
-        }
-    }
-    
-    fileprivate func sortConverstaions(_ convs: [JMSGConversation]) -> [JMSGConversation] {
-        var stickyConvs: [JMSGConversation] = []
-        var allConvs: [JMSGConversation] = []
-        for index in 0..<convs.count {
-            let conv = convs[index]
-            if conv.ex.isSticky {
-                stickyConvs.append(conv)
-            } else {
-                allConvs.append(conv)
-            }
-        }
-        
-        stickyConvs = stickyConvs.sorted(by: { (c1, c2) -> Bool in
-            c1.ex.stickyTime > c2.ex.stickyTime
-        })
-        
-        allConvs.insert(contentsOf: stickyConvs, at: 0)
-        return allConvs
-    }
-    
-    //MARK: - click func
-    @objc func _clickNavRightButton(_ sender: UIButton) {
-        _setupPopView()
-    }
-    
-    private func _setupPopView() {
-        presentPopupView(selectView)
-    }
-    
-    fileprivate lazy var selectView: YHPopupView = {
-        let popupView = MorePopupView(frame: CGRect(x: self.view.width - 150, y: 65, width: 145, height: 100))
-        popupView.delegate = self
-        return popupView
-    }()
-}
-
-extension JCConversationListViewController: UITableViewDelegate, UITableViewDataSource {
-    
-    public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
-        return showNetworkTips ? datas.count + 1 : datas.count
-    }
-    
-    public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
-        if showNetworkTips && indexPath.row == 0 {
-            errorTips.selectionStyle = .none
-            return errorTips
-        }
-        return tableView.dequeueReusableCell(withIdentifier: "JCConversationCell", for: indexPath)
-    }
-    
-    public func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
-        guard let cell = cell as? JCConversationCell else {
-            return
-        }
-        cell.bindConversation(datas[showNetworkTips ? indexPath.row - 1 : indexPath.row])
-    }
-    
-    public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
-        if showNetworkTips && indexPath.row == 0 {
-            return 40
-        }
-        return 65
-    }
-    
-    public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
-        tableView.deselectRow(at: indexPath, animated: true)
-        if showNetworkTips && indexPath.row == 0 {
-            return 
-        }
-        let conversation = datas[showNetworkTips ? indexPath.row - 1 : indexPath.row]
-        conversation.clearUnreadCount()
-        guard let cell = tableView.cellForRow(at: indexPath) as? JCConversationCell else {
-            return
-        }
-        cell.bindConversation(conversation)
-        let vc = JCChatViewController(conversation: conversation)
-        navigationController?.pushViewController(vc, animated: true)
-    }
-    
-    func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
-        return true
-    }
-    
-    func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
-        let action1 = UITableViewRowAction(style: .destructive, title: "删除") { (action, indexPath) in
-            self._delete(indexPath)
-        }
-        let conversation = datas[showNetworkTips ? indexPath.row - 1 : indexPath.row]
-        let action2 = UITableViewRowAction(style: .normal, title: "置顶") { (action, indexPath) in
-            conversation.ex.isSticky = !conversation.ex.isSticky
-            self._getConversations()
-        }
-        if conversation.ex.isSticky {
-            action2.title = "取消置顶"
-        } else {
-            action2.title = "置顶"
-        }
-        return [action1, action2]
-    }
-    
-    private func _delete(_ indexPath: IndexPath) {
-        let conversation = datas[indexPath.row]
-        let tager = conversation.target
-        JCDraft.update(text: nil, conversation: conversation)
-        if conversation.ex.isGroup {
-            guard let group = tager as? JMSGGroup else {
-                return
-            }
-            JMSGConversation.deleteGroupConversation(withGroupId: group.gid)
-        } else {
-            guard let user = tager as? JMSGUser else {
-                return
-            }
-            JMSGConversation.deleteSingleConversation(withUsername: user.username, appKey: user.appKey!)
-        }
-        datas.remove(at: indexPath.row)
-        if datas.count == 0 {
-            emptyView.isHidden = false
-        } else {
-            emptyView.isHidden = true
-        }
-        tableview.reloadData()
-    }
-    
-}
-
-
-extension JCConversationListViewController: MorePopupViewDelegate {
-    
-    
-    
-    //查询当前用户身份的顶级组织
-    private func findCurrentIdentityTopUnit(callback: @escaping (String?)-> Void) {
-        var myPersonURL:String? {
-            let url = AppDelegate.o2Collect.generateURLWithAppContextKey(PersonContext.personContextKey, query: PersonContext.personInfoQuery, parameter: nil)
-            return url
-        }
-        var topUnitByIdentityURL: String? {
-            let url = AppDelegate.o2Collect.generateURLWithAppContextKey(ContactContext.contactsContextKey, query: ContactContext.topLevelUnitByIdentity, parameter: nil)
-            return url
-        }
-        Alamofire.request(myPersonURL!, method: .get, parameters: nil, encoding:URLEncoding.default, headers: nil).validate().responseJSON {
-            response in
-            switch response.result {
-            case .success(let val):
-                let objects = JSON(val)["data"]
-                var identity = ""
-                if let person = Mapper<PersonV2>().map(JSONString:objects.description) {
-                    if let identities = person.woIdentityList, identities.count > 0 {
-                        identity = identities[0].distinguishedName ?? ""
-                    }
-                }
-                if !identity.isEmpty {
-                    Alamofire.request(topUnitByIdentityURL!, method: .post, parameters: ["identity": identity as AnyObject, "level": 1 as AnyObject], encoding: JSONEncoding.default, headers: nil).responseJSON(completionHandler: { (res) in
-                        switch res.result {
-                        case .success(let val):
-                            let objects = JSON(val)["data"]
-                            if let unit = Mapper<OrgUnit>().map(JSONString:objects.description) {
-                               callback(unit.distinguishedName)
-                            }else {
-                                callback(nil)
-                            }
-                            break
-                        case .failure(let err):
-                            DDLogError(err.localizedDescription)
-                            callback(nil)
-                        }
-                    })
-                }else {
-                    callback(nil)
-                }
-            case .failure(let err):
-                DDLogError(err.localizedDescription)
-                callback(nil)
-            }
-        }
-    }
-    
-    
-    //群聊
-    func popupView(view: MorePopupView, addGroup addButton: UIButton) {
-        dismissPopupView()
-        self.findCurrentIdentityTopUnit { (topOrg) in
-            self.chooseGroupUsers(topOrg: topOrg)
-        }
-    }
-    private func chooseGroupUsers(topOrg: String?) {
-        var topList:[String] = []
-        if topOrg != nil {
-            topList.append(topOrg!)
-        }
-        if let v = ContactPickerViewController.providePickerVC(
-            pickerModes: [ContactPickerType.person],
-            topUnitList: topList,
-            unitType: "",
-            maxNumber: 0,
-            multiple: true,
-            dutyList: [],
-            initDeptPickedArray: [],
-            initIdPickedArray: [],
-            initGroupPickedArray: [],
-            initUserPickedArray: [],
-            pickedDelegate: { (result: O2BizContactPickerResult) in
-                if let users = result.users, !users.isEmpty {
-                    self.groupChat(selectedPersons: users)
-                }
-        }
-            ) {
-            self.navigationController?.pushViewController(v, animated: true)
-        }
-    }
-    
-    func popupView(view: MorePopupView, addFriend addButton: UIButton) {
-      
-        //navigationController?.pushViewController(JCSearchFriendViewController(), animated: true)
-    }
-    
-    //单聊
-    func popupView(view: MorePopupView, addSingle addButton: UIButton) {
-        dismissPopupView()
-        //添加当前用户顶级组织的限制
-        self.findCurrentIdentityTopUnit { (topOrg) in
-            self.chooseSingleUser(topOrg: topOrg)
-        }
-    }
-    private func chooseSingleUser(topOrg: String?) {
-        var topList:[String] = []
-        if topOrg != nil {
-            topList.append(topOrg!)
-        }
-        if let v = ContactPickerViewController.providePickerVC(
-            pickerModes: [ContactPickerType.person],
-            topUnitList: topList,
-            unitType: "",
-            maxNumber: 1,
-            multiple: false,
-            dutyList: [],
-            initDeptPickedArray: [],
-            initIdPickedArray: [],
-            initGroupPickedArray: [],
-            initUserPickedArray: [],
-            pickedDelegate: { (result: O2BizContactPickerResult) in
-                if let users = result.users, !users.isEmpty {
-                    if let selectedPerson = users[0].id {
-                        self.singleChat(selectedPerson: selectedPerson)
-                    }
-                }
-        }
-            ) {
-            self.navigationController?.pushViewController(v, animated: true)
-        }
-    }
-    
-    private func singleChat(selectedPerson: String) {
-        let username = selectedPerson
-        MBProgressHUD_JChat.showMessage(message: "创建中...", toView: view)
-        JMSGConversation.createSingleConversation(withUsername: username) { (result, error) in
-            MBProgressHUD_JChat.hide(forView: self.view, animated: true)
-            if error == nil {
-                let conv = result as! JMSGConversation
-                let vc = JCChatViewController(conversation: conv)
-                NotificationCenter.default.post(name: NSNotification.Name(rawValue: kUpdateConversation), object: nil, userInfo: nil)
-                self.navigationController?.pushViewController(vc, animated: true)
-            }else{
-                O2Logger.error(error.debugDescription)
-                MBProgressHUD_JChat.show(text: "创建会话失败,请重试", view: self.view)
-            }
-        }
-    }
-    
-    private func groupChat(selectedPersons: [O2PersonPickerItem]) {
-        MBProgressHUD_JChat.showMessage(message: "创建中...", toView: view)
-        let userNames = selectedPersons.map { (p) -> String in
-            return p.id!
-        }
-        JMSGGroup.createGroup(withName: nil, desc: nil, memberArray: userNames, completionHandler: { (result, error) in
-            MBProgressHUD_JChat.hide(forView: self.view, animated: true)
-            if error == nil {
-                for vc in (self.navigationController?.viewControllers)! {
-                    if vc is JCConversationListViewController {
-                        self.navigationController?.popToViewController(vc, animated: true)
-                        let group = result as! JMSGGroup
-                        JMSGConversation.createGroupConversation(withGroupId: group.gid, completionHandler: { (result, error) in
-                            let conv = JMSGConversation.groupConversation(withGroupId: group.gid)
-                            let chatVC = JCChatViewController(conversation: conv!)
-                            vc.navigationController?.pushViewController(chatVC, animated: true)
-                        })
-                    }
-                }
-                
-            } else {
-                O2Logger.error(error.debugDescription)
-                MBProgressHUD_JChat.show(text: "创建会话失败,请确保添加的群聊成员都使用过O2移动端应用", view: self.view)
-            }
-        })
-    }
-    
-    
-    func popupView(view: MorePopupView, scanQRCode addButton: UIButton) {
-        dismissPopupView()
-        let vc = ScanQRCodeViewController()
-        navigationController?.pushViewController(vc, animated: true)
-    }
-}
-
-extension JCConversationListViewController: JMessageDelegate {
-    
-    func onReceive(_ message: JMSGMessage!, error: Error!) {
-        _getConversations()
-    }
-    
-    func onConversationChanged(_ conversation: JMSGConversation!) {
-        _getConversations()
-    }
-    
-    func onGroupInfoChanged(_ group: JMSGGroup!) {
-        _getConversations()
-    }
-    
-    func onSyncRoamingMessageConversation(_ conversation: JMSGConversation!) {
-        _getConversations()
-    }
-    
-    func onSyncOfflineMessageConversation(_ conversation: JMSGConversation!, offlineMessages: [JMSGMessage]!) {
-        _getConversations()
-    }
-    
-    func onReceive(_ retractEvent: JMSGMessageRetractEvent!) {
-        _getConversations()
-    }
-    
-}
-
-extension JCConversationListViewController: UISearchControllerDelegate {
-    func willPresentSearchController(_ searchController: UISearchController) {
-        tableview.isHidden = true
-        emptyView.isHidden = true
-        UIView.animate(withDuration: 0.35, animations: { 
-            self.emptyView.frame = CGRect(x: 0, y: 64, width: self.view.width, height: self.view.height - 64)
-        }) { (_) in
-            self.navigationController?.tabBarController?.tabBar.isHidden = true
-        }
-    }
-    func willDismissSearchController(_ searchController: UISearchController) {
-        UIView.animate(withDuration: 0.35) {
-            self.emptyView.frame = CGRect(x: 0, y: 64 + 36, width: self.view.width, height: self.view.height - 64 - 36)
-        }
-        tableview.isHidden = false
-        if datas.count == 0 {
-            emptyView.isHidden = false
-        }
-        let nav = searchController.searchResultsController as! JCNavigationController
-        nav.isNavigationBarHidden = true
-        nav.popToRootViewController(animated: false)
-        navigationController?.tabBarController?.tabBar.isHidden = false
-    }
-}
-
-// MARK: - network tips
-extension JCConversationListViewController {
-    
-    func reachable() {
-        if !showNetworkTips {
-            return
-        }
-        showNetworkTips = false
-        tableview.reloadData()
-    }
-    
-    func notReachable() {
-        if showNetworkTips {
-            return
-        }
-        showNetworkTips = true
-        if datas.count > 0 {
-            let indexPath = IndexPath(row: 0, section: 0)
-            tableview.beginUpdates()
-            tableview.insertRows(at: [indexPath], with: .automatic)
-            tableview.endUpdates()
-        } else {
-            tableview.reloadData()
-        }
-    }
-    
-    @objc func connectClose() {
-        isConnecting = false
-        DispatchQueue.main.async {
-            self.titleTipsView.isHidden = true
-        }
-        
-    }
-    
-    @objc func connectSucceed() {
-        isConnecting = false
-        DispatchQueue.main.async {
-            self.titleTipsView.isHidden = true
-        }
-    }
-    
-    @objc func connecting() {
-        DispatchQueue.main.async {
-            self._connectingSate()
-        }
-    }
-    
-    func _connectingSate() {
-        let window = UIApplication.shared.delegate?.window
-        if let window = window {
-            guard let rootViewController = window?.rootViewController as? O2MainController else {
-                return
-            }
-            guard let nav = rootViewController.selectedViewController as? JCNavigationController else {
-                return
-            }
-            guard let currentVC = nav.topViewController else {
-                return
-            }
-            if currentVC.isKind(of: JCConversationListViewController.self) {
-                isConnecting = true
-                titleTips.text = "连接中"
-                titleTipsView.isHidden = false
-            }
-        }
-    }
-}

+ 0 - 112
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/JCDocumentViewController.swift

@@ -1,112 +0,0 @@
-//
-//  JCDocumentViewController.swift
-//  JChat
-//
-//  Created by deng on 2017/7/24.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-import WebKit
-
-class JCDocumentViewController: UIViewController, CustomNavigation {
-    
-    var filePath: String!
-    var fileType: String!
-    var fileData: Data!
-
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        _init()
-    }
-
-    fileprivate lazy var webView: UIWebView = {
-        var webView = UIWebView(frame: .zero)
-        webView.delegate = self
-        webView.backgroundColor = .white
-        webView.scrollView.isDirectionalLockEnabled = true
-        webView.scrollView.showsHorizontalScrollIndicator = false
-        return webView
-    }()
-    private var fileUrl: URL?
-    private lazy var documentInteractionController = UIDocumentInteractionController()
-    fileprivate lazy var leftButton = UIButton(frame: CGRect(x: 0, y: 0, width: 60, height: 65 / 3))
-    
-    private func _init() {
-        view.backgroundColor = .white
-        automaticallyAdjustsScrollViewInsets = false
-        view.addSubview(webView)
-        
-        _setupNavigation()
-        
-        view.addConstraint(_JCLayoutConstraintMake(webView, .left, .equal, view, .left))
-        view.addConstraint(_JCLayoutConstraintMake(webView, .right, .equal, view, .right))
-        view.addConstraint(_JCLayoutConstraintMake(webView, .top, .equal, view, .top, 64))
-        view.addConstraint(_JCLayoutConstraintMake(webView, .bottom, .equal, view, .bottom))
-        
-        let encodeWord = filePath.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
-        let url = URL(fileURLWithPath: encodeWord!)
-        let fileName = url.lastPathComponent
-        
-        let path = "\(NSHomeDirectory())/tmp/" + fileName + "." + fileType
-        if JCFileManager.saveFileToLocal(data: fileData, savaPath: path) {
-            fileUrl = URL(fileURLWithPath: path)
-            do {
-                let string = try String(contentsOf: fileUrl!, encoding: .utf8)
-                webView.loadHTMLString(string, baseURL: nil)
-            } catch {
-                let request = URLRequest(url: fileUrl!)
-                webView.loadRequest(request)
-            }
-        }
-    }
-    
-    private func _setupNavigation() {
-        let navButton = UIButton(frame: CGRect(x: 0, y: 0, width: 18, height: 18))
-        navButton.setImage(UIImage.loadImage("com_icon_file_more"), for: .normal)
-        navButton.addTarget(self, action: #selector(_openFile), for: .touchUpInside)
-        let item1 = UIBarButtonItem(customView: navButton)
-        navigationItem.rightBarButtonItems =  [item1]
-        
-        customLeftBarButton(delegate: self)
-    }
-
-    func _openFile() {
-        guard let url = fileUrl else {
-            return
-        }
-        documentInteractionController.url = url
-        documentInteractionController.delegate = self
-        documentInteractionController.presentOptionsMenu(from: .zero, in: self.view, animated: true)
-    }
-
-}
-
-extension JCDocumentViewController: UIDocumentInteractionControllerDelegate {
-    func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
-        return self
-    }
-    func documentInteractionControllerViewForPreview(_ controller: UIDocumentInteractionController) -> UIView? {
-        return self.view
-    }
-    
-    func documentInteractionControllerRectForPreview(_ controller: UIDocumentInteractionController) -> CGRect {
-        return self.view.frame
-    }
-}
-
-extension JCDocumentViewController: UIWebViewDelegate {
-    func webViewDidFinishLoad(_ webView: UIWebView) {
-        print("webViewDidFinishLoad")
-        
-    }
-    func webView(_ webView: UIWebView, didFailLoadWithError error: Error) {
-        print(error.localizedDescription)
-    }
-}
-
-extension JCDocumentViewController: UIGestureRecognizerDelegate {
-    public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
-        return true
-    }
-}

+ 0 - 166
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/JCFileDownloadViewController.swift

@@ -1,166 +0,0 @@
-//
-//  JCFileDownloadViewController.swift
-//  JChat
-//
-//  Created by deng on 2017/7/24.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-class JCFileDownloadViewController: UIViewController {
-    
-    var message: JMSGMessage!
-    var fileSize: String?
-
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        _init()
-    }
-
-    private lazy var _imageView: UIImageView = {
-        var _imageView = UIImageView()
-        _imageView.image = UIImage.loadImage("com_icon_file_file_75")
-        return _imageView
-    }()
-    
-    private lazy var _tipsLabel: UILabel = {
-        var _tipsLabel = UILabel()
-        _tipsLabel.font = UIFont.systemFont(ofSize: 12)
-        _tipsLabel.textAlignment = .center
-        _tipsLabel.textColor = UIColor(netHex: 0x999999)
-        _tipsLabel.text = "该文件不支持预览,请下载原文件查看"
-        return _tipsLabel
-    }()
-    
-    private lazy var _downloadButton: UIButton = {
-        var _downloadButton = UIButton()
-        _downloadButton.setBackgroundImage(UIImage.createImage(color: UIColor(netHex: 0x2ECFCF), size: CGSize(width: 225, height: 40)), for: .normal)
-        _downloadButton.addTarget(self, action: #selector(_downloadFile), for: .touchUpInside)
-        _downloadButton.setTitle("下载(\(self.fileSize ?? "未知大小"))", for: .normal)
-        return _downloadButton
-    }()
-    
-    private lazy var _openButton: UIButton = {
-        var _openButton = UIButton()
-        _openButton.setBackgroundImage(UIImage.createImage(color: UIColor(netHex: 0x2ECFCF), size: CGSize(width: 225, height: 40)), for: .normal)
-        _openButton.addTarget(self, action: #selector(_openFile), for: .touchUpInside)
-        _openButton.setTitle("打开文件", for: .normal)
-        _openButton.isHidden = true
-        return _openButton
-    }()
-    
-    private lazy var _fileNameLabel: UILabel = {
-        var _fileNameLabel = UILabel()
-        _fileNameLabel.font = UIFont.systemFont(ofSize: 16)
-        _fileNameLabel.numberOfLines = 0
-        _fileNameLabel.textAlignment = .center
-        _fileNameLabel.text = self.title
-        return _fileNameLabel
-    }()
-    
-    private lazy var _progressView: UIProgressView = {
-        var _progressView = UIProgressView(frame: .zero)
-        _progressView.backgroundColor = UIColor(netHex: 0x72D635)
-        _progressView.isHidden = true
-        return _progressView
-    }()
-    
-    private var _fileData: Data!
-    private lazy var documentInteractionController = UIDocumentInteractionController()
-    
-    private func _init() {
-        view.backgroundColor = UIColor(netHex: 0xE8EDF3)
-        
-        documentInteractionController.delegate = self
-        
-        view.addSubview(_imageView)
-        view.addSubview(_fileNameLabel)
-        view.addSubview(_tipsLabel)
-        view.addSubview(_downloadButton)
-        view.addSubview(_openButton)
-        
-        view.addConstraint(_JCLayoutConstraintMake(_imageView, .top, .equal, view, .top, 98 + 64))
-        view.addConstraint(_JCLayoutConstraintMake(_imageView, .centerX, .equal, view, .centerX))
-        view.addConstraint(_JCLayoutConstraintMake(_imageView, .width, .equal, nil, .notAnAttribute, 75))
-        view.addConstraint(_JCLayoutConstraintMake(_imageView, .height, .equal, nil, .notAnAttribute, 75))
-        
-        view.addConstraint(_JCLayoutConstraintMake(_fileNameLabel, .top, .equal, _imageView, .bottom, 14))
-        view.addConstraint(_JCLayoutConstraintMake(_fileNameLabel, .centerX, .equal, view, .centerX))
-        view.addConstraint(_JCLayoutConstraintMake(_fileNameLabel, .width, .equal, nil, .notAnAttribute, 225))
-        view.addConstraint(_JCLayoutConstraintMake(_fileNameLabel, .height, .equal, nil, .notAnAttribute, 45))
-        
-        view.addConstraint(_JCLayoutConstraintMake(_tipsLabel, .top, .equal, _fileNameLabel, .bottom, 14))
-        view.addConstraint(_JCLayoutConstraintMake(_tipsLabel, .centerX, .equal, view, .centerX))
-        view.addConstraint(_JCLayoutConstraintMake(_tipsLabel, .width, .equal, nil, .notAnAttribute, 225))
-        view.addConstraint(_JCLayoutConstraintMake(_tipsLabel, .height, .equal, nil, .notAnAttribute, 7))
-
-        view.addConstraint(_JCLayoutConstraintMake(_downloadButton, .top, .equal, _tipsLabel, .bottom, 30))
-        view.addConstraint(_JCLayoutConstraintMake(_downloadButton, .centerX, .equal, view, .centerX))
-        view.addConstraint(_JCLayoutConstraintMake(_downloadButton, .width, .equal, nil, .notAnAttribute, 225))
-        view.addConstraint(_JCLayoutConstraintMake(_downloadButton, .height, .equal, nil, .notAnAttribute, 40))
-        
-        view.addConstraint(_JCLayoutConstraintMake(_openButton, .top, .equal, _tipsLabel, .bottom, 30))
-        view.addConstraint(_JCLayoutConstraintMake(_openButton, .centerX, .equal, view, .centerX))
-        view.addConstraint(_JCLayoutConstraintMake(_openButton, .width, .equal, nil, .notAnAttribute, 225))
-        view.addConstraint(_JCLayoutConstraintMake(_openButton, .height, .equal, nil, .notAnAttribute, 40))
-    }
-    
-    @objc func _openFile() {
-        if let fileType = message.ex.fileType {
-            let content = message.content as! JMSGFileContent
-            switch fileType.fileFormat() {
-            case .document:
-                let vc = JCDocumentViewController()
-                vc.title = self.title
-                vc.fileData = _fileData
-                vc.filePath = content.originMediaLocalPath
-                vc.fileType = fileType
-                navigationController?.pushViewController(vc, animated: true)
-            case .video, .voice:
-                let url = URL(fileURLWithPath: content.originMediaLocalPath ?? "")
-                try! JCVideoManager.playVideo(data: Data(contentsOf: url), fileType, currentViewController: self)
-            case .photo:
-                let browserImageVC = JCImageBrowserViewController()
-                let image = UIImage(contentsOfFile: content.originMediaLocalPath ?? "")
-                browserImageVC.imageArr = [image!]
-                browserImageVC.imgCurrentIndex = 0
-                present(browserImageVC, animated: true) {}
-            default:
-                let url = URL(fileURLWithPath: content.originMediaLocalPath ?? "")
-                documentInteractionController.url = url
-                documentInteractionController.presentOptionsMenu(from: .zero, in: view, animated: true)
-            }
-        }
-    }
-    
-    @objc func _downloadFile() {
-        let content = message.content as! JMSGFileContent
-        MBProgressHUD_JChat.showMessage(message: "下载中", toView: view)
-        content.fileData { (data, id, error) in
-            MBProgressHUD_JChat.hide(forView: self.view, animated: true)
-            if error == nil {
-                self._openButton.isHidden = false
-                self._downloadButton.isHidden = true
-                self._fileData = data
-                NotificationCenter.default.post(name: NSNotification.Name(rawValue: kUpdateFileMessage), object: nil, userInfo: [kUpdateFileMessage : self.message.msgId])
-            } else {
-                MBProgressHUD_JChat.show(text: "下载失败", view: self.view)
-            }
-        }
-    }
-
-}
-
-extension JCFileDownloadViewController: UIDocumentInteractionControllerDelegate {
-    func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
-        return self
-    }
-    func documentInteractionControllerViewForPreview(_ controller: UIDocumentInteractionController) -> UIView? {
-        return view
-    }
-    
-    func documentInteractionControllerRectForPreview(_ controller: UIDocumentInteractionController) -> CGRect {
-        return view.frame
-    }
-}

+ 0 - 269
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/JCForwardViewController.swift

@@ -1,269 +0,0 @@
-//
-//  JCForwardViewController.swift
-//  JChat
-//
-//  Created by deng on 2017/7/17.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-class JCForwardViewController: UIViewController {
-    
-    var message: JMSGMessage?
-    var fromUser: JMSGUser!
-
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        _init()
-    }
-
-    private lazy var cancelButton = UIButton(frame: CGRect(x: 0, y: 0, width: 36, height: 36))
-    
-    fileprivate lazy var contacterView: UITableView = {
-        var contacterView = UITableView(frame: .zero, style: .grouped)
-        contacterView.delegate = self
-        contacterView.dataSource = self
-        contacterView.separatorStyle = .none
-        contacterView.sectionIndexColor = UIColor(netHex: 0x2dd0cf)
-        contacterView.sectionIndexBackgroundColor = .clear
-        contacterView.register(JCContacterCell.self, forCellReuseIdentifier: "JCContacterCell")
-        contacterView.frame = CGRect(x: 0, y: 0, width: self.view.width, height: self.view.height)
-        return contacterView
-    }()
-    let searchResultVC = JCSearchResultViewController()
-    private lazy var searchController: JCSearchController = JCSearchController(searchResultsController: JCNavigationController(rootViewController: self.searchResultVC))
-    private lazy var searchView: UIView = UIView(frame: CGRect(x: 0, y: 0, width: self.view.width, height: 31))
-    fileprivate var badgeCount = 0
-    
-    fileprivate lazy var tagArray = ["群组"]
-    fileprivate lazy var users: [JMSGUser] = []
-    
-    fileprivate lazy var keys: [String] = []
-    fileprivate lazy var data: Dictionary<String, [JMSGUser]> = Dictionary()
-    
-    fileprivate var selectUser: JMSGUser!
-
-    private func _init() {
-        if message == nil {
-            self.title = "发送名片"
-        } else {
-            self.title = "转发"
-        }
-
-        searchResultVC.message = message
-        searchResultVC.fromUser = fromUser
-        searchResultVC.delegate = self
-
-        view.backgroundColor = UIColor(netHex: 0xe8edf3)
-        _setupNavigation()
-        
-        let nav = searchController.searchResultsController as! JCNavigationController
-        let vc = nav.topViewController as! JCSearchResultViewController
-        searchController.delegate = self
-        searchController.searchResultsUpdater = vc
-        
-        searchView.addSubview(searchController.searchBar)
-        contacterView.tableHeaderView = searchView
-
-        view.addSubview(contacterView)
-        
-        _getFriends()
-    }
-    
-    private func _setupNavigation() {
-        cancelButton.addTarget(self, action: #selector(_clickNavleftButton), for: .touchUpInside)
-        cancelButton.setTitle("取消", for: .normal)
-        cancelButton.titleLabel?.font = UIFont.systemFont(ofSize: 16)
-        let item = UIBarButtonItem(customView: cancelButton)
-        navigationItem.leftBarButtonItem = item
-    }
-    
-    func _clickNavleftButton() {
-        dismiss(animated: true, completion: nil)
-    }
-    
-    func _updateUserInfo() {
-        let users = self.users
-        _classify(users)
-        contacterView.reloadData()
-    }
-    
-    func _classify(_ users: [JMSGUser]) {
-        self.users = users
-        keys.removeAll()
-        data.removeAll()
-        for item in users {
-            var key = item.displayName().firstCharacter()
-            if !key.isLetterOrNum() {
-                key = "#"
-            }
-            var array = data[key]
-            if array == nil {
-                array = [item]
-            } else {
-                array?.append(item)
-            }
-            if !keys.contains(key) {
-                keys.append(key)
-            }
-            data[key] = array
-        }
-        keys = keys.sortedKeys()
-    }
-    
-    func _getFriends() {
-        JMSGFriendManager.getFriendList { (result, error) in
-            if let users = result as? [JMSGUser] {
-                self._classify(users)
-                self.contacterView.reloadData()
-            }
-        }
-    }
-
-}
-
-//Mark: -
-extension JCForwardViewController: UITableViewDelegate, UITableViewDataSource {
-    
-    func numberOfSections(in tableView: UITableView) -> Int {
-        if users.count > 0 {
-            return keys.count + 1
-        }
-        return 1
-    }
-    
-    public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
-        if section == 0 {
-            return tagArray.count
-        }
-        return data[keys[section - 1]]!.count
-    }
-    
-    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
-        if section == 0 {
-            return ""
-        }
-        return keys[section - 1]
-    }
-    
-    func sectionIndexTitles(for tableView: UITableView) -> [String]? {
-        return keys
-    }
-    
-    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
-        return 55
-    }
-    
-    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
-        if section == 0 {
-            return 5
-        }
-        return 10
-    }
-    
-    
-    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
-        return tableView.dequeueReusableCell(withIdentifier: "JCContacterCell", for: indexPath)
-    }
-    
-    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
-        guard let cell = cell as? JCContacterCell else {
-            return
-        }
-        if indexPath.section == 0 {
-            switch indexPath.row {
-            case 0:
-                cell.title = "群组"
-                cell.icon = UIImage.loadImage("com_icon_group_36")
-                cell.isShowBadge = false
-            default:
-                break
-            }
-            return
-        }
-        let user = data[keys[indexPath.section - 1]]?[indexPath.row]
-        cell.isShowBadge = false
-        cell.bindDate(user!)
-    }
-    
-    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
-        tableView.deselectRow(at: indexPath, animated: true)
-        if indexPath.section == 0 {
-            let vc = JCGroupListViewController()
-            vc.message = message
-            vc.fromUser = fromUser
-            navigationController?.pushViewController(vc, animated: true)
-            return
-        }
-        selectUser = data[keys[indexPath.section - 1]]?[indexPath.row]
-        if let message = message {
-            forwardMessage(message)
-        } else {
-            sendBusinessCard()
-        }
-        
-    }
-    
-    private func sendBusinessCard() {
-        fromUser = fromUser ?? JMSGUser.myInfo()
-        JCAlertView.bulid().setTitle("发送给:\(selectUser.displayName())")
-            .setMessage(fromUser.displayName() + "的名片")
-            .setDelegate(self)
-            .addCancelButton("取消")
-            .addButton("确定")
-            .setTag(10003)
-            .show()
-    }
-    
-    private func forwardMessage(_ message: JMSGMessage) {
-        JCAlertView.bulid().setJMessage(message)
-            .setTitle("发送给:\(selectUser.displayName())")
-            .setDelegate(self)
-            .setTag(10001)
-            .show()
-    }
-}
-
-extension JCForwardViewController: UISearchControllerDelegate {
-    func willPresentSearchController(_ searchController: UISearchController) {
-        contacterView.isHidden = true
-    }
-    func willDismissSearchController(_ searchController: UISearchController) {
-        contacterView.isHidden = false
-        let nav = searchController.searchResultsController as! JCNavigationController
-        nav.isNavigationBarHidden = true
-        nav.popToRootViewController(animated: false)
-    }
-}
-
-extension JCForwardViewController: UIAlertViewDelegate {
-    func alertView(_ alertView: UIAlertView, clickedButtonAt buttonIndex: Int) {
-        if buttonIndex != 1 {
-            return
-        }
-        switch alertView.tag {
-        case 10001:
-            JMSGMessage.forwardMessage(message!, target: selectUser, optionalContent: JMSGOptionalContent.ex.default)
-            
-        case 10003:
-            JMSGConversation.createSingleConversation(withUsername: selectUser.username) { (result, error) in
-                if let conversation = result as? JMSGConversation {
-                    let message = JMSGMessage.ex.createBusinessCardMessage(conversation, self.fromUser.username, self.fromUser.appKey ?? "")
-                    JMSGMessage.send(message, optionalContent: JMSGOptionalContent.ex.default)
-                }
-            }
-        default:
-            break
-        }
-        MBProgressHUD_JChat.show(text: "已发送", view: view, 2)
-
-        let time: TimeInterval = 2
-        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.2) {
-            NotificationCenter.default.post(name: NSNotification.Name(rawValue: kReloadAllMessage), object: nil)
-        }
-        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + time) { [weak self] in
-            self?.dismiss(animated: true, completion: nil)
-        }
-    }
-}

+ 0 - 144
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/JCGroupMembersViewController.swift

@@ -1,144 +0,0 @@
-//
-//  JCGroupMembersViewController.swift
-//  JChat
-//
-//  Created by deng on 2017/5/10.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-import JMessage
-import RxSwift
-import RxCocoa
-
-class JCGroupMembersViewController: UIViewController {
-    
-    var group: JMSGGroup!
-
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        _init()
-    }
-
-    fileprivate lazy var searchController: JCSearchController = JCSearchController(searchResultsController: nil)
-    fileprivate lazy var searchView: UIView = UIView(frame: CGRect(x: 0, y: 0, width: self.view.width, height: 36))
-    private var collectionView: UICollectionView!
-    
-    fileprivate var count = 0
-    fileprivate var sectionCount = 0
-    fileprivate lazy var users: [JMSGUser] = []
-    
-    fileprivate lazy var filteredUsersArray: [JMSGUser] = []
-    
-    let disposeBag = DisposeBag()
-    
-    private func _init() {
-        self.title = "群成员"
-        view.backgroundColor = .white
-        definesPresentationContext = true
-        
-        users = group.memberArray()
-        filteredUsersArray = users
-        count = filteredUsersArray.count
-        
-        searchView.backgroundColor = UIColor(netHex: 0xe8edf3)
-//        searchController.searchBar.delegate = self
-        searchController.hidesNavigationBarDuringPresentation = false
-        searchView.addSubview(searchController.searchBar)
-        
-        let flowLayout = UICollectionViewFlowLayout()
-        flowLayout.scrollDirection = .vertical
-        flowLayout.minimumInteritemSpacing = 0
-        flowLayout.minimumLineSpacing = 0
-        flowLayout.headerReferenceSize = CGSize(width: view.width, height: 36)
-        collectionView = UICollectionView(frame: view.frame, collectionViewLayout: flowLayout)
-        collectionView.bounces = true
-        collectionView.register(UICollectionReusableView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "kHeaderView")
-        
-        collectionView.backgroundColor = .white
-        collectionView.delegate = self
-        collectionView.dataSource = self
-        collectionView.register(JCGroupMemberCell.self, forCellWithReuseIdentifier: "JCGroupMemberCell")
-        
-        view.addSubview(collectionView)
-        
-        _ = searchController.searchBar.rx.text.orEmpty
-            .throttle(0.5, scheduler: MainScheduler.instance).subscribe(onNext: { (text) in
-                self.filter(text)
-            })
-            .disposed(by: disposeBag)
-        _ = searchController.searchBar.rx.cancelButtonClicked.subscribe(onNext: { (_) in
-            self.filter("")
-        }).disposed(by: disposeBag)
-        
-    }
-    
-    fileprivate func filter(_ searchString: String) {
-        if searchString.isEmpty || searchString == "" {
-            filteredUsersArray = users
-            collectionView.reloadData()
-            return
-        }
-        
-        filteredUsersArray = _JCFilterUsers(users: users, string: searchString)
-        collectionView.reloadData()
-    }
-
-}
-
-extension JCGroupMembersViewController: UICollectionViewDelegate, UICollectionViewDataSource {
-    func numberOfSections(in collectionView: UICollectionView) -> Int {
-        return 1
-    }
-    
-    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
-        return filteredUsersArray.count
-    }
-    
-    func collectionView(_ collectionView: UICollectionView,
-                        layout collectionViewLayout: UICollectionViewLayout,
-                        sizeForItemAtIndexPath indexPath: IndexPath) -> CGSize {
-        return CGSize(width:Int(collectionView.frame.size.width / 5), height: 90)
-    }
-    
-    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
-        return collectionView.dequeueReusableCell(withReuseIdentifier: "JCGroupMemberCell", for: indexPath)
-    }
-    
-    func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
-        guard let cell = cell as? JCGroupMemberCell else {
-            return
-        }
-        cell.backgroundColor = .white
-        cell.bindDate(user: filteredUsersArray[indexPath.row])
-    }
-    
-    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
-        let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "kHeaderView", for: indexPath)
-        if kind == UICollectionView.elementKindSectionHeader {
-            header.backgroundColor = UIColor(netHex: 0xe8edf3)
-            header.addSubview(searchView)
-        }
-        return header
-    }
-    
-    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
-        let user = filteredUsersArray[indexPath.row]
-        let vc = JCUserInfoViewController()
-        vc.user = user
-        navigationController?.pushViewController(vc, animated: true)
-        searchController.isActive = false
-        filter("")
-    }
-}
-
-//extension JCGroupMembersViewController: UISearchBarDelegate {
-//    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
-//        filter(searchText)
-//    }
-//    
-//    func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
-//        filter("")
-//    }
-//}
-

+ 0 - 424
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/JCGroupSettingViewController.swift

@@ -1,424 +0,0 @@
-//
-//  JCGroupSettingViewController.swift
-//  JChat
-//
-//  Created by deng on 2017/4/27.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-import JMessage
-
-class JCGroupSettingViewController: UIViewController, CustomNavigation {
-    
-    var group: JMSGGroup!
-    
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        _init()
-    }
-
-    deinit {
-        NotificationCenter.default.removeObserver(self)
-    }
-    
-    private var tableView: UITableView = UITableView(frame: .zero, style: .grouped)
-    fileprivate var memberCount = 0
-    fileprivate lazy var users: [JMSGUser] = []
-    fileprivate var isMyGroup = false
-    fileprivate var isNeedUpdate = false
-
-    //MARK: - private func
-    private func _init() {
-        self.title = "群组信息"
-        view.backgroundColor = .white
-
-        users = group.memberArray()
-        memberCount = users.count
-        
-        let user = JMSGUser.myInfo()
-//        && group.ownerAppKey == user.appKey!  这里group.ownerAppKey == "" 目测sdk bug
-        if group.owner == user.username  {
-            isMyGroup = true
-        }
-        
-        tableView.separatorStyle = .none
-        tableView.delegate = self
-        tableView.dataSource = self
-        tableView.sectionIndexColor = UIColor(netHex: 0x2dd0cf)
-        tableView.sectionIndexBackgroundColor = .clear
-        tableView.register(JCButtonCell.self, forCellReuseIdentifier: "JCButtonCell")
-        tableView.register(JCMineInfoCell.self, forCellReuseIdentifier: "JCMineInfoCell")
-        tableView.register(GroupAvatorCell.self, forCellReuseIdentifier: "GroupAvatorCell")
-        tableView.frame = CGRect(x: 0, y: 0, width: view.width, height: view.height)
-        view.addSubview(tableView)
-        
-        customLeftBarButton(delegate: self)
-        
-        JMSGGroup.groupInfo(withGroupId: group.gid) { (result, error) in
-            if error == nil {
-                guard let group = result as? JMSGGroup else {
-                    return
-                }
-                self.group = group
-                self.isNeedUpdate = true
-                self._updateGroupInfo()
-            }
-        }
-        
-        NotificationCenter.default.addObserver(self, selector: #selector(_updateGroupInfo), name: NSNotification.Name(rawValue: kUpdateGroupInfo), object: nil)
-    }
-    
-    @objc func _updateGroupInfo() {
-        if !isNeedUpdate {
-            let conv = JMSGConversation.groupConversation(withGroupId: group.gid)
-            group = conv?.target as! JMSGGroup
-        }
-        if group.memberArray().count != memberCount {
-            isNeedUpdate = true
-            memberCount = group.memberArray().count
-        }
-        users = group.memberArray()
-        memberCount = users.count
-        tableView.reloadData()
-    }
-    
-}
-
-extension JCGroupSettingViewController: UITableViewDelegate, UITableViewDataSource {
-    
-    func numberOfSections(in tableView: UITableView) -> Int {
-        
-        return 4
-    }
-    
-    public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
-        
-        switch section {
-        case 0:
-            return 1
-        case 1:
-            return 3
-        case 2:
-//            return 5
-            return 4
-        case 3:
-            return 1
-        default:
-            return 0
-        }
-    }
-    
-    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
-        switch indexPath.section {
-        case 0:
-            if isMyGroup {
-                if memberCount > 13 {
-                    return 314
-                }
-                if memberCount > 8 {
-                    return 260
-                }
-                if memberCount > 3 {
-                    return 200
-                }
-                return 100
-            } else {
-                if memberCount > 14 {
-                    return 314
-                }
-                if memberCount > 9 {
-                    return 260
-                }
-                if memberCount > 4 {
-                    return 200
-                }
-                return 100
-            }
-            
-        case 1:
-            return 45
-        case 2:
-            return 40
-        default:
-            return 45
-        }
-    }
-    
-    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
-        if section == 0 {
-            return 0.0001
-        }
-        return 10
-    }
-    
-    
-    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
-        if indexPath.section == 0 {
-            var cell = tableView.dequeueReusableCell(withIdentifier: "JCGroupSettingCell") as? JCGroupSettingCell
-            if isNeedUpdate {
-                cell = JCGroupSettingCell(style: .default, reuseIdentifier: "JCGroupSettingCell", group: self.group)
-                isNeedUpdate = false
-            }
-            if cell == nil {
-                cell = JCGroupSettingCell(style: .default, reuseIdentifier: "JCGroupSettingCell", group: self.group)
-            }
-            return cell!
-        }
-        if indexPath.section == 3 {
-            return tableView.dequeueReusableCell(withIdentifier: "JCButtonCell", for: indexPath)
-        }
-        if indexPath.section == 1 && indexPath.row == 0 {
-            return tableView.dequeueReusableCell(withIdentifier: "GroupAvatorCell", for: indexPath)
-        }
-        return tableView.dequeueReusableCell(withIdentifier: "JCMineInfoCell", for: indexPath)
-    }
-    
-    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
-        cell.selectionStyle = .none
-        if indexPath.section == 3 {
-            guard let cell = cell as? JCButtonCell else {
-                return
-            }
-            cell.buttonColor = UIColor(netHex: 0xEB424D)
-            cell.buttonTitle = "退出此群"
-            cell.delegate = self
-            return
-        }
-        cell.accessoryType = .disclosureIndicator
-        if indexPath.section == 0 {
-            guard let cell = cell as? JCGroupSettingCell else {
-                return
-            }
-            cell.bindData(self.group)
-            cell.delegate = self
-            cell.accessoryType = .none
-            return
-        }
-
-        if let cell = cell as? GroupAvatorCell {
-            cell.title = "群头像"
-            cell.bindData(group)
-        }
-
-        guard let cell = cell as? JCMineInfoCell else {
-            return
-        }
-        if indexPath.section == 2 {
-            if indexPath.row == 1 {
-                cell.delegate = self
-                cell.indexPate = indexPath
-                cell.accessoryType = .none
-                cell.isSwitchOn = group.isNoDisturb
-                cell.isShowSwitch = true
-            }
-            if indexPath.row == 2 {
-                cell.delegate = self
-                cell.indexPate = indexPath
-                cell.accessoryType = .none
-                cell.isSwitchOn = group.isShieldMessage
-                cell.isShowSwitch = true
-            }
-        }
-        if indexPath.section == 1 {
-            let conv = JMSGConversation.groupConversation(withGroupId: self.group.gid)
-            let group = conv?.target as! JMSGGroup
-            switch indexPath.row {
-            case 1:
-                cell.title = "群聊名称"
-                cell.detail = group.displayName()
-            case 2:
-                cell.title = "群描述"
-                cell.detail = group.desc
-            default:
-                break
-            }
-        } else {
-            switch indexPath.row {
-            case 0:
-                cell.title = "聊天文件"
-            case 1:
-                cell.title = "消息免打扰"
-            case 2:
-                cell.title = "消息屏蔽"
-//            case 2:
-//                cell.title = "清理缓存"
-            case 3:
-                cell.title = "清空聊天记录"
-            default:
-                break
-            }
-        }
-        
-    }
-    
-    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
-        tableView.deselectRow(at: indexPath, animated: true)
-        if indexPath.section == 1 {
-            switch indexPath.row {
-            case 0:
-                let vc = GroupAvatorViewController()
-                vc.group = group
-                navigationController?.pushViewController(vc, animated: true)
-            case 1:
-                let vc = JCGroupNameViewController()
-                vc.group = group
-                navigationController?.pushViewController(vc, animated: true)
-            case 2:
-                let vc = JCGroupDescViewController()
-                vc.group = group
-                navigationController?.pushViewController(vc, animated: true)
-            default:
-                break
-            }
-        }
-        
-        if indexPath.section == 2 {
-            switch indexPath.row {
-//            case 2:
-//                let actionSheet = UIActionSheet(title: nil, delegate: self, cancelButtonTitle: "取消", destructiveButtonTitle: nil, otherButtonTitles: "清理缓存")
-//                actionSheet.tag = 1001
-//                actionSheet.show(in: self.view)
-            case 0:
-                let vc = FileManagerViewController()
-                let conv = JMSGConversation.groupConversation(withGroupId: group.gid)
-                vc.conversation  = conv
-                navigationController?.pushViewController(vc, animated: true)
-            case 3:
-                let actionSheet = UIActionSheet(title: nil, delegate: self, cancelButtonTitle: "取消", destructiveButtonTitle: nil, otherButtonTitles: "清空聊天记录")
-                actionSheet.tag = 1001
-                actionSheet.show(in: self.view)
-            default:
-                break
-            }
-        }
-    }
-}
-
-extension JCGroupSettingViewController: UIAlertViewDelegate {
-    func alertView(_ alertView: UIAlertView, clickedButtonAt buttonIndex: Int) {
-        switch buttonIndex {
-        case 1:
-            MBProgressHUD_JChat.showMessage(message: "退出中...", toView: self.view)
-            group.exit({ (result, error) in
-                MBProgressHUD_JChat.hide(forView: self.view, animated: true)
-                if error == nil {
-                    self.navigationController?.popToRootViewController(animated: true)
-                } else {
-                    MBProgressHUD_JChat.show(text: "\(String.errorAlert(error! as NSError))", view: self.view)
-                }
-            })
-        default:
-            break
-        }
-    }
-}
-
-extension JCGroupSettingViewController: JCMineInfoCellDelegate {
-    func mineInfoCell(clickSwitchButton button: UISwitch, indexPath: IndexPath?) {
-        if indexPath != nil {
-            switch (indexPath?.row)! {
-            case 1:
-                if group.isNoDisturb == button.isOn {
-                    return
-                }
-                // 消息免打扰
-                group.setIsNoDisturb(button.isOn, handler: { (result, error) in
-                    MBProgressHUD_JChat.hide(forView: self.view, animated: true)
-                    if error != nil {
-                        button.isOn = !button.isOn
-                        MBProgressHUD_JChat.show(text: "\(String.errorAlert(error! as NSError))", view: self.view)
-                    }
-                })
-            case 2:
-                if group.isShieldMessage == button.isOn {
-                    return
-                }
-                // 消息屏蔽
-                group.setIsShield(button.isOn, handler: { (result, error) in
-                    MBProgressHUD_JChat.hide(forView: self.view, animated: true)
-                    if error != nil {
-                        button.isOn = !button.isOn
-                        MBProgressHUD_JChat.show(text: "\(String.errorAlert(error! as NSError))", view: self.view)
-                    }
-                })
-            default:
-                break
-            }
-        }
-    }
-}
-
-extension JCGroupSettingViewController: JCButtonCellDelegate {
-    func buttonCell(clickButton button: UIButton) {
-        let alertView = UIAlertView(title: "退出此群", message: "确定要退出此群?", delegate: self, cancelButtonTitle: "取消", otherButtonTitles: "确定")
-        alertView.show()
-    }
-}
-
-extension JCGroupSettingViewController: JCGroupSettingCellDelegate {
-    func clickMoreButton(clickButton button: UIButton) {
-        let vc = JCGroupMembersViewController()
-        vc.group = self.group
-        self.navigationController?.pushViewController(vc, animated: true)
-    }
-    
-    //增加群组成员 -- 暂不实现
-    func clickAddCell(cell: JCGroupSettingCell) {
-//        let vc = JCUpdateMemberViewController()
-//        vc.group = group
-//        self.navigationController?.pushViewController(vc, animated: true)
-    }
-    
-    //删除群组成员 -- 暂不实现
-    func clickRemoveCell(cell: JCGroupSettingCell) {
-//        let vc = JCRemoveMemberViewController()
-//        vc.group = group
-//        self.navigationController?.pushViewController(vc, animated: true)
-    }
-    
-    func didSelectCell(cell: JCGroupSettingCell, indexPath: IndexPath) {
-        let index = indexPath.section * 5 + indexPath.row
-        let user = users[index]
-        if user.isEqual(to: JMSGUser.myInfo()) {
-//            navigationController?.pushViewController(JCMyInfoViewController(), animated: true)
-            navigationController?.pushViewController(SPersonViewController(), animated: true)
-            return
-        }
-//        let vc = JCUserInfoViewController()
-//        vc.user = user
-//        navigationController?.pushViewController(vc, animated: true)
-        let storyBoard = UIStoryboard(name: "contacts", bundle: nil)
-        guard let personVC = storyBoard.instantiateViewController(withIdentifier: "ContactPersonInfoV2") as?  ContactPersonInfoV2ViewController else {
-            return
-        }
-        let person = PersonV2()
-        person.id = user.username
-        personVC.person = person
-        navigationController?.pushViewController(personVC, animated: true)
-        
-    }
-}
-
-extension JCGroupSettingViewController: UIActionSheetDelegate {
-    func actionSheet(_ actionSheet: UIActionSheet, clickedButtonAt buttonIndex: Int) {
-//        if actionSheet.tag == 1001 {
-//            // SDK 暂无该功能
-//        }
-        
-        if actionSheet.tag == 1001 {
-            if buttonIndex == 1 {
-                let conv = JMSGConversation.groupConversation(withGroupId: group.gid)
-                conv?.deleteAllMessages()
-                NotificationCenter.default.post(name: Notification.Name(rawValue: kDeleteAllMessage), object: nil)
-                MBProgressHUD_JChat.show(text: "成功清空", view: self.view)
-            }
-        }
-    }
-}
-
-extension JCGroupSettingViewController: UIGestureRecognizerDelegate {
-    public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
-        return true
-    }
-}

+ 0 - 199
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/JCRemindListViewController.swift

@@ -1,199 +0,0 @@
-//
-//  JCRemindListViewController.swift
-//  JChat
-//
-//  Created by deng on 2017/6/26.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-class JCRemindListViewController: UIViewController {
-    
-    typealias handleFinish = (_ user: JMSGUser?, _ isAtll: Bool, _ length: Int) -> ()
-    
-    var finish: handleFinish!
-    
-    var group: JMSGGroup!
-
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        _init()
-    }
-
-    private lazy var cancel = UIButton(frame: CGRect(x: 0, y: 0, width: 50, height: 36))
-    fileprivate lazy var tableView: UITableView = {
-        var tableView = UITableView(frame: .zero, style: .grouped)
-        tableView.delegate = self
-        tableView.dataSource = self
-        tableView.separatorStyle = .none
-        tableView.keyboardDismissMode = .onDrag
-        tableView.sectionIndexColor = UIColor(netHex: 0x2dd0cf)
-        tableView.sectionIndexBackgroundColor = .clear
-        tableView.register(JCContacterCell.self, forCellReuseIdentifier: "JCContacterCell")
-        tableView.frame = CGRect(x: 0, y: 0, width: self.view.width, height: self.view.height)
-        return tableView
-    }()
-    fileprivate lazy var searchView: UISearchBar = {
-        let searchView = UISearchBar.default
-        searchView.frame = CGRect(x: 0, y: 0, width: self.view.width, height: 31)
-        searchView.delegate = self
-        return searchView
-    }()
-    
-    fileprivate lazy var tagArray = ["所有成员"]
-    fileprivate lazy var users: [JMSGUser] = []
-    fileprivate lazy var keys: [String] = []
-    fileprivate lazy var data: Dictionary<String, [JMSGUser]> = Dictionary()
-    
-    fileprivate lazy var defaultGroupIcon = UIImage.loadImage("com_icon_group_36")
-    fileprivate var isSearching = false
-    
-    private func _init() {
-        self.title = "选择提醒的人"
-        view.backgroundColor = .white
-        _setupNavigation()
-        tableView.tableHeaderView = searchView
-        users = group.memberArray()
-        _classify(users)
-        view.addSubview(tableView)
-    }
-    
-    private func _setupNavigation() {
-        cancel.addTarget(self, action: #selector(_clickNavRightButton), for: .touchUpInside)
-        cancel.setTitle("取消", for: .normal)
-        cancel.titleLabel?.font = UIFont.systemFont(ofSize: 15)
-        let item = UIBarButtonItem(customView: cancel)
-        navigationItem.leftBarButtonItem = item
-    }
-    
-    @objc func _clickNavRightButton() {
-        dismiss(animated: true, completion: nil)
-    }
-    
-    func _classify(_ users: [JMSGUser]) {
-        keys.removeAll()
-        data.removeAll()
-        for item in users {
-            if item.username == JMSGUser.myInfo().username {
-                continue
-            }
-            var key = item.displayName().firstCharacter()
-            if !key.isLetterOrNum() {
-                key = "#"
-            }
-            var array = data[key]
-            if array == nil {
-                array = [item]
-            } else {
-                array?.append(item)
-            }
-            if !keys.contains(key) {
-                keys.append(key)
-            }
-            data[key] = array
-        }
-        keys = keys.sortedKeys()
-    }
-    
-    fileprivate func filter(_ searchString: String) {
-        if searchString.isEmpty || searchString == "" {
-            isSearching = false
-            _classify(users)
-            tableView.reloadData()
-            return
-        }
-        isSearching = true
-        let filteredUsersArray = _JCFilterUsers(users: users, string: searchString)
-        _classify(filteredUsersArray)
-        tableView.reloadData()
-    }
-}
-
-//Mark: -
-extension JCRemindListViewController: UITableViewDelegate, UITableViewDataSource {
-    
-    func numberOfSections(in tableView: UITableView) -> Int {
-        if isSearching {
-            return keys.count
-        }
-        if users.count > 0 {
-            return keys.count + 1
-        }
-        return 1
-    }
-    
-    public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
-        if section == 0 && !isSearching {
-            return tagArray.count
-        }
-        return isSearching ? data[keys[section]]!.count : data[keys[section - 1]]!.count
-    }
-    
-    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
-        if isSearching {
-            return keys[section]
-        }
-        if section == 0 {
-            return ""
-        }
-        return keys[section - 1]
-    }
-    
-    func sectionIndexTitles(for tableView: UITableView) -> [String]? {
-        return keys
-    }
-    
-    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
-        return 55
-    }
-    
-    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
-        if section == 0 {
-            return 25
-        }
-        return 10
-    }
-    
-    
-    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
-        return tableView.dequeueReusableCell(withIdentifier: "JCContacterCell", for: indexPath)
-    }
-    
-    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
-        guard let cell = cell as? JCContacterCell else {
-            return
-        }
-        if indexPath.section == 0 && !isSearching {
-            switch indexPath.row {
-            case 0:
-                cell.title = tagArray[indexPath.row]
-                cell.icon = defaultGroupIcon
-            default:
-                break
-            }
-            return
-        }
-        let user = isSearching ? data[keys[indexPath.section]]?[indexPath.row] : data[keys[indexPath.section - 1]]?[indexPath.row]
-        cell.bindDate(user!)
-    }
-    
-    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
-        tableView.deselectRow(at: indexPath, animated: true)
-        if indexPath.section == 0 && !isSearching {
-            finish(nil, true, 4)
-            dismiss(animated: true, completion: nil)
-            return
-        }
-        if let user = isSearching ? data[keys[indexPath.section]]?[indexPath.row] : data[keys[indexPath.section - 1]]?[indexPath.row]  {
-            finish(user, false, user.displayName().length)
-        }
-        dismiss(animated: true, completion: nil)
-    }
-}
-
-extension JCRemindListViewController: UISearchBarDelegate {
-    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
-        filter(searchText)
-    }
-}

+ 0 - 301
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/JCRemoveMemberViewController.swift

@@ -1,301 +0,0 @@
-//
-//  JCRemoveMemberViewController.swift
-//  JChat
-//
-//  Created by deng on 2017/5/16.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-import JMessage
-
-class JCRemoveMemberViewController: UIViewController {
-    
-    var group: JMSGGroup!
-    
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        _init()
-    }
-
-    fileprivate lazy var toolView: UIView = UIView(frame: CGRect(x: 0, y: 64, width: self.view.width, height: 55))
-    fileprivate var tableView: UITableView = UITableView(frame: .zero, style: .grouped)
-    fileprivate var collectionView: UICollectionView!
-    fileprivate lazy var searchView: UISearchBar = UISearchBar.default
-
-    fileprivate lazy var delButton = UIButton(frame: CGRect(x: 0, y: 0, width: 120, height: 28))
-    
-    fileprivate lazy var users: [JMSGUser] = []
-    fileprivate lazy var keys: [String] = []
-    fileprivate lazy var data: Dictionary<String, [JMSGUser]> = Dictionary()
-    
-    fileprivate lazy var filteredUsersArray: [JMSGUser] = []
-    
-    fileprivate lazy var selectUsers: [JMSGUser] = []
-    
-    private func _init() {
-        self.title = "删除成员"
-        view.backgroundColor = .white
-        automaticallyAdjustsScrollViewInsets = false
-
-        view.addSubview(toolView)
-        
-        tableView.delegate = self
-        tableView.dataSource = self
-        tableView.keyboardDismissMode = .onDrag
-        tableView.sectionIndexColor = UIColor(netHex: 0x2dd0cf)
-        tableView.sectionIndexBackgroundColor = .clear
-        tableView.register(JCSelectMemberCell.self, forCellReuseIdentifier: "JCSelectMemberCell")
-        tableView.frame = CGRect(x: 0, y: 31 + 64, width: view.width, height: view.height - 55 - 64)
-        view.addSubview(tableView)
-        
-        let flowLayout = UICollectionViewFlowLayout()
-        flowLayout.scrollDirection = .horizontal
-        flowLayout.minimumInteritemSpacing = 0
-        flowLayout.minimumLineSpacing = 0
-        collectionView = UICollectionView(frame: .zero, collectionViewLayout: flowLayout)
-        collectionView.backgroundColor = .clear
-        collectionView.delegate = self
-        collectionView.dataSource = self
-        collectionView.register(JCUpdateMemberCell.self, forCellWithReuseIdentifier: "JCUpdateMemberCell")
-        
-        searchView.frame = CGRect(x: 15, y: 0, width: toolView.width - 30, height: 31)
-        searchView.delegate = self
-
-        users = group.memberArray()
-        if group.owner == JMSGUser.myInfo().username  {
-            users = users.filter({ (u) -> Bool in
-                u.username != JMSGUser.myInfo().username || u.appKey != JMSGUser.myInfo().appKey
-            })
-        }
-        filteredUsersArray = users
-        _classify(users)
-        
-        toolView.addSubview(searchView)
-        toolView.addSubview(collectionView)
-        
-        _setupNavigation()
-    }
-    
-    private func _setupNavigation() {
-        delButton.addTarget(self, action: #selector(_clickNavRightButton(_:)), for: .touchUpInside)
-        delButton.setTitle("删除", for: .normal)
-        delButton.titleLabel?.font = UIFont.systemFont(ofSize: 15)
-        delButton.contentHorizontalAlignment = .right
-        let item = UIBarButtonItem(customView: delButton)
-        navigationItem.rightBarButtonItem =  item
-        navigationController?.navigationItem.rightBarButtonItem?.isEnabled = false
-    }
-    
-    private func _classify(_ users: [JMSGUser]) {
-        
-        filteredUsersArray = users
-        
-        keys.removeAll()
-        data.removeAll()
-        
-        for item in users {
-            let key = item.displayName().firstCharacter()
-            var array = data[key]
-            if array == nil {
-                array = [item]
-            } else {
-                array?.append(item)
-            }
-            if !keys.contains(key) {
-                keys.append(key)
-            }
-            data[key] = array
-        }
-        keys = keys.sorted(by: { (str1, str2) -> Bool in
-            return str1 < str2
-        })
-        tableView.reloadData()
-        collectionView.reloadData()
-    }
-    
-    fileprivate func _reloadCollectionView() {
-        if selectUsers.count > 0 {
-            delButton.alpha = 1.0
-            delButton.setTitle("删除(\(selectUsers.count))", for: .normal)
-            navigationController?.navigationItem.rightBarButtonItem?.isEnabled = true
-        } else {
-            delButton.alpha = 0.5
-            delButton.setTitle("删除", for: .normal)
-            navigationController?.navigationItem.rightBarButtonItem?.isEnabled = false
-        }
-        switch selectUsers.count {
-        case 0:
-            collectionView.frame = .zero
-            searchView.frame = CGRect(x: 15, y: 0, width: toolView.width - 30, height: 31)
-            toolView.frame = CGRect(x: 0, y: 64, width: toolView.width, height: 31)
-            tableView.frame = CGRect(x: tableView.x, y: 64 + 31, width: tableView.width, height: view.height - 64 - 31)
-        case 1:
-            collectionView.frame = CGRect(x: 10, y: 0, width: 46, height: 55)
-            searchView.frame = CGRect(x: 5 + 46, y: 0, width: toolView.width - 5 - 46, height: 55)
-            toolView.frame = CGRect(x: 0, y: 64, width: toolView.width, height: 55)
-            tableView.frame = CGRect(x: tableView.x, y: 64 + 55, width: tableView.width, height: view.height - 64 - 55)
-        case 2:
-            collectionView.frame = CGRect(x: 10, y: 0, width: 92, height: 55)
-            searchView.frame = CGRect(x: 5 + 46 * 2, y: 0, width: toolView.width - 5 - 46 * 2, height: 55)
-        case 3:
-            collectionView.frame = CGRect(x: 10, y: 0, width: 138, height: 55)
-            searchView.frame = CGRect(x: 5 + 46 * 3, y: 0, width: toolView.width - 5 - 46 * 3, height: 55)
-        case 4:
-            collectionView.frame = CGRect(x: 10, y: 0, width: 184, height: 55)
-            searchView.frame = CGRect(x: 5 + 46 * 4, y: 0, width: toolView.width - 5 - 46 * 4, height: 55)
-        default:
-            collectionView.frame = CGRect(x: 10, y: 0, width: 230, height: 55)
-            searchView.frame = CGRect(x: 5 + 46 * 5, y: 0, width: toolView.width - 5 - 46 * 5, height: 55)
-        }
-        collectionView.reloadData()
-    }
-    
-    func _clickNavRightButton(_ sender: UIButton) {
-        var userNames: [String] = []
-        for item in selectUsers {
-            userNames.append(item.username)
-        }
-        MBProgressHUD_JChat.showMessage(message: "删除中...", toView: view)
-        group.removeMembers(withUsernameArray: userNames) { (result, error) in
-            MBProgressHUD_JChat.hide(forView: self.view, animated: true)
-            if error == nil {
-                NotificationCenter.default.post(name: Notification.Name(rawValue: kUpdateGroupInfo), object: nil)
-                self.navigationController?.popViewController(animated: true)
-            } else {
-                MBProgressHUD_JChat.show(text: "删除失败,请重试", view: self.view)
-            }
-        }
-    }
-    
-    fileprivate func filter(_ searchString: String) {
-        if searchString.isEmpty || searchString == "" {
-            _classify(users)
-            return
-        }
-        filteredUsersArray = _JCFilterUsers(users: users, string: searchString)
-        _classify(filteredUsersArray)
-    }
-}
-
-//Mark: - UITableViewDelegate & UITableViewDataSource
-extension JCRemoveMemberViewController: UITableViewDelegate, UITableViewDataSource {
-    
-    func numberOfSections(in tableView: UITableView) -> Int {
-        if filteredUsersArray.count > 0 {
-            return keys.count
-        }
-        return 0
-    }
-    
-    public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
-        return data[keys[section]]!.count
-    }
-    
-    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
-        return keys[section]
-    }
-    
-    func sectionIndexTitles(for tableView: UITableView) -> [String]? {
-        return keys
-    }
-    
-    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
-        return 55
-    }
-    
-    
-    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
-        if section == 0 {
-            return 30
-        }
-        return 10
-    }
-    
-    
-    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
-        return tableView.dequeueReusableCell(withIdentifier: "JCSelectMemberCell", for: indexPath)
-    }
-    
-    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
-        guard let cell = cell as? JCSelectMemberCell else {
-            return
-        }
-        let user = data[keys[indexPath.section]]?[indexPath.row]
-        cell.bindDate(user!)
-        if selectUsers.contains(where: { (u) -> Bool in
-            return u.username == user?.username && u.appKey == user?.appKey
-        })  {
-            cell.selectIcon = UIImage.loadImage("com_icon_select")
-        } else {
-            cell.selectIcon = UIImage.loadImage("com_icon_unselect")
-        }
-    }
-    
-    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
-        tableView.deselectRow(at: indexPath, animated: true)
-        guard let cell = tableView.cellForRow(at: indexPath) as? JCSelectMemberCell else {
-            return
-        }
-        guard let user = data[keys[indexPath.section]]?[indexPath.row] else {
-            return
-        }
-        if selectUsers.contains(where: { (u) -> Bool in
-            return u.username == user.username && u.appKey == user.appKey
-        })  {
-            // remove
-            cell.selectIcon = UIImage.loadImage("com_icon_unselect")
-            selectUsers = selectUsers.filter({ (u) -> Bool in
-                u.username != user.username || u.appKey != user.appKey
-            })
-            _reloadCollectionView()
-        } else {
-            selectUsers.append(user)
-            cell.selectIcon = UIImage.loadImage("com_icon_select")
-            _reloadCollectionView()
-        }
-        if selectUsers.count > 0 {
-            collectionView.scrollToItem(at: IndexPath(row: selectUsers.count - 1, section: 0), at: .right, animated: false)
-        }
-    }
-}
-
-extension JCRemoveMemberViewController: UICollectionViewDelegate, UICollectionViewDataSource {
-    func numberOfSections(in collectionView: UICollectionView) -> Int {
-        return 1
-    }
-    
-    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
-        return selectUsers.count
-    }
-    
-    func collectionView(_ collectionView: UICollectionView,
-                        layout collectionViewLayout: UICollectionViewLayout,
-                        sizeForItemAtIndexPath indexPath: IndexPath) -> CGSize {
-        return CGSize(width: 46, height: 55)
-    }
-    
-    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
-        return collectionView.dequeueReusableCell(withReuseIdentifier: "JCUpdateMemberCell", for: indexPath)
-    }
-    
-    func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
-        guard let cell = cell as? JCUpdateMemberCell else {
-            return
-        }
-        cell.backgroundColor = .white
-        cell.bindDate(user: selectUsers[indexPath.row])
-    }
-
-    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
-        selectUsers.remove(at: indexPath.row)
-        tableView.reloadData()
-        _reloadCollectionView()
-    }
-}
-
-extension JCRemoveMemberViewController: UISearchBarDelegate {
-    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
-        filter(searchText)
-    }
-}

+ 0 - 256
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/JCSingleSettingViewController.swift

@@ -1,256 +0,0 @@
-//
-//  JCSingleSettingViewController.swift
-//  JChat
-//
-//  Created by deng on 2017/4/5.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-import JMessage
-
-class JCSingleSettingViewController: UIViewController, CustomNavigation {
-    
-    var user: JMSGUser!
-
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        _init()
-    }
-
-    private lazy var tableView: UITableView = {
-        var tableView = UITableView(frame: CGRect(x: 0, y: 0, width: self.view.width, height: self.view.height), style: .grouped)
-        tableView.separatorStyle = .none
-        tableView.delegate = self
-        tableView.dataSource = self
-        tableView.sectionIndexColor = UIColor(netHex: 0x2dd0cf)
-        tableView.sectionIndexBackgroundColor = .clear
-        tableView.register(JCSingleSettingCell.self, forCellReuseIdentifier: "JCSingleSettingCell")
-        tableView.register(JCButtonCell.self, forCellReuseIdentifier: "JCButtonCell")
-        tableView.register(JCMineInfoCell.self, forCellReuseIdentifier: "JCMineInfoCell")
-        return tableView
-    }()
-    
-    fileprivate lazy var leftButton = UIButton(frame: CGRect(x: 0, y: 0, width: 60, height: 65 / 3))
-    
-    //MARK: - private func 
-    private func _init() {
-        self.title = "聊天设置"
-        view.backgroundColor = .white
-
-        view.addSubview(tableView)
-        customLeftBarButton(delegate: self)
-    }
-}
-
-extension JCSingleSettingViewController: UITableViewDelegate, UITableViewDataSource {
-    
-    func numberOfSections(in tableView: UITableView) -> Int {
-        return 3
-    }
-    
-    public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
-        
-        switch section {
-        case 0:
-            return 1
-        case 1:
-            return 3
-        case 2:
-            return 1
-        default:
-            return 0
-        }
-    }
-    
-    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
-        switch indexPath.section {
-        case 0:
-            return 105
-        case 1:
-            return 45
-        case 2:
-            return 40
-        default:
-            return 45
-        }
-    }
-    
-    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
-        if section == 0 {
-            return 0.0001
-        }
-        return 10
-    }
-    
-    
-    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
-        if indexPath.section == 0 {
-            return tableView.dequeueReusableCell(withIdentifier: "JCSingleSettingCell", for: indexPath)
-        }
-        if indexPath.section == 2 {
-            return tableView.dequeueReusableCell(withIdentifier: "JCButtonCell", for: indexPath)
-        }
-        return tableView.dequeueReusableCell(withIdentifier: "JCMineInfoCell", for: indexPath)
-    }
-    
-    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
-        cell.selectionStyle = .none
-        if indexPath.section == 2 {
-            guard let cell = cell as? JCButtonCell else {
-                return
-            }
-            if !user.isFriend {
-                cell.buttonColor = O2ThemeManager.color(for: "Base.base_color")!
-                cell.buttonTitle = "添加好友"
-                cell.delegate = self
-            } else {
-                cell.buttonColor = O2ThemeManager.color(for: "Base.base_color")!
-                cell.buttonTitle = "删除好友"
-                cell.delegate = self
-            }
-            return
-        }
-        cell.accessoryType = .disclosureIndicator
-        if indexPath.section == 0 {
-            guard let cell = cell as? JCSingleSettingCell else {
-                return
-            }
-            cell.bindData(user)
-            cell.delegate = self
-            cell.accessoryType = .none
-            return
-        }
-        guard let cell = cell as? JCMineInfoCell else {
-            return
-        }
-        if indexPath.section == 1 && indexPath.row == 1 {
-            cell.delegate = self
-            cell.accessoryType = .none
-            cell.isShowSwitch = true
-        }
-        switch indexPath.row {
-        case 0:
-            cell.title = "聊天文件"
-        case 1:
-            cell.isSwitchOn = user.isNoDisturb
-            cell.title = "消息免打扰"
-//        case 1:
-//            cell.isSwitchOn = JMessage.isSetGlobalNoDisturb()
-//            cell.title = "清理缓存"
-        case 2:
-            cell.title = "清空聊天记录"
-        default:
-            break
-        }
-    }
-    
-    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
-        tableView.deselectRow(at: indexPath, animated: true)
-        if indexPath.section == 1 {
-            switch indexPath.row {
-            case 0:
-                let vc = FileManagerViewController()
-                let conv = JMSGConversation.singleConversation(withUsername: user.username)
-                vc.conversation  = conv
-                navigationController?.pushViewController(vc, animated: true)
-            case 2:
-                let actionSheet = UIActionSheet(title: nil, delegate: self, cancelButtonTitle: "取消", destructiveButtonTitle: nil, otherButtonTitles: "清空聊天记录")
-                actionSheet.tag = 1001
-                actionSheet.show(in: view)
-            case 3:
-                break
-            default:
-                break
-            }
-        }
-    }
-}
-
-extension JCSingleSettingViewController: UIActionSheetDelegate {
-    func actionSheet(_ actionSheet: UIActionSheet, clickedButtonAt buttonIndex: Int) {
-        //        if actionSheet.tag == 1001 {
-        //            // SDK 暂无该功能
-        //        }
-        
-        if actionSheet.tag == 1001 {
-            if buttonIndex == 1 {
-                let conv = JMSGConversation.singleConversation(withUsername: user.username)
-                conv?.deleteAllMessages()
-                NotificationCenter.default.post(name: Notification.Name(rawValue: kDeleteAllMessage), object: nil)
-                MBProgressHUD_JChat.show(text: "成功清空", view: view)
-            }
-        }
-    }
-    
-}
-
-extension JCSingleSettingViewController: JCMineInfoCellDelegate {
-    func mineInfoCell(clickSwitchButton button: UISwitch, indexPath: IndexPath?) {
-        if user.isNoDisturb != button.isOn {
-            MBProgressHUD_JChat.showMessage(message: "修改中", toView: view)
-            user.setIsNoDisturb(button.isOn, handler: { (result, error) in
-                MBProgressHUD_JChat.hide(forView: self.view, animated: true)
-                if error == nil {
-                    MBProgressHUD_JChat.show(text: "修改成功", view: self.view)
-                } else {
-                    MBProgressHUD_JChat.show(text: "修改失败", view: self.view)
-                }
-            })
-        }
-    }
-}
-
-extension JCSingleSettingViewController: JCButtonCellDelegate {
-    func buttonCell(clickButton button: UIButton) {
-        if user.isFriend {
-            let alertView = UIAlertView(title: "删除好友", message: "是否确认删除该好友?", delegate: self, cancelButtonTitle: "取消", otherButtonTitles: "删除")
-            alertView.show()
-        } else {
-            let vc = JCAddFriendViewController()
-            vc.user = user
-            navigationController?.pushViewController(vc, animated: true)
-        }
-    }
-}
-
-extension JCSingleSettingViewController: UIAlertViewDelegate {
-    func alertView(_ alertView: UIAlertView, clickedButtonAt buttonIndex: Int) {
-        if buttonIndex == 1 {
-            JMSGFriendManager.removeFriend(withUsername: user.username, appKey: user.appKey, completionHandler: { (result, error) in
-                if error == nil {
-                    let conv = JMSGConversation.singleConversation(withUsername: self.user.username)
-                    if conv != nil {
-                        JMSGConversation.deleteSingleConversation(withUsername: self.user.username)
-                    }
-                    NotificationCenter.default.post(name: Notification.Name(rawValue: kUpdateFriendList), object: nil)
-                    self.navigationController?.popToRootViewController(animated: true)
-                } else {
-                    MBProgressHUD_JChat.show(text: "\(String.errorAlert(error! as NSError))", view: self.view)
-                }
-            })
-        }
-    }
-}
-
-extension JCSingleSettingViewController: JCSingleSettingCellDelegate {
-    func singleSettingCell(clickAddButton button: UIButton) {
-        let vc = JCUpdateMemberViewController()
-        vc.isAddMember = false
-        vc.currentUser = user
-        navigationController?.pushViewController(vc, animated: true)
-    }
-    
-    func singleSettingCell(clickAvatorButton button: UIButton) {
-        let vc = JCUserInfoViewController()
-        vc.user = user
-        vc.isOnConversation = true
-        navigationController?.pushViewController(vc, animated: true)
-    }
-}
-
-extension JCSingleSettingViewController: UIGestureRecognizerDelegate {
-    public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
-        return true
-    }
-}

+ 0 - 441
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/JCUpdateMemberViewController.swift

@@ -1,441 +0,0 @@
-//
-//  JCUpdateMemberViewController.swift
-//  JChat
-//
-//  Created by deng on 2017/5/11.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-import JMessage
-
-class JCUpdateMemberViewController: UIViewController {
-    
-    var isAddMember = true
-    var group: JMSGGroup?
-    var currentUser: JMSGUser?
-
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        _init()
-    }
-    
-    override func viewDidAppear(_ animated: Bool) {
-        super.viewDidAppear(animated)
-        if selectUsers.count == 0 {
-            confirm.alpha = 0.5
-            navigationController?.navigationItem.rightBarButtonItem?.isEnabled = false
-        }
-    }
-
-    private var topOffset: CGFloat {
-        if isIPhoneX {
-            return 88
-        }
-        return 64
-    }
-
-    fileprivate lazy var toolView: UIView = UIView(frame: CGRect(x: 0, y: self.topOffset, width: self.view.width, height: 55))
-    fileprivate var tableView: UITableView = UITableView(frame: .zero, style: .grouped)
-    fileprivate var collectionView: UICollectionView!
-    fileprivate lazy var searchBar: UISearchBar = UISearchBar.default
-    fileprivate lazy var confirm = UIButton(frame: CGRect(x: 0, y: 0, width: 120, height: 28))
-    
-    fileprivate lazy var users: [JMSGUser] = []
-    fileprivate lazy var keys: [String] = []
-    fileprivate lazy var data: Dictionary<String, [JMSGUser]> = Dictionary()
-    
-    fileprivate lazy var filteredUsersArray: [JMSGUser] = []
-    fileprivate lazy var selectUsers: [JMSGUser] = []
-    fileprivate var searchUser: JMSGUser?
-    fileprivate var members: [JMSGUser]?
-    
-    fileprivate lazy var tipsView: UIView = {
-        let view = UIView(frame: CGRect(x: 0, y: self.topOffset + 31 + 5, width: self.view.width, height: self.view.height - 31 - self.topOffset - 5))
-        view.backgroundColor = .white
-        let tips = UILabel(frame: CGRect(x: 0, y: 0, width: view.width, height: 50))
-        tips.font = UIFont.systemFont(ofSize: 16)
-        tips.textColor = UIColor(netHex: 0x999999)
-        tips.textAlignment = .center
-        tips.text = "未搜索到用户"
-        view.addSubview(tips)
-        view.isHidden = true
-        return view
-    }()
-    
-    private func _init() {
-        view.backgroundColor = .white
-        automaticallyAdjustsScrollViewInsets = false
-        if isAddMember {
-            self.title = "添加成员"
-            members = group?.memberArray()
-        } else {
-            self.title = "发起群聊"
-        }
-        
-        view.addSubview(toolView)
-        
-        tableView.delegate = self
-        tableView.dataSource = self
-        tableView.keyboardDismissMode = .onDrag
-        tableView.sectionIndexColor = UIColor(netHex: 0x2dd0cf)
-        tableView.sectionIndexBackgroundColor = .clear
-        tableView.register(JCSelectMemberCell.self, forCellReuseIdentifier: "JCSelectMemberCell")
-        tableView.frame = CGRect(x: 0, y: 31 + topOffset, width: view.width, height: view.height - 31 - topOffset)
-        view.addSubview(tableView)
-        
-        view.addSubview(tipsView)
-        
-        _classify([], isFrist: true)
-        
-        let flowLayout = UICollectionViewFlowLayout()
-        flowLayout.scrollDirection = .horizontal
-        flowLayout.minimumInteritemSpacing = 0
-        flowLayout.minimumLineSpacing = 0
-        collectionView = UICollectionView(frame: .zero, collectionViewLayout: flowLayout)
-        collectionView.backgroundColor = .clear
-        collectionView.delegate = self
-        collectionView.dataSource = self
-        collectionView.register(JCUpdateMemberCell.self, forCellWithReuseIdentifier: "JCUpdateMemberCell")
-        
-        searchBar.frame = CGRect(x: 15, y: 0, width: toolView.width - 30, height: 31)
-        searchBar.delegate = self
-        searchBar.placeholder = "可搜索非好友"
-
-        toolView.addSubview(searchBar)
-        toolView.addSubview(collectionView)
-        
-        _setupNavigation()
-    }
-    
-    private func _setupNavigation() {
-        confirm.addTarget(self, action: #selector(_clickNavRightButton(_:)), for: .touchUpInside)
-        confirm.setTitle("确定", for: .normal)
-        confirm.titleLabel?.font = UIFont.systemFont(ofSize: 15)
-        confirm.contentHorizontalAlignment = .right
-        let item = UIBarButtonItem(customView: confirm)
-        navigationItem.rightBarButtonItem =  item
-    }
-    
-    fileprivate func _classify(_ users: [JMSGUser], isFrist: Bool = false) {
-        
-        if users.count > 0 {
-            tipsView.isHidden = true
-        }
-        
-        if isFrist {
-            JMSGFriendManager.getFriendList { (result, error) in
-                if error == nil {
-                    self.users.removeAll()
-                    self.keys.removeAll()
-                    self.data.removeAll()
-                    for item in result as! [JMSGUser] {
-                        if let currentUser = self.currentUser {
-                            if item.username == currentUser.username {
-                                continue
-                            }
-                        }
-                        self.users.append(item)
-                        var key = item.displayName().firstCharacter()
-                        if !key.isLetterOrNum() {
-                            key = "#"
-                        }
-                        var array = self.data[key]
-                        if array == nil {
-                            array = [item]
-                        } else {
-                            array?.append(item)
-                        }
-                        if !self.keys.contains(key) {
-                            self.keys.append(key)
-                        }
-                        
-                        self.data[key] = array
-                    }
-                    self.filteredUsersArray = self.users
-                    self.keys = self.keys.sortedKeys()
-                    self.tableView.reloadData()
-                    self.collectionView.reloadData()
-                }
-            }
-        } else {
-            filteredUsersArray = users
-            keys.removeAll()
-            data.removeAll()
-            for item in users {
-                var key = item.displayName().firstCharacter()
-                if !key.isLetterOrNum() {
-                    key = "#"
-                }
-                var array = data[key]
-                if array == nil {
-                    array = [item]
-                } else {
-                    array?.append(item)
-                }
-                if !keys.contains(key) {
-                    keys.append(key)
-                }
-                
-                data[key] = array
-            }
-            keys = keys.sortedKeys()
-            tableView.reloadData()
-            collectionView.reloadData()
-        }
-    }
-    
-    fileprivate func _removeUser(_ user: JMSGUser) {
-        selectUsers = selectUsers.filter({ (u) -> Bool in
-            u.username != user.username || u.appKey != user.appKey
-        })
-    }
-    
-    fileprivate func _reloadCollectionView() {
-        if selectUsers.count > 0 {
-            confirm.alpha = 1.0
-            confirm.setTitle("确定(\(selectUsers.count))", for: .normal)
-            navigationController?.navigationItem.rightBarButtonItem?.isEnabled = true
-        } else {
-            confirm.alpha = 0.5
-            confirm.setTitle("确定", for: .normal)
-            navigationController?.navigationItem.rightBarButtonItem?.isEnabled = false
-        }
-        switch selectUsers.count {
-        case 0:
-            collectionView.frame = .zero
-            searchBar.frame = CGRect(x: 15, y: 0, width: toolView.width - 30, height: 31)
-            toolView.frame = CGRect(x: 0, y: topOffset, width: toolView.width, height: 31)
-            tableView.frame = CGRect(x: tableView.x, y: topOffset + 31, width: tableView.width, height: view.height - topOffset - 31)
-            tipsView.frame = CGRect(x: 0, y: topOffset + 31 + 5, width: view.width, height: view.height - 31 - topOffset - 5)
-        case 1:
-            collectionView.frame = CGRect(x: 10, y: 0, width: 46, height: 55)
-            searchBar.frame = CGRect(x: 5 + 46, y: 0, width: toolView.width - 5 - 46, height: 55)
-            toolView.frame = CGRect(x: 0, y: topOffset, width: toolView.width, height: 55)
-            tableView.frame = CGRect(x: tableView.x, y: topOffset + 55, width: tableView.width, height: view.height - topOffset - 55)
-            tipsView.frame = CGRect(x: 0, y: topOffset + 31 + 5 + 24, width: view.width, height: view.height - 31 - 40 - 5)
-        case 2:
-            collectionView.frame = CGRect(x: 10, y: 0, width: 92, height: 55)
-            searchBar.frame = CGRect(x: 5 + 46 * 2, y: 0, width: toolView.width - 5 - 46 * 2, height: 55)
-        case 3:
-            collectionView.frame = CGRect(x: 10, y: 0, width: 138, height: 55)
-            searchBar.frame = CGRect(x: 5 + 46 * 3, y: 0, width: toolView.width - 5 - 46 * 3, height: 55)
-        case 4:
-            collectionView.frame = CGRect(x: 10, y: 0, width: 184, height: 55)
-            searchBar.frame = CGRect(x: 5 + 46 * 4, y: 0, width: toolView.width - 5 - 46 * 4, height: 55)
-        default:
-            collectionView.frame = CGRect(x: 10, y: 0, width: 230, height: 55)
-            searchBar.frame = CGRect(x: 5 + 46 * 5, y: 0, width: toolView.width - 5 - 46 * 5, height: 55)
-        }
-        collectionView.reloadData()
-    }
-    
-    @objc func _clickNavRightButton(_ sender: UIButton) {
-        if selectUsers.count == 0 {
-            return
-        }
-        var userNames: [String] = []
-        for item in selectUsers {
-            userNames.append(item.username)
-        }
-        if isAddMember {
-            MBProgressHUD_JChat.showMessage(message: "添加中...", toView: view)
-            group?.addMembers(withUsernameArray: userNames, completionHandler: { (result, error) in
-                MBProgressHUD_JChat.hide(forView: self.view, animated: true)
-                if error == nil {
-                    NotificationCenter.default.post(name: Notification.Name(rawValue: kUpdateGroupInfo), object: nil)
-                    self.navigationController?.popViewController(animated: true)
-                } else {
-                    MBProgressHUD_JChat.show(text: "添加失败,请重试", view: self.view)
-                }
-            })
-        
-        } else {
-            if currentUser != nil {
-                userNames.insert((currentUser?.username)!, at: 0)
-            }
-            MBProgressHUD_JChat.showMessage(message: "创建中...", toView: view)
-            JMSGGroup.createGroup(withName: nil, desc: nil, memberArray: userNames, completionHandler: { (result, error) in
-                MBProgressHUD_JChat.hide(forView: self.view, animated: true)
-                if error == nil {
-                    for vc in (self.navigationController?.viewControllers)! {
-                        if vc is JCConversationListViewController {
-                            self.navigationController?.popToViewController(vc, animated: true)
-                            let group = result as! JMSGGroup
-                            JMSGConversation.createGroupConversation(withGroupId: group.gid, completionHandler: { (result, error) in
-                                let conv = JMSGConversation.groupConversation(withGroupId: group.gid)
-                                let chatVC = JCChatViewController(conversation: conv!)
-                                vc.navigationController?.pushViewController(chatVC, animated: true)
-                            })
-                        }
-                    }
-                    
-                } else {
-                    MBProgressHUD_JChat.show(text: "创建失败,请重试", view: self.view)
-                }
-            })
-        }
-    }
-    
-    fileprivate func filter(_ searchString: String) {
-        if searchString.isEmpty || searchString == "" {
-            _classify(users)
-            return
-        }
-        let searchString = searchString.uppercased()
-        filteredUsersArray = _JCFilterUsers(users: users, string: searchString)
-        _classify(filteredUsersArray)
-    }
-}
-
-//Mark: -
-extension JCUpdateMemberViewController: UITableViewDelegate, UITableViewDataSource {
-    
-    func numberOfSections(in tableView: UITableView) -> Int {
-        if filteredUsersArray.count > 0 {
-            return keys.count
-        }
-        return 0
-    }
-    
-    public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
-        return data[keys[section]]!.count
-    }
-    
-    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
-        return keys[section]
-    }
-    
-    func sectionIndexTitles(for tableView: UITableView) -> [String]? {
-        return keys
-    }
-    
-    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
-        return 55
-    }
-    
-    
-    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
-        if section == 0 {
-            return 30
-        }
-        return 10
-    }
-    
-    
-    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
-        return tableView.dequeueReusableCell(withIdentifier: "JCSelectMemberCell", for: indexPath)
-    }
-    
-    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
-        guard let cell = cell as? JCSelectMemberCell else {
-            return
-        }
-        let user = data[keys[indexPath.section]]?[indexPath.row]
-        cell.bindDate(user!)
-        if let members = members {
-            if members.contains(where: { (u) -> Bool in
-                return u.username == user?.username && u.appKey == user?.appKey
-            }) {
-                cell.selectIcon = UIImage.loadImage("com_icon_isSelect")
-                return
-            }
-        }
-        if selectUsers.contains(where: { (u) -> Bool in
-            return u.username == user?.username && u.appKey == user?.appKey
-        })  {
-            cell.selectIcon = UIImage.loadImage("com_icon_select")
-        } else {
-            cell.selectIcon = UIImage.loadImage("com_icon_unselect")
-        }
-    }
-    
-    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
-        tableView.deselectRow(at: indexPath, animated: true)
-        guard let cell = tableView.cellForRow(at: indexPath) as? JCSelectMemberCell else {
-            return
-        }
-        let user = data[keys[indexPath.section]]?[indexPath.row]
-        if members != nil {
-            if (members?.contains(where: { (u) -> Bool in
-                return u.username == user?.username && u.appKey == user?.appKey
-            }))! {
-                return
-            }
-        }
-        if selectUsers.contains(where: { (u) -> Bool in
-            return u.username == user?.username && u.appKey == user?.appKey
-        })  {
-            // remove
-            cell.selectIcon = UIImage.loadImage("com_icon_unselect")
-            _removeUser(user!)
-            _reloadCollectionView()
-        } else {
-            selectUsers.append(user!)
-            cell.selectIcon = UIImage.loadImage("com_icon_select")
-            _reloadCollectionView()
-        }
-        if selectUsers.count > 0 {
-            collectionView.scrollToItem(at: IndexPath(row: selectUsers.count - 1, section: 0), at: .right, animated: false)
-        }
-    }
-}
-
-extension JCUpdateMemberViewController: UICollectionViewDelegate, UICollectionViewDataSource {
-    func numberOfSections(in collectionView: UICollectionView) -> Int {
-        return 1
-    }
-    
-    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
-        return selectUsers.count
-    }
-    
-    func collectionView(_ collectionView: UICollectionView,
-                        layout collectionViewLayout: UICollectionViewLayout,
-                        sizeForItemAtIndexPath indexPath: IndexPath) -> CGSize {
-        return CGSize(width: 46, height: 55)
-    }
-    
-    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
-        return collectionView.dequeueReusableCell(withReuseIdentifier: "JCUpdateMemberCell", for: indexPath)
-    }
-    
-    func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
-        guard let cell = cell as? JCUpdateMemberCell else {
-            return
-        }
-        
-        cell.backgroundColor = .white
-        cell.bindDate(user: selectUsers[indexPath.row])
-    }
-    
-    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
-        selectUsers.remove(at: indexPath.row)
-        tableView.reloadData()
-        _reloadCollectionView()
-    }
-}
-
-extension JCUpdateMemberViewController: UISearchBarDelegate {
-    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
-        filter(searchText)
-    }
-    
-    func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
-        // 搜索非好友
-        let searchText = searchBar.text!
-        JMSGUser.userInfoArray(withUsernameArray: [searchText]) { (result, error) in
-            if error == nil {
-                let users = result as! [JMSGUser]
-                self.searchUser = users.first
-                self._classify([self.searchUser!])
-                self.tipsView.isHidden = true
-            } else {
-                // 未查询到该用户的信息
-                self.tipsView.isHidden = false
-            }
-        }
-    }
-}
-
-

+ 0 - 232
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/ScanQRCodeViewController.swift

@@ -1,232 +0,0 @@
-//
-//  ScanQRCodeViewController.swift
-//  JChat
-//
-//  Created by 邓永豪 on 2017/8/16.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-import UIKit
-import AVFoundation
-
-class ScanQRCodeViewController: UIViewController {
-    
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        self.title = "扫一扫"
-        view.backgroundColor = .white
-        
-        let authStatus = AVCaptureDevice.authorizationStatus(for: AVMediaType.video)
-        if(authStatus == .restricted || authStatus == .denied){
-            let alertView = UIAlertView(title: "无法访问相机", message: "请在设备的设置-趣阅中允许访问相机。",delegate: self, cancelButtonTitle: "好的", otherButtonTitles: "去设置")
-            alertView.show()
-            return;
-        }
-        
-        previewLayer.frame = view.frame
-        view.layer.addSublayer(previewLayer)
-        session.startRunning()
-        
-        let borderView = UIImageView(frame: CGRect(x: (view.width - 240) / 2, y: 123, width: 240, height: 240))
-        borderView.image = UIImage.loadImage("com_icon_qrc_border")
-        view.addSubview(borderView)
-        
-        qrcLine = UIImageView(frame: CGRect(x: (view.width - 190) / 2, y: 123, width: 190, height: 6))
-        qrcLine.image = UIImage.loadImage("com_icon_qrc_line")
-        view.addSubview(qrcLine)
-
-        let imageView = UIImageView(frame: view.frame)
-        imageView.image = _getBackgroundImage()
-        view.addSubview(imageView)
-        
-        let tipsLabel = UILabel(frame: CGRect(x: 0, y: 123 + 240 + 17.5, width: view.width, height: 20))
-        tipsLabel.font = UIFont.systemFont(ofSize: 14)
-        tipsLabel.text = "将取景框对准二维码,即可自动扫描"
-        tipsLabel.textAlignment = .center
-        tipsLabel.textColor = UIColor(netHex: 0x6EF8F8)
-        view.addSubview(tipsLabel)
-        
-        NotificationCenter.default.addObserver(self, selector: #selector(startQRCAnimate), name: UIApplication.didBecomeActiveNotification, object: nil)
-    }
-    
-    var qrcLine: UIImageView!
-    var isStopAnimate = false
-    
-    override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
-        navigationController?.navigationBar.shadowImage = UIImage()
-    }
-    
-    override func viewDidAppear(_ animated: Bool) {
-        super.viewDidAppear(animated)
-        session.startRunning()
-        isStopAnimate = false
-        isAnimating = false
-        startQRCAnimate()
-    }
-    
-    override func viewWillDisappear(_ animated: Bool) {
-        super.viewWillDisappear(animated)
-        navigationController?.navigationBar.setBackgroundImage(nil, for: .default)
-        navigationController?.navigationBar.shadowImage = nil
-        navigationController?.navigationBar.barTintColor = UIColor(netHex: 0x2dd0cf)
-        self.qrcLine.layer.removeAllAnimations()
-    }
-    
-    deinit {
-        NotificationCenter.default.removeObserver(self)
-    }
-    
-    fileprivate lazy var session: AVCaptureSession = {
-        var session = AVCaptureSession()
-        var device = AVCaptureDevice.default(for:AVMediaType.video)
-        var input: AVCaptureDeviceInput?
-        do {
-            input = try AVCaptureDeviceInput(device: device!)
-        } catch {
-            print(error)
-        }
-        if input != nil {
-            session.addInput(input!)
-        }
-        var output = AVCaptureMetadataOutput()
-        session.addOutput(output)
-        output.metadataObjectTypes = [AVMetadataObject.ObjectType.qr]
-        output.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
-        
-        return session
-    }()
-    fileprivate lazy var previewLayer: AVCaptureVideoPreviewLayer = {
-        var previewLayer = AVCaptureVideoPreviewLayer(session: self.session)
-        return previewLayer
-    }()
-    
-    private func _getBackgroundImage() -> UIImage? {
-        UIGraphicsBeginImageContext(view.frame.size)
-        guard let ctx = UIGraphicsGetCurrentContext() else {
-            return nil
-        }
-        ctx.setFillColor(red: 0, green: 0, blue: 0, alpha: 0.5)
-        let screenSize = UIScreen.main.bounds.size
-        var drawRect = CGRect(x: 0, y: 0, width: screenSize.width, height: screenSize.height)
-        ctx.fill(drawRect)
-        drawRect = CGRect(x: (view.width - 240) / 2, y: 123, width: 240, height: 240)
-        ctx.clear(drawRect)
-        let image = UIGraphicsGetImageFromCurrentImageContext()
-        UIGraphicsEndImageContext()
-        return image
-    }
-    
-    var isAnimating = false
-    
-    @objc func startQRCAnimate() {
-        if isStopAnimate || isAnimating {
-            return
-        }
-        isAnimating = true
-        qrcLine.frame = CGRect(x: (self.view.width - 190) / 2, y: 123, width: 190, height: 6)
-        UIView.animate(withDuration: 2.5, animations: {
-            self.qrcLine.frame = CGRect(x: (self.view.width - 190) / 2, y: 123 + 240 - 5, width: 190, height: 6)
-        }) { (finish) in
-            self.isAnimating = false
-            self.qrcLine.frame = CGRect(x: (self.view.width - 190) / 2, y: 123, width: 190, height: 6)
-            if finish {
-                self.startQRCAnimate()
-            }
-        }
-    }
-}
-
-// MARK: - AVCaptureMetadataOutputObjectsDelegate
-extension ScanQRCodeViewController: AVCaptureMetadataOutputObjectsDelegate {
-    func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {
-        for metadataObject in metadataObjects {
-            guard let object = metadataObject as? AVMetadataMachineReadableCodeObject else {
-                return
-            }
-            
-            let barCodeObject = previewLayer.transformedMetadataObject(for: object)
-            let frame = barCodeObject!.bounds
-            
-            let validFrame = CGRect(x: (view.width - 240) / 2, y: 123, width: 240, height: 240)
-            if frame.origin.x < validFrame.origin.x || frame.origin.x + frame.size.width > validFrame.origin.x + validFrame.size.width {
-                return
-            }
-            
-            if frame.size.width > validFrame.size.width {
-                return
-            }
-            
-            if frame.origin.y < validFrame.origin.y || frame.origin.y + frame.size.height > validFrame.origin.y + validFrame.size.height {
-                return
-            }
-            
-            if frame.size.height > validFrame.size.height {
-                return
-            }
-            
-            if object.type == AVMetadataObject.ObjectType.qr {
-                guard let url = object.stringValue else {
-                    return
-                }
-                if let Url = URL(string: url) {
-                    if UIApplication.shared.canOpenURL(Url) {
-                        UIApplication.shared.openURL(Url)
-                    } else {
-                        let newUrl = URL(string: "https://" + url)
-                        UIApplication.shared.openURL(newUrl!)
-                    }
-                    return
-                }
-                let jsonData:Data = url.data(using: .utf8)!
-
-                let dict = try? JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers)
-                guard let info = dict as? NSDictionary else {
-                    return
-                }
-                guard let userInfo = info["user"] as? NSDictionary else {
-                    return
-                }
-                let username = userInfo["username"] as! String
-                let appkey = userInfo["appkey"] as! String
-                session.stopRunning()
-                JMSGUser.userInfoArray(withUsernameArray: [username], appKey: appkey, completionHandler: { (result, error) in
-                    if error == nil {
-                        let users = result as! [JMSGUser]
-                        let user = users.first
-                        let vc = JCUserInfoViewController()
-                        vc.user = user
-                        self.navigationController?.pushViewController(vc, animated: true)
-                    }
-                })
-            }
-        }
-    }
-    
-
-    func convertStringToDictionary(text: String) -> [String : AnyObject]? {
-        if let data = text.data(using: .utf8) {
-            do {
-                return try JSONSerialization.jsonObject(with: data, options: [JSONSerialization.ReadingOptions.init(rawValue: 0)]) as? [String:AnyObject]
-            } catch let error as NSError {
-                print(error)
-            }
-        }
-        return nil
-    }
-}
-
-extension ScanQRCodeViewController: UIAlertViewDelegate {
-    func alertView(_ alertView: UIAlertView, clickedButtonAt buttonIndex: Int) {
-        if buttonIndex == 1 {
-            JCAppManager.openAppSetter()
-        }
-    }
-}
-
-
-
-

+ 0 - 146
o2ios/O2Platform/Framework/JMessage/ChatModule/Chat/ViewController/UnreadListViewController.swift

@@ -1,146 +0,0 @@
-//
-//  UnreadListViewController.swift
-//  JChat
-//
-//  Created by 邓永豪 on 2017/9/14.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-class UnreadListViewController: UIViewController, CustomNavigation {
-
-    var message: JMSGMessage!
-
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        _init()
-    }
-
-    fileprivate var unreadList = UnreadListTableView()
-    fileprivate var readList = UnreadListTableView()
-
-    private lazy var tabedSlideView: DLTabedSlideView = {
-        var tabedSlideView = DLTabedSlideView(frame: CGRect(x: 0, y: 64, width: self.view.width, height: self.view.height - 64))
-        tabedSlideView.delegate = self
-        tabedSlideView.baseViewController = self
-        tabedSlideView.tabItemNormalColor = .black
-        tabedSlideView.tabItemSelectedColor =  UIColor(netHex: 0x2DD0CF)
-        tabedSlideView.tabbarTrackColor = UIColor(netHex: 0x2DD0CF)
-        tabedSlideView.tabbarBackgroundImage = UIImage.createImage(color: .white, size: CGSize(width: self.view.width, height: 39))
-        tabedSlideView.tabbarBottomSpacing = 0.0
-        return tabedSlideView
-    }()
-
-    private func _init() {
-        self.title = "消息查看列表"
-        view.backgroundColor = .white
-
-        customLeftBarButton(delegate: self)
-
-        MBProgressHUD_JChat.showMessage(message: "获取中...", toView: view)
-        message.messageReadDetailHandler { (readUsers, unreadUsers, error) in
-            MBProgressHUD_JChat.hide(forView: self.view, animated: true)
-            if error == nil {
-                DispatchQueue.main.async {
-                    self.unreadList.users = unreadUsers as! [JMSGUser]
-                    self.readList.users = readUsers as! [JMSGUser]
-                    self.view.addSubview(self.tabedSlideView)
-                    var unreadTitle = "未读"
-                    if let count = unreadUsers?.count {
-                        unreadTitle = "未读(\(count))"
-                    }
-                    let unreadItem = DLTabedbarItem(title: unreadTitle, image: nil, selectedImage: nil)
-                    var readTitle =  "已读"
-                    if let count = readUsers?.count {
-                        readTitle = "已读(\(count))"
-                    }
-
-                    let readItem = DLTabedbarItem(title: readTitle, image: nil, selectedImage: nil)
-                    self.tabedSlideView.tabbarItems = [unreadItem!, readItem!]
-                    self.tabedSlideView.buildTabbar()
-                    self.tabedSlideView.selectedIndex = 0
-                }
-
-            } else {
-                MBProgressHUD_JChat.show(text: "获取失败", view: self.view)
-            }
-        }
-
-
-    }
-}
-
-extension UnreadListViewController: DLTabedSlideViewDelegate {
-    func numberOfTabs(in sender: DLTabedSlideView!) -> Int {
-        return 2
-    }
-
-    func dlTabedSlideView(_ sender: DLTabedSlideView!, controllerAt index: Int) -> UIViewController! {
-        switch index {
-        case 0:
-            return unreadList
-        default:
-             return readList
-        }
-    }
-}
-
-
-class UnreadListTableView: UITableViewController {
-
-    var users: [JMSGUser] = []
-
-    override func viewDidLoad() {
-        super.viewDidLoad()
-        _init()
-    }
-
-    private func _init() {
-        view.backgroundColor = .white
-        tableView.separatorStyle = .none
-        tableView.showsVerticalScrollIndicator = false
-        tableView.register(JCContacterCell.self, forCellReuseIdentifier: "JCContacterCell")
-        let line = UILabel(frame: CGRect(x: 0, y: 0, width: view.width, height: 0.5))
-        line.layer.backgroundColor = UIColor(netHex: 0xD9D9D9).cgColor
-        view.addSubview(line)
-    }
-
-    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
-        return users.count
-    }
-
-    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
-        return 55
-    }
-
-    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
-        return tableView.dequeueReusableCell(withIdentifier: "JCContacterCell", for: indexPath)
-    }
-
-    override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
-        guard let cell = cell as? JCContacterCell else {
-            return
-        }
-
-        let user = users[indexPath.row]
-        cell.isShowBadge = false
-        cell.bindDate(user)
-    }
-
-    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
-        tableView.deselectRow(at: indexPath, animated: true)
-        let vc = JCUserInfoViewController()
-        let user = users[indexPath.row]
-        vc.user = user
-        navigationController?.pushViewController(vc, animated: true)
-    }
-
-}
-
-extension UnreadListViewController: UIGestureRecognizerDelegate {
-    public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
-        return true
-    }
-}
-

+ 0 - 90
o2ios/O2Platform/Framework/JMessage/ChatModule/Input/InputView/Emoticon/JCEmoticon.swift

@@ -1,90 +0,0 @@
-//
-//  JCEmoticon.swift
-//  JChat
-//
-//  Created by deng on 2017/3/8.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-internal protocol JCEmoticonDelegate: class {
-    func emoticon(shouldSelectFor emoticon: JCEmoticon) -> Bool
-    func emoticon(didSelectFor emoticon: JCEmoticon)
-    
-    func emoticon(shouldPreviewFor emoticon: JCEmoticon?) -> Bool
-    func emoticon(didPreviewFor emoticon: JCEmoticon?)
-}
-
-open class JCEmoticon: NSObject {
-    
-    open var isBackspace: Bool {
-        return self === JCEmoticon.backspace
-    }
-    
-    public static let backspace: JCEmoticon = {
-        let em = JCEmoticon()
-        em.contents = "⌫"
-        return em
-    }()
-    
-    open func draw(in rect: CGRect, in ctx: CGContext) {
-        
-        switch contents {
-        case let image as UIImage:
-            var nrect = rect
-            nrect.size = image.size
-            nrect.origin.x = rect.minX + (rect.width - nrect.width) / 2
-            nrect.origin.y = rect.minY + (rect.height - nrect.height) / 2
-            image.draw(in: nrect)
-            
-        case let str as NSString:
-            let cfg = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 32)]
-            let size = str.size(withAttributes: cfg)
-            let nrect = CGRect(x: rect.minX + (rect.width - size.width + 3) / 2,
-                               y: rect.minY + (rect.height - size.height) / 2,
-                               width: size.width,
-                               height: size.height)
-            str.draw(in: nrect, withAttributes: cfg)
-            
-        case let str as NSAttributedString:
-            str.draw(in: rect)
-            
-        default:
-            break
-        }
-    }
-    
-    open func show(in view: UIView) {
-        let imageView = view.subviews.first as? UIImageView ?? {
-            let imageView = UIImageView()
-            view.subviews.forEach{
-                $0.removeFromSuperview()
-            }
-            view.addSubview(imageView)
-            return imageView
-            }()
-        
-        if let image = contents as? UIImage {
-            imageView.subviews.forEach{
-                $0.removeFromSuperview()
-            }
-            imageView.bounds = CGRect(origin: .zero, size: image.size)
-            imageView.center = CGPoint(x: view.frame.width / 2, y: view.frame.height / 2)
-            imageView.image = contents as? UIImage
-        }
-        if let emjoji = contents as? String {
-            imageView.subviews.forEach{
-                $0.removeFromSuperview()
-            }
-            let label = UILabel(frame: view.frame)
-            label.textAlignment = .center
-            label.text = emjoji
-            label.font = UIFont.systemFont(ofSize: view.frame.width / 3 * 2)
-            imageView.addSubview(label)
-        }
-    }
-    
-    // 目前只支持UIImage/NSString/NSAttributedString
-    open var contents: Any?
-}

Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 125
o2ios/O2Platform/Framework/JMessage/ChatModule/Input/InputView/Emoticon/JCEmoticonBackgroundView.swift


+ 0 - 33
o2ios/O2Platform/Framework/JMessage/ChatModule/Input/InputView/Emoticon/JCEmoticonGroup.swift

@@ -1,33 +0,0 @@
-//
-//  JCEmoticonGroup.swift
-//  JChat
-//
-//  Created by deng on 2017/3/9.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-public enum JCEmoticonType: Int {
-    case small = 0
-    case large = 1
-    
-    public var isSmall: Bool {
-        return self == .small
-    }
-    
-    public var isLarge: Bool {
-        return self == .large
-    }
-}
-
-open class JCEmoticonGroup: NSObject {
-    
-    open lazy var id: String = UUID().uuidString
-    
-    open var title: String?
-    open var thumbnail: UIImage?
-    open var type: JCEmoticonType = .small
-    open var emoticons: [JCEmoticon] = []
-
-}

+ 0 - 369
o2ios/O2Platform/Framework/JMessage/ChatModule/Input/InputView/Emoticon/JCEmoticonInputView.swift

@@ -1,369 +0,0 @@
-//
-//  JCEmoticonInputView.swift
-//  JChat
-//
-//  Created by deng on 2017/3/9.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-@objc public protocol JCEmoticonInputViewDataSource: NSObjectProtocol {
-    
-    func numberOfEmotionGroups(in emoticon: JCEmoticonInputView) -> Int
-    func emoticon(_ emoticon: JCEmoticonInputView, emotionGroupForItemAt index: Int) -> JCEmoticonGroup
-    
-    @objc optional func emoticon(_ emoticon: JCEmoticonInputView, numberOfRowsForGroupAt index: Int) -> Int
-    @objc optional func emoticon(_ emoticon: JCEmoticonInputView, numberOfColumnsForGroupAt index: Int) -> Int
-    
-    @objc optional func emoticon(_ emoticon: JCEmoticonInputView, moreViewForGroupAt index: Int) -> UIView?
-}
-
-@objc public protocol JCEmoticonInputViewDelegate: NSObjectProtocol {
-    
-    @objc optional func inputViewContentSize(_ inputView: UIView) -> CGSize
-    
-    @objc optional func emoticon(_ emoticon: JCEmoticonInputView, insetForGroupAt index: Int) -> UIEdgeInsets
-    
-    @objc optional func emoticon(_ emoticon: JCEmoticonInputView, shouldSelectFor item: JCEmoticon) -> Bool
-    @objc optional func emoticon(_ emoticon: JCEmoticonInputView, didSelectFor item: JCEmoticon)
-    
-    @objc optional func emoticon(_ emoticon: JCEmoticonInputView, shouldPreviewFor item: JCEmoticon?) -> Bool
-    @objc optional func emoticon(_ emoticon: JCEmoticonInputView, didPreviewFor item: JCEmoticon?)
-    
-}
-
-open class JCEmoticonInputView: UIView {
-
-    private var _cacheBounds: CGRect?
-    
-    fileprivate var _color: UIColor?
-    fileprivate var _currentGroup: Int?
-    fileprivate var _contentViewIsInit: Bool = false
-    
-    fileprivate var _currentMoreView: UIView?
-    fileprivate var _currentMoreViewConstraints: [NSLayoutConstraint]?
-    
-    fileprivate lazy var _tabbarLayout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
-    fileprivate lazy var _tabbar: UICollectionView = UICollectionView(frame: .zero, collectionViewLayout: self._tabbarLayout)
-    
-    fileprivate lazy var _previewer: JCEmoticonPreviewer = JCEmoticonPreviewer()
-    fileprivate lazy var _pageControl: UIPageControl = UIPageControl()
-    
-    fileprivate lazy var _contentViewLayout: JCEmoticonInputViewLayout = JCEmoticonInputViewLayout()
-    fileprivate lazy var _contentView: UICollectionView = UICollectionView(frame: .zero, collectionViewLayout: self._contentViewLayout)
-    
-    public override init(frame: CGRect) {
-        super.init(frame: frame)
-        _init()
-    }
-    public required init?(coder aDecoder: NSCoder) {
-        super.init(coder: aDecoder)
-        _init()
-    }
-    
-    open override func layoutSubviews() {
-        super.layoutSubviews()
-        
-        if _cacheBounds?.width != bounds.width {
-            _cacheBounds = bounds
-            if let idx = _contentView.indexPathsForVisibleItems.first {
-                _contentView.reloadData()
-                _restoreContentOffset(at: idx)
-            }
-        }
-    }
-    open override var intrinsicContentSize: CGSize {
-        return delegate?.inputViewContentSize?(self) ?? CGSize(width: frame.width, height: 253)
-    }
-    
-    open weak var dataSource: JCEmoticonInputViewDataSource?
-    open weak var delegate: JCEmoticonInputViewDelegate?
-    
-    // MARK: Private Method
-    private func _restoreContentOffset(at indexPath: IndexPath) {
-        
-        let section = indexPath.section
-        let count = _contentView.numberOfItems(inSection: section)
-        let item = min(indexPath.item, count - 1)
-        
-        let nidx = IndexPath(item: item, section: section)
-        let mcount = (0 ..< section).reduce(0) {
-            return $0 + _contentView.numberOfItems(inSection: $1)
-        }
-        let x = CGFloat(mcount + item) * _contentView.frame.width
-        
-        _contentView.contentOffset = CGPoint(x: x, y: 0)
-        _updatePageNumber(at: nidx)
-    }
-    
-    private func _init() {
-        
-        //_color = UIColor(colorLiteralRed: 0xec / 0xff, green: 0xed / 0xff, blue: 0xf1 / 0xff, alpha: 1)
-        _color = UIColor.init(red: 0xec / 0xff, green: 0xed / 0xff, blue: 0xf1 / 0xff, alpha: 1)
-        
-        _pageControl.numberOfPages = 8
-        _pageControl.hidesForSinglePage = true
-        _pageControl.pageIndicatorTintColor = UIColor.gray
-        _pageControl.currentPageIndicatorTintColor = UIColor.darkGray
-        _pageControl.translatesAutoresizingMaskIntoConstraints = false
-        _pageControl.backgroundColor = .clear
-        _pageControl.isUserInteractionEnabled = false
-        
-        _contentView.delegate = self
-        _contentView.dataSource = self
-        _contentView.scrollsToTop = false
-        _contentView.isPagingEnabled = true
-        _contentView.delaysContentTouches = true
-        _contentView.showsVerticalScrollIndicator = false
-        _contentView.showsHorizontalScrollIndicator = false
-        _contentView.register(JCEmoticonPageView.self, forCellWithReuseIdentifier: "Page")
-        _contentView.translatesAutoresizingMaskIntoConstraints = false
-        _contentView.backgroundColor = .clear
-        
-        _previewer.isHidden = true
-        _previewer.isUserInteractionEnabled = false
-        
-        _tabbarLayout.scrollDirection = .horizontal
-        _tabbarLayout.minimumLineSpacing = 0
-        _tabbarLayout.minimumInteritemSpacing = 0
-        
-        _tabbar.register(JCEmoticonTabItemView.self, forCellWithReuseIdentifier: "Page")
-        _tabbar.translatesAutoresizingMaskIntoConstraints = false
-        _tabbar.dataSource = self
-        _tabbar.backgroundColor = .white
-        _tabbar.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
-        _tabbar.delegate = self
-        _tabbar.scrollsToTop = false
-        _tabbar.showsVerticalScrollIndicator = false
-        _tabbar.showsHorizontalScrollIndicator = false
-        
-        backgroundColor = _color
-        
-        // add views
-        addSubview(_contentView)
-        addSubview(_tabbar)
-        addSubview(_pageControl)
-        addSubview(_previewer)
-        
-        // add constraints
-        addConstraint(_JCEmoticonLayoutConstraintMake(_contentView, .top, .equal, self, .top))
-        addConstraint(_JCEmoticonLayoutConstraintMake(_contentView, .left, .equal, self, .left))
-        addConstraint(_JCEmoticonLayoutConstraintMake(_contentView, .right, .equal, self, .right))
-        
-        addConstraint(_JCEmoticonLayoutConstraintMake(_pageControl, .left, .equal, self, .left))
-        addConstraint(_JCEmoticonLayoutConstraintMake(_pageControl, .right, .equal, self, .right))
-        addConstraint(_JCEmoticonLayoutConstraintMake(_pageControl, .bottom, .equal, _contentView, .bottom, -4))
-        
-        addConstraint(_JCEmoticonLayoutConstraintMake(_tabbar, .top, .equal, _contentView, .bottom))
-        addConstraint(_JCEmoticonLayoutConstraintMake(_tabbar, .left, .equal, self, .left))
-        addConstraint(_JCEmoticonLayoutConstraintMake(_tabbar, .right, .equal, self, .right))
-        addConstraint(_JCEmoticonLayoutConstraintMake(_tabbar, .bottom, .equal, self, .bottom))
-        
-        addConstraint(_JCEmoticonLayoutConstraintMake(_tabbar, .height, .equal, nil, .notAnAttribute, 37))
-        addConstraint(_JCEmoticonLayoutConstraintMake(_pageControl, .height, .equal, nil, .notAnAttribute, 20))
-    }
-
-}
-
-// MARK: - JCEmoticonDelegate(Forwarding)
-extension JCEmoticonInputView: JCEmoticonDelegate {
-    
-    open func emoticon(shouldSelectFor emoticon: JCEmoticon) -> Bool {
-        return delegate?.emoticon?(self, shouldSelectFor: emoticon) ?? true
-    }
-    open func emoticon(shouldPreviewFor emoticon: JCEmoticon?) -> Bool {
-        return delegate?.emoticon?(self, shouldPreviewFor: emoticon) ?? false
-    }
-    
-    open func emoticon(didSelectFor emoticon: JCEmoticon) {
-        delegate?.emoticon?(self, didSelectFor: emoticon)
-    }
-    open func emoticon(didPreviewFor emoticon: JCEmoticon?) {
-        delegate?.emoticon?(self, didPreviewFor: emoticon)
-    }
-}
-
-// MARK: - UICollectionViewDataSource & UICollectionViewDelegateFlowLayout & JCEmoticonInputViewDelegateLayout
-extension JCEmoticonInputView: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, JCEmoticonInputViewDelegateLayout {
-    
-    public func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
-        if scrollView === _tabbar {
-            return
-        }
-        if scrollView === _contentView {
-            guard let idx = _contentView.indexPathForItem(at: targetContentOffset.move()) else {
-                return
-            }
-            _updateMoreView(at: idx)
-            _updatePageNumber(at: idx)
-        }
-    }
-    
-    public func numberOfSections(in collectionView: UICollectionView) -> Int {
-        if collectionView === _tabbar {
-            return 1
-        }
-        if collectionView === _contentView {
-            return dataSource?.numberOfEmotionGroups(in: self) ?? 0
-        }
-        return 0
-    }
-    public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
-        if collectionView === _tabbar {
-            return dataSource?.numberOfEmotionGroups(in: self) ?? 0
-        }
-        if collectionView === _contentView {
-            let pageCount = _contentViewLayout.numberOfPages(in: section)
-            if !_contentViewIsInit {
-                _contentViewIsInit = true
-                let idx = IndexPath(item: 0, section: 0)
-                _updateMoreView(at: idx)
-                _updatePageNumber(at: idx)
-            }
-            return pageCount
-        }
-        return 0
-    }
-    
-    public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
-        return collectionView.dequeueReusableCell(withReuseIdentifier: "Page", for: indexPath)
-    }
-    public func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
-        if let cell = cell as? JCEmoticonPageView {
-            cell.page = _contentViewLayout.page(at: indexPath)
-            cell.delegate = self
-            cell.previewer = _previewer
-            return
-        }
-        if let cell = cell as? JCEmoticonTabItemView {
-            cell.group = dataSource?.emoticon(self, emotionGroupForItemAt: indexPath.item)
-            cell.selectedBackgroundView?.backgroundColor = _color
-            return
-        }
-    }
-    
-    public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
-        if collectionView === _tabbar {
-            let nidx = IndexPath(item: 0, section: indexPath.item)
-            guard _contentView.indexPathsForVisibleItems.first?.section != nidx.section else {
-                return // no change
-            }
-            _contentView.scrollToItem(at: nidx, at: .left, animated: false)
-            _updateMoreView(at: nidx)
-            _updatePageNumber(at: nidx)
-        }
-    }
-    
-    public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
-        if collectionView === _tabbar {
-            return CGSize(width: 45, height: collectionView.frame.height)
-        }
-        if collectionView === _contentView {
-            return collectionView.frame.size
-        }
-        return .zero
-    }
-    internal func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: JCEmoticonInputViewLayout, groupAt index: Int) -> JCEmoticonGroup? {
-        return dataSource?.emoticon(self, emotionGroupForItemAt: index)
-    }
-    internal func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: JCEmoticonInputViewLayout, numberOfRowsForGroupAt index: Int) -> Int {
-        return dataSource?.emoticon?(self, numberOfRowsForGroupAt: index) ?? 3
-    }
-    internal func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: JCEmoticonInputViewLayout, numberOfColumnsForGroupAt index: Int) -> Int {
-        return dataSource?.emoticon?(self, numberOfColumnsForGroupAt: index) ?? 7
-    }
-    internal func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: JCEmoticonInputViewLayout, insetForGroupAt index: Int) -> UIEdgeInsets {
-        return delegate?.emoticon?(self, insetForGroupAt: index) ?? UIEdgeInsets(top: 12, left: 10, bottom: 12 + 30, right: 10)
-    }
-    
-    fileprivate func _updateMoreView(at indexPath: IndexPath) {
-        guard _currentGroup != indexPath.section else {
-            return
-        }
-        let moreView = dataSource?.emoticon?(self, moreViewForGroupAt: indexPath.section)
-        
-        if _currentMoreView != moreView {
-            
-            var newValue: UIView?
-            var newValueCs: [NSLayoutConstraint]?
-            
-            let oldValue = _currentMoreView
-            let oldValueCs = _currentMoreViewConstraints
-            
-            if let view = moreView {
-                
-                view.translatesAutoresizingMaskIntoConstraints = false
-                
-                insertSubview(view, belowSubview: _previewer)
-                
-                let constraints = [
-                    _JCEmoticonLayoutConstraintMake(view, .top, .equal, _tabbar, .top),
-                    _JCEmoticonLayoutConstraintMake(view, .right, .equal, _tabbar, .right),
-                    _JCEmoticonLayoutConstraintMake(view, .bottom, .equal, _tabbar, .bottom),
-                    ]
-                
-                addConstraints(constraints)
-                
-                newValue = view
-                newValueCs = constraints
-            }
-            
-            newValue?.layoutIfNeeded()
-            newValue?.transform = CGAffineTransform(translationX: newValue?.frame.width ?? 0, y: 0)
-            
-            UIView.animate(withDuration: 0.25, animations: {
-                
-                self._tabbar.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: newValue?.frame.width ?? 0)
-                
-                newValue?.transform = CGAffineTransform(translationX: 0, y: 0)
-                oldValue?.transform = CGAffineTransform(translationX: oldValue?.frame.width ?? 0, y: 0)
-                
-                }, completion: { f in
-                    if let view = oldValue, let cs = oldValueCs {
-                        guard view !== self._currentMoreView else {
-                            self.removeConstraints(cs)
-                            return
-                        }
-                        self.removeConstraints(cs)
-                        view.removeFromSuperview()
-                    }
-            })
-            
-            _currentMoreView = newValue
-            _currentMoreViewConstraints = newValueCs
-        }
-        _currentGroup = indexPath.section
-    }
-    
-    fileprivate func _updatePageNumber(at indexPath: IndexPath) {
-        
-        _pageControl.numberOfPages = _contentView.numberOfItems(inSection: indexPath.section)
-        _pageControl.currentPage = indexPath.item
-        
-        let nidx = IndexPath(item: indexPath.section, section: 0)
-        guard _tabbar.indexPathsForSelectedItems?.first?.item != nidx.item else {
-            return
-        }
-        _tabbar.selectItem(at: nidx, animated: true, scrollPosition: .centeredHorizontally)
-    }
-}
-
-internal func _SAEmoticonLoadImage(base64Encoded base64String: String, scale: CGFloat) -> UIImage? {
-    guard let data = Data(base64Encoded: base64String, options: .ignoreUnknownCharacters) else {
-        return nil
-    }
-    return UIImage(data: data, scale: scale)
-}
-
-@inline(__always)
-internal func _JCEmoticonLayoutConstraintMake(_ item: AnyObject, _ attr1: NSLayoutConstraint.Attribute, _ related: NSLayoutConstraint.Relation, _ toItem: AnyObject? = nil, _ attr2: NSLayoutConstraint.Attribute = .notAnAttribute, _ constant: CGFloat = 0, priority: UILayoutPriority = UILayoutPriority.init(1000), multiplier: CGFloat = 1, output: UnsafeMutablePointer<NSLayoutConstraint?>? = nil) -> NSLayoutConstraint {
-    
-    let c = NSLayoutConstraint(item:item, attribute:attr1, relatedBy:related, toItem:toItem, attribute:attr2, multiplier:multiplier, constant:constant)
-    c.priority = priority
-    if output != nil {
-        output?.pointee = c
-    }
-    
-    return c
-}

+ 0 - 176
o2ios/O2Platform/Framework/JMessage/ChatModule/Input/InputView/Emoticon/JCEmoticonInputViewLayout.swift

@@ -1,176 +0,0 @@
-//
-//  JCEmoticonInputViewLayout.swift
-//  JChat
-//
-//  Created by deng on 2017/3/9.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-@objc internal protocol JCEmoticonInputViewDelegateLayout: UICollectionViewDelegate {
-    
-    @objc optional func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: JCEmoticonInputViewLayout, groupAt index: Int) -> JCEmoticonGroup?
-    @objc optional func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: JCEmoticonInputViewLayout, insetForGroupAt index: Int) -> UIEdgeInsets
-    @objc optional func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: JCEmoticonInputViewLayout, numberOfRowsForGroupAt index: Int) -> Int
-    @objc optional func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: JCEmoticonInputViewLayout, numberOfColumnsForGroupAt index: Int) -> Int
-}
-
-internal class JCEmoticonInputViewLayout: UICollectionViewLayout {
-    override var collectionViewContentSize: CGSize {
-        if let size = _cacheContentSize {
-            return size
-        }
-        guard let collectionView = collectionView else {
-            return .zero
-        }
-        let width = collectionView.frame.width
-        let count = (0 ..< collectionView.numberOfSections).reduce(0) {
-            return $0 + numberOfPages(in: $1)
-        }
-        let size = CGSize(width: CGFloat(count) * width, height: 0)
-        _cacheContentSize = size
-        return size
-    }
-    override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
-        if collectionView?.frame.width != newBounds.width {
-            return true
-        }
-        return false
-    }
-    
-    override func prepare() {
-        super.prepare()
-        _cacheContentSize = nil
-        _cacheLayoutAttributes = nil
-    }
-    override func invalidateLayout() {
-        super.invalidateLayout()
-        
-        _cacheContentSize = nil
-        _cacheLayoutAttributes = nil
-    }
-    
-    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
-        guard let collectionView = collectionView else {
-            return nil
-        }
-        if let attributes = _cacheLayoutAttributes {
-            return attributes
-        }
-        var allAttributes = [UICollectionViewLayoutAttributes]()
-        
-        var x = CGFloat(0)
-        let width = collectionView.frame.width
-        let height = collectionView.frame.height
-        
-        (0 ..< collectionView.numberOfSections).forEach { section in
-            (0 ..< collectionView.numberOfItems(inSection: section)).forEach { item in
-                let idx = IndexPath(item: item, section: section)
-                let attributes = layoutAttributesForItem(at: idx) ?? UICollectionViewLayoutAttributes(forCellWith: idx)
-                
-                attributes.frame = CGRect(x: x, y: 0, width: width, height: height)
-                x += width
-                
-                allAttributes.append(attributes)
-            }
-        }
-        _cacheLayoutAttributes = allAttributes
-        return allAttributes
-    }
-    
-    func page(at indexPath: IndexPath) -> JCEmoticonPage {
-        return _pages(at: indexPath.section, with: Int(collectionView?.frame.width ?? 0))[indexPath.item]
-    }
-    func pages(in section: Int) -> [JCEmoticonPage] {
-        return _pages(at: section, with: Int(collectionView?.frame.width ?? 0))
-    }
-    
-    func numberOfPages(in section: Int) -> Int {
-        return _numberOfPages(in: section, with: Int(collectionView?.frame.width ?? 0))
-    }
-    
-    func numberOfRows(in section: Int) -> Int {
-        guard let collectionView = collectionView else {
-            return 3
-        }
-        guard let delegate = collectionView.delegate as? JCEmoticonInputViewDelegateLayout else {
-            return 3
-        }
-        return delegate.collectionView?(collectionView, layout: self, numberOfRowsForGroupAt: section) ?? 3
-    }
-    func numberOfColumns(in section: Int) -> Int {
-        guard let collectionView = collectionView else {
-            return 7
-        }
-        guard let delegate = collectionView.delegate as? JCEmoticonInputViewDelegateLayout else {
-            return 7
-        }
-        return delegate.collectionView?(collectionView, layout: self, numberOfColumnsForGroupAt: section) ?? 7
-    }
-    func contentInset(in section: Int) -> UIEdgeInsets {
-        guard let collectionView = collectionView else {
-            return .zero
-        }
-        guard let delegate = collectionView.delegate as? JCEmoticonInputViewDelegateLayout else {
-            return .zero
-        }
-        return delegate.collectionView?(collectionView, layout: self, insetForGroupAt: section) ?? .zero
-    }
-    
-    private func _group(at index: Int) -> JCEmoticonGroup? {
-        guard let collectionView = collectionView else {
-            return nil
-        }
-        guard let delegate = collectionView.delegate as? JCEmoticonInputViewDelegateLayout else {
-            return nil
-        }
-        return delegate.collectionView?(collectionView, layout: self, groupAt: index)
-    }
-    private func _pagesWithoutCache(at index: Int, with width: Int) -> [JCEmoticonPage]  {
-        guard let group = _group(at: index) else {
-            return []
-        }
-        
-        let inset = contentInset(in: index)
-        let rows = CGFloat(numberOfRows(in: index))
-        let columns = CGFloat(numberOfColumns(in: index))
-        
-        let bounds = CGRect(origin: .zero, size: collectionView?.frame.size ?? .zero)
-        let rect = bounds.inset(by: inset)
-        
-        let type = group.type
-        let size = CGSize(width: min(trunc((rect.width - 8 * columns) / columns), 80),
-                          height: min(trunc((rect.height - 8 * rows) / rows), 80))
-        
-        let nlsp = (rect.height / rows) - size.height
-        let nisp = (rect.width / columns) - size.width
-        
-        return group.emoticons.reduce([]) {
-            if let page = $0.last, page.addEmoticon($1) {
-                return $0
-            }
-            return $0 + [JCEmoticonPage($1, size, rect, bounds, nlsp, nisp, type)]
-        }
-    }
-    private func _pages(at index: Int, with width: Int) -> [JCEmoticonPage]  {
-        if let pages = _allPages[width]?[index] {
-            return pages
-        }
-        let pages = _pagesWithoutCache(at: index, with: width)
-        if _allPages[width] == nil {
-            _allPages[width] = [:]
-        }
-        _allPages[width]?[index] = pages
-        return pages
-    }
-    private func _numberOfPages(in index: Int, with width: Int) -> Int {
-        return _allPages[width]?[index]?.count ?? _pages(at: index, with: width).count
-    }
-    
-    private var _cacheContentSize: CGSize?
-    private var _cacheLayoutAttributes: [UICollectionViewLayoutAttributes]?
-    
-    // width + section + pages
-    private lazy var _allPages: [Int: [Int: [JCEmoticonPage]]] = [:]
-}

+ 0 - 94
o2ios/O2Platform/Framework/JMessage/ChatModule/Input/InputView/Emoticon/JCEmoticonLine.swift

@@ -1,94 +0,0 @@
-//
-//  JCEmoticonLine.swift
-//  JChat
-//
-//  Created by deng on 2017/3/9.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-internal class JCEmoticonLine {
-    
-    func draw(in ctx: CGContext) {
-        _ = emoticons.reduce(CGRect(origin: vaildRect.origin, size: itemSize)) {
-            $1.draw(in: $0, in: ctx)
-            return $0.offsetBy(dx: $0.width + minimumInteritemSpacing, dy: 0)
-        }
-    }
-    func rect(at index: Int) -> CGRect? {
-        guard index < emoticons.count else {
-            return nil
-        }
-        let isp = minimumInteritemSpacing
-        let nwidth = (itemSize.width + isp) * CGFloat(index)
-        return CGRect(origin: CGPoint(x: vaildRect.minX + nwidth, y: vaildRect.minY), size: itemSize)
-    }
-    
-    func addEmoticon(_ emoticon: JCEmoticon) -> Bool {
-        let isp = minimumInteritemSpacing
-        let nwidth = visableSize.width + isp + itemSize.width
-        let nwidthWithDelete = visableSize.width + (isp + itemSize.width) * 2
-        let nheight = max(visableSize.height, itemSize.height)
-        
-        if floor(vaildRect.minX + nwidth) > floor(vaildRect.maxX) {
-            return false
-        }
-        if itemType.isSmall && isLastLine && floor(vaildRect.minX + nwidthWithDelete) > floor(vaildRect.maxX) {
-            return false
-        }
-        if floor(vaildRect.minY + nheight) > floor(vaildRect.maxY) {
-            return false
-        }
-        if visableSize.height != nheight {
-            _isLastLine = nil
-        }
-        
-        visableSize.width = nwidth
-        visableSize.height = nheight
-        
-        emoticons.append(emoticon)
-        return true
-    }
-    
-    var itemSize: CGSize
-    
-    var vaildRect: CGRect
-    var visableSize: CGSize
-    
-    var itemType: JCEmoticonType
-    var isLastLine: Bool {
-        if let isLastLine = _isLastLine {
-            return isLastLine
-        }
-        let isLastLine = floor(vaildRect.minY + visableSize.height + minimumLineSpacing + itemSize.height) > floor(vaildRect.maxY)
-        _isLastLine = isLastLine
-        return isLastLine
-    }
-    
-    var minimumLineSpacing: CGFloat
-    var minimumInteritemSpacing: CGFloat
-    
-    var emoticons: [JCEmoticon]
-    
-    var _isLastLine: Bool?
-    
-    init(_ first: JCEmoticon,
-         _ itemSize: CGSize,
-         _ rect: CGRect,
-         _ lineSpacing: CGFloat,
-         _ interitemSpacing: CGFloat,
-         _ itemType: JCEmoticonType) {
-        
-        self.itemSize = itemSize
-        self.itemType = itemType
-        
-        self.vaildRect = rect
-        self.visableSize = itemSize
-        
-        minimumLineSpacing = lineSpacing
-        minimumInteritemSpacing = interitemSpacing
-        
-        emoticons = [first]
-    }
-}

+ 0 - 119
o2ios/O2Platform/Framework/JMessage/ChatModule/Input/InputView/Emoticon/JCEmoticonPage.swift

@@ -1,119 +0,0 @@
-//
-//  JCEmoticonPage.swift
-//  JChat
-//
-//  Created by deng on 2017/3/9.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-internal class JCEmoticonPage {
-    func draw(in ctx: CGContext) {
-
-        lines.forEach {
-            $0.draw(in: ctx)
-        }
-    }
-    func contents(fetch: @escaping ((Any?) -> (Void))) {
-        if let contents = _contents {
-            fetch(contents.cgImage)
-            return
-        }
-        JCEmoticonPage.queue.async {
-            
-            UIGraphicsBeginImageContextWithOptions(self.bounds.size, false, UIScreen.main.scale)
-            
-            if let ctx = UIGraphicsGetCurrentContext() {
-                self.draw(in: ctx)
-            }
-            let img = UIGraphicsGetImageFromCurrentImageContext()
-            self._contents = img
-            
-            UIGraphicsEndImageContext()
-            
-            fetch(img?.cgImage)
-        }
-    }
-    
-    func addEmoticon(_ emoticon: JCEmoticon) -> Bool {
-        guard let lastLine = lines.last else {
-            return false
-        }
-        if lastLine.addEmoticon(emoticon) {
-            visableSize.width = max(visableSize.width, lastLine.visableSize.width)
-            visableSize.height = lastLine.vaildRect.minY - vaildRect.minY + lastLine.visableSize.height
-            return true
-        }
-        let rect = vaildRect.inset(by: UIEdgeInsets(top: visableSize.height + minimumLineSpacing, left: 0, bottom: 0, right: 0))
-        let line = JCEmoticonLine(emoticon, itemSize, rect, minimumLineSpacing, minimumInteritemSpacing, itemType)
-        if floor(line.vaildRect.minY + line.visableSize.height) > floor(vaildRect.maxY) {
-            return false
-        }
-        lines.append(line)
-        return true
-    }
-    
-    func emoticon(at indexPath: IndexPath) -> JCEmoticon? {
-        guard indexPath.section < lines.count else {
-            return nil
-        }
-        let line = lines[indexPath.section]
-        guard indexPath.item < line.emoticons.count else {
-            return nil
-        }
-        return line.emoticons[indexPath.item]
-    }
-    func rect(at indexPath: IndexPath) -> CGRect? {
-        guard indexPath.section < lines.count else {
-            return nil
-        }
-        return lines[indexPath.section].rect(at: indexPath.item)
-    }
-    
-    var bounds: CGRect
-    
-    var vaildRect: CGRect
-    var visableSize: CGSize
-    var visableRect: CGRect
-    
-    var itemSize: CGSize
-    var itemType: JCEmoticonType
-    
-    var minimumLineSpacing: CGFloat
-    var minimumInteritemSpacing: CGFloat
-    
-    var lines: [JCEmoticonLine]
-    
-    private var _contents: UIImage?
-    
-    init(_ first: JCEmoticon,
-         _ itemSize: CGSize,
-         _ rect: CGRect,
-         _ bounds: CGRect,
-         _ lineSpacing: CGFloat,
-         _ interitemSpacing: CGFloat,
-         _ itemType: JCEmoticonType) {
-        
-        let nlsp = lineSpacing / 2
-        let nisp = interitemSpacing / 2
-        
-        let nrect = rect.inset(by: UIEdgeInsets(top: nlsp, left: nisp, bottom: nlsp, right: nisp))
-        let line = JCEmoticonLine(first, itemSize, nrect, lineSpacing, interitemSpacing, itemType)
-        
-        self.bounds = bounds
-        self.itemSize = itemSize
-        self.itemType = itemType
-        
-        self.vaildRect = nrect
-        self.visableSize = line.visableSize
-        self.visableRect = rect
-        
-        self.minimumLineSpacing = lineSpacing
-        self.minimumInteritemSpacing = interitemSpacing
-        
-        self.lines = [line]
-    }
-    
-    static var queue = DispatchQueue(label: "jc.emoticon.background")
-}

+ 0 - 199
o2ios/O2Platform/Framework/JMessage/ChatModule/Input/InputView/Emoticon/JCEmoticonPageView.swift

@@ -1,199 +0,0 @@
-//
-//  JCEmoticonPageView.swift
-//  JChat
-//
-//  Created by deng on 2017/3/9.
-//  Copyright © 2017年 HXHG. All rights reserved.
-//
-
-import UIKit
-
-internal class JCEmoticonPageView: UICollectionViewCell, UIGestureRecognizerDelegate {
-    
-    open weak var delegate: JCEmoticonDelegate?
-    weak var previewer: JCEmoticonPreviewer?
-    
-    private var _activedIndexPath: IndexPath?
-    
-    private lazy var _backgroundLayer: CALayer = CALayer()
-    private lazy var _backspaceButton: UIButton = UIButton(type: .system)
-    
-    override init(frame: CGRect) {
-        super.init(frame: frame)
-        _init()
-    }
-    required init?(coder aDecoder: NSCoder) {
-        super.init(coder: aDecoder)
-        _init()
-    }
-    
-    func setupBackspace() {
-        _backspaceButton.isHidden = !(page?.itemType.isSmall ?? true)
-        guard let page = self.page else {
-            return
-        }
-        var nframe = CGRect(origin: .zero, size: page.itemSize)
-        
-        nframe.origin.x = page.vaildRect.maxX - nframe.width
-        nframe.origin.y = page.vaildRect.maxY - nframe.height
-        
-        _backspaceButton.frame = nframe
-        _backspaceButton.autoresizingMask = [.flexibleRightMargin, .flexibleBottomMargin]
-        
-        if _backspaceButton.superview == nil {
-            addSubview(_backspaceButton)
-        }
-    }
-    
-    var page: JCEmoticonPage? {
-        didSet {
-            let newValue = self.page
-            guard newValue !== oldValue else {
-                return
-            }
-            newValue?.contents { contents in
-                guard self.page === newValue else {
-                    return
-                }
-                let block = { () -> Void in
-                    self.contentView.layer.contents = contents
-                    self.setupBackspace()
-                }
-                
-                guard !Thread.current.isMainThread else {
-                    block()
-                    return
-                }
-                DispatchQueue.main.async(execute: block)
-            }
-        }
-    }
-    
-    @objc func onPress(_ sender: UITapGestureRecognizer) {
-        guard let idx = _index(at: sender.location(in: self)) else {
-            
-            return // no index
-        }
-        guard let emoticon = page?.emoticon(at: idx) else {
-            return // outside
-        }
-        
-        if delegate?.emoticon(shouldSelectFor: emoticon) ?? true {
-            delegate?.emoticon(didSelectFor: emoticon)
-        }
-    }
-    @objc func onLongPress(_ sender: UITapGestureRecognizer) {
-        guard let page = page else {
-            return
-        }
-        
-        var idx: IndexPath?
-        var rect: CGRect?
-        var emoticon: JCEmoticon?
-        
-        let isbegin = sender.state == .began || sender.state == .possible
-        let isend = sender.state == .cancelled || sender.state == .failed || sender.state == .ended
-        
-        if isend {
-            if let idx = _activedIndexPath, let emoticon = page.emoticon(at: idx) {
-                if delegate?.emoticon(shouldSelectFor: emoticon) ?? true {
-                    delegate?.emoticon(didSelectFor: emoticon)
-                }
-            }
-            idx = nil
-        } else {
-            idx = _index(at: sender.location(in: self))
-        }
-        
-        if let idx = idx {
-            rect = page.rect(at: idx)
-            emoticon = page.emoticon(at: idx)
-        }
-        // 并没有找到任何可用的表情
-        if emoticon == nil {
-            idx = nil
-        }
-        // 检查没有改变
-        guard _activedIndexPath != idx else {
-            return
-        }
-        
-        var canpreview = !isbegin && !isend
-        
-        if canpreview && !(delegate?.emoticon(shouldPreviewFor: emoticon) ?? true) {
-            canpreview = false
-            emoticon = nil
-            idx = nil
-        }
-        
-        _activedIndexPath = idx
-        
-        if let nframe = rect, page.itemType.isLarge {
-            _backgroundLayer.frame = nframe
-            _backgroundLayer.isHidden = false
-            _backgroundLayer.removeAllAnimations()
-        } else {
-            _backgroundLayer.isHidden = true
-        }
-        
-        previewer?.preview(emoticon, page.itemType, in: rect ?? .zero)
-        
-        if isbegin || canpreview {
-            delegate?.emoticon(didPreviewFor: emoticon)
-        }
-    }
-    @objc func onBackspace(_ sender: UIButton) {
-        
-        if delegate?.emoticon(shouldSelectFor: JCEmoticon.backspace) ?? true {
-            delegate?.emoticon(didSelectFor: JCEmoticon.backspace)
-        }
-    }
-    
-    // MARK: UIGestureRecognizerDelegate
-    override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
-        if let idx = _index(at: gestureRecognizer.location(in: self)), let emoticon = page?.emoticon(at: idx) {
-            return delegate?.emoticon(shouldPreviewFor: emoticon) ?? true
-        }
-        return false
-    }
-    
-    private func _index(at point: CGPoint) -> IndexPath? {
-        guard let page = page else {
-            return nil
-        }
-        let rect = page.visableRect
-        guard rect.contains(point) else {
-            return nil
-        }
-        let x = point.x - rect.minX
-        let y = point.y - rect.minY
-        
-        let col = Int(x / (page.itemSize.width + page.minimumInteritemSpacing))
-        let row = Int(y / (page.itemSize.height + page.minimumLineSpacing))
-        
-        return IndexPath(item: col, section: row)
-    }
-    
-    private func _init() {
-        
-        _backgroundLayer.backgroundColor = UIColor(white: 0, alpha: 0.2).cgColor
-        _backgroundLayer.masksToBounds = true
-        _backgroundLayer.cornerRadius = 4
-        
-        _backspaceButton.tintColor = .gray
-        _backspaceButton.setTitle("⌫", for: .normal)
-        _backspaceButton.addTarget(self, action: #selector(onBackspace(_:)), for: .touchUpInside)
-        
-        let tapgr = UITapGestureRecognizer(target: self, action: #selector(onPress(_:)))
-        let longtapgr = UILongPressGestureRecognizer(target: self, action: #selector(onLongPress(_:)))
-        
-        longtapgr.delegate = self
-        longtapgr.minimumPressDuration = 0.25
-        
-        layer.addSublayer(_backgroundLayer)
-        
-        contentView.addGestureRecognizer(tapgr)
-        contentView.addGestureRecognizer(longtapgr)
-    }
-}
-

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.