git.iko.soy/dashared/GDproject
on master help sign in
Added ability to write and send message to chats and groups. Full UI is waiting for me. Can give admins. Chat info is completed.
commit4acfa6e9aafabb6bfd76281869c8136191d5fa98 authorDarya Rednikina <rednikina.com@yandex.ru> dateMon 6 May 2019, 18:54 (7 years ago) parentb65cc45
7 files changed+209−57
GDproject/Base.lproj/Main.storyboard−44 GDproject/Controller/Coordinators/MessagesCoordinator.swift+2−4 GDproject/Controller/Messages/ChatInfoViewController.swift+43−1 GDproject/Controller/Messages/Dialog/DialogViewController.swift+109−5 GDproject/Controller/Messages/MessagesViewController.swift+2−1 GDproject/Controller/Profile/ProfileViewController.swift+1−1 GDproject/Simple model/Model.swift+52−1
GDproject/Base.lproj/Main.storyboard−44
@@ -610,50 +610,6 @@
610610 </objects>
611611 <point key="canvasLocation" x="3614" y="938"/>
612612 </scene>
613− <!--Dialog View Controller-->
614− <scene sceneID="9ac-1R-s4m">
615− <objects>
616− <tableViewController storyboardIdentifier="DialogViewController" id="AVr-rR-mka" customClass="DialogViewController" customModule="GDproject" customModuleProvider="target" sceneMemberID="viewController">
617− <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="NlQ-jM-tQP">
618− <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
619− <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
620− <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
621− <prototypes>
622− <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" reuseIdentifier="cell3" textLabel="8Ad-wM-No8" detailTextLabel="QHM-V8-CWk" style="IBUITableViewCellStyleSubtitle" id="bgd-9d-SmR">
623− <rect key="frame" x="0.0" y="28" width="375" height="44"/>
624− <autoresizingMask key="autoresizingMask"/>
625− <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="bgd-9d-SmR" id="9W4-bO-4MN">
626− <rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
627− <autoresizingMask key="autoresizingMask"/>
628− <subviews>
629− <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="8Ad-wM-No8">
630− <rect key="frame" x="16" y="5" width="33.5" height="20.5"/>
631− <autoresizingMask key="autoresizingMask"/>
632− <fontDescription key="fontDescription" type="system" pointSize="17"/>
633− <nil key="textColor"/>
634− <nil key="highlightedColor"/>
635− </label>
636− <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="hfhhfhh" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="QHM-V8-CWk">
637− <rect key="frame" x="16" y="25.5" width="44.5" height="14.5"/>
638− <autoresizingMask key="autoresizingMask"/>
639− <fontDescription key="fontDescription" type="system" pointSize="12"/>
640− <nil key="textColor"/>
641− <nil key="highlightedColor"/>
642− </label>
643− </subviews>
644− </tableViewCellContentView>
645− </tableViewCell>
646− </prototypes>
647− <connections>
648− <outlet property="dataSource" destination="AVr-rR-mka" id="quz-3V-jDT"/>
649− <outlet property="delegate" destination="AVr-rR-mka" id="R4y-E9-LVr"/>
650− </connections>
651− </tableView>
652− </tableViewController>
653− <placeholder placeholderIdentifier="IBFirstResponder" id="Tzh-O8-O7T" userLabel="First Responder" sceneMemberID="firstResponder"/>
654− </objects>
655− <point key="canvasLocation" x="4336" y="937"/>
656− </scene>
657613 <!--Chat Info View Controller-->
658614 <scene sceneID="1br-Xg-fR9">
659615 <objects>
GDproject/Controller/Coordinators/MessagesCoordinator.swift+2−4
@@ -40,15 +40,13 @@ class MessagesCoordinator: BaseCoordinator {
4040 vc?.navigationController?.pushViewController(newVC, animated: true)
4141 }
4242
43− vc.onDialogDisplay = { [weak vc, unowned self] in
44− let newVC = self.storyboard.instantiateViewController(withIdentifier: dialogVC) as! DialogViewController
43+ vc.onDialogDisplay = { [weak vc] in
44+ let newVC = DialogViewController()
4545 newVC.dialog = $0.dialog
4646 newVC.users = $0.users
4747 vc?.navigationController?.pushViewController(newVC, animated: true)
4848 }
4949
50−
51−
5250 navigationController?.viewControllers = [vc]
5351 }
5452}
GDproject/Controller/Messages/ChatInfoViewController.swift+43−1
@@ -119,7 +119,14 @@ class ChatInfoViewController: UITableViewController {
119119 }
120120
121121 private func name(for user: Model.Users?) -> String {
122− return "👤 \(user!.fullName())"
122+ if let user = user, let perm = groupChat?.users[user.id]?.isAdmin {
123+ if perm {
124+ return "🤴🏻 \(user.fullName())"
125+ }
126+ return "👤 \(user.fullName())"
127+ }
128+
129+ return "left"
123130 }
124131
125132 override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?
@@ -219,6 +226,41 @@ class ChatInfoViewController: UITableViewController {
219226 return true
220227 }
221228
229+ override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]?
230+ {
231+ let editButton = UITableViewRowAction(style: .normal, title: "Promote") { [unowned self] (rowAction, indexPath) in
232+
233+ self.tableView.beginUpdates()
234+ self.groupChat?.users[self.usersArray[indexPath.row-1]]?.isAdmin = true
235+ self.tableView.reloadRows(at: [indexPath], with: .none)
236+ self.tableView.endUpdates()
237+ }
238+
239+ editButton.backgroundColor = #colorLiteral(red: 0.476841867, green: 0.5048075914, blue: 1, alpha: 1)
240+
241+ let restrictButton = UITableViewRowAction(style: .normal, title: "Restrict") { [unowned self] (rowAction, indexPath) in
242+
243+ self.tableView.beginUpdates()
244+ self.groupChat?.users[self.usersArray[indexPath.row-1]]?.isAdmin = false
245+ self.tableView.reloadRows(at: [indexPath], with: .none)
246+ self.tableView.endUpdates()
247+ }
248+
249+ restrictButton.backgroundColor = #colorLiteral(red: 0.8039215803, green: 0.8039215803, blue: 0.8039215803, alpha: 1)
250+
251+ let deleteButton = UITableViewRowAction(style: .normal, title: "Delete") { [unowned self] (action, indexPath) in
252+
253+ self.tableView.beginUpdates()
254+ self.groupChat?.users[self.usersArray[indexPath.row-1]] = nil
255+ self.tableView.deleteRows(at: [indexPath], with: .none)
256+ self.tableView.endUpdates()
257+ }
258+
259+ deleteButton.backgroundColor = #colorLiteral(red: 1, green: 0.1491314173, blue: 0, alpha: 1)
260+
261+ return [editButton, restrictButton, deleteButton]
262+ }
263+
222264 /// update chatInfo
223265 override func viewWillDisappear(_ animated: Bool) {
224266
GDproject/Controller/Messages/Dialog/DialogViewController.swift+109−5
@@ -7,12 +7,16 @@
77//
88
99import UIKit
10+import TinyConstraints
1011
1112protocol UpdatableGroup:class {
1213 func updateGroup(with group: Model.Group)
1314}
1415
15−class DialogViewController: UITableViewController, UpdatableGroup {
16+class DialogViewController: UIViewController, UpdatableGroup, UITableViewDelegate, UITableViewDataSource
17+{
18+
19+ var tableView: UITableView = UITableView()
1620
1721 func updateGroup(with group: Model.Group){
1822 self.groupChat?.group = group
@@ -49,6 +53,12 @@ class DialogViewController: UITableViewController, UpdatableGroup {
4953
5054 override func viewDidLoad() {
5155 super.viewDidLoad()
56+
57+ setConstraints()
58+ magicForKeyboardChanges()
59+
60+ self.tableView.delegate = self
61+ self.tableView.dataSource = self
5262
5363 tabBarController?.tabBar.isHidden = true
5464 navigationItem.largeTitleDisplayMode = .never
@@ -65,6 +75,97 @@ class DialogViewController: UITableViewController, UpdatableGroup {
6575 }
6676 }
6777
78+ var messageSendView: UIView = {
79+ let view = UIView()
80+ view.backgroundColor = .red
81+ return view
82+ }()
83+
84+ var messageTextView: UITextView = {
85+ let textView = UITextView()
86+ textView.isEditable = true
87+ textView.isScrollEnabled = true
88+ textView.backgroundColor = .green
89+ return textView
90+ }()
91+
92+ var sendButton: UIButton = {
93+ let button = UIButton()
94+ button.setTitle("Send", for: .normal)
95+ button.setTitleColor(.blue, for: .normal)
96+ button.addTarget(self, action: #selector(sendMessage), for: .touchUpInside)
97+ return button
98+ }()
99+
100+ @objc func sendMessage()
101+ {
102+ var destination: Model.MessageDestination?
103+
104+ if let group = groupChat{
105+ destination = Model.MessageDestination.groupChatDestination(group.group.id)
106+ } else if let user = userChat {
107+ destination = Model.MessageDestination.userChatDestination(user.user)
108+ }
109+
110+ if let destination = destination
111+ {
112+ Model.sendMessage(message: Model.SendMessage(body: Model.Attachments(markdown: messageTextView.text), destination: destination)) { [unowned self] in
113+ self.getMessages(for: self.dialog!)
114+ }
115+ }
116+ }
117+
118+ var bottomConstraint: NSLayoutConstraint!
119+
120+ func setConstraints(){
121+ self.view.addSubview(tableView)
122+ self.view.addSubview(messageSendView)
123+
124+ messageSendView.addSubview(messageTextView)
125+ messageSendView.addSubview(sendButton)
126+
127+ messageSendView.edgesToSuperview(excluding: [.top,.bottom])
128+
129+ bottomConstraint = NSLayoutConstraint(item: messageSendView, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: 0)
130+ view.addConstraint(bottomConstraint)
131+
132+ messageSendView.height(40)
133+
134+ sendButton.edgesToSuperview(excluding: .left)
135+ sendButton.width(60)
136+
137+ messageTextView.edgesToSuperview(excluding: .right)
138+ messageTextView.rightToLeft(of: sendButton)
139+
140+ tableView.edgesToSuperview(excluding: .bottom)
141+ tableView.bottomToTop(of: messageSendView)
142+
143+ self.view.layoutSubviews()
144+ }
145+
146+ func magicForKeyboardChanges()
147+ {
148+ NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotifications), name: UIResponder.keyboardWillShowNotification, object: nil)
149+
150+ NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardNotifications), name: UIResponder.keyboardWillHideNotification, object: nil)
151+ }
152+
153+ @objc func handleKeyboardNotifications(notification: NSNotification){
154+ if let userInfo = notification.userInfo{
155+ // UIKeyboardFrameEndUserInfoKey
156+
157+ let keyBoardFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
158+
159+ bottomConstraint.constant = notification.name == UIResponder.keyboardWillShowNotification ? -(keyBoardFrame.height) : 0
160+
161+ UIView.animate(withDuration: 0, delay: 0, options: .curveEaseOut, animations: {
162+ self.view.layoutIfNeeded()
163+ }) { (completed) in
164+
165+ }
166+ }
167+ }
168+
68169 func setTitleForChat(userChat: Model.UserChat){
69170 navigationItem.title = "🌌 \(users![userChat.user]!.fullName())"
70171 }
@@ -75,7 +176,7 @@ class DialogViewController: UITableViewController, UpdatableGroup {
75176 }
76177
77178 @objc func moveToInfoVC(){
78− let vc = storyboard?.instantiateViewController(withIdentifier: chatInfoViewController) as! ChatInfoViewController
179+ let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: chatInfoViewController) as! ChatInfoViewController
79180
80181 vc.delegate = self
81182 vc.users = users!
@@ -97,11 +198,11 @@ class DialogViewController: UITableViewController, UpdatableGroup {
97198
98199 // MARK: - Table view data source
99200
100− override func numberOfSections(in tableView: UITableView) -> Int {
201+ func numberOfSections(in tableView: UITableView) -> Int {
101202 return 1
102203 }
103204
104− override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
205+ func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
105206 return cellData.count
106207 }
107208
@@ -128,7 +229,7 @@ class DialogViewController: UITableViewController, UpdatableGroup {
128229 }
129230 }
130231
131− override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
232+ func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
132233 {
133234 let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! DialogCell
134235
@@ -143,3 +244,6 @@ class DialogViewController: UITableViewController, UpdatableGroup {
143244 return cell
144245 }
145246}
247+
248+
249+
GDproject/Controller/Messages/MessagesViewController.swift+2−1
@@ -67,11 +67,12 @@ class MessagesViewController: UITableViewController {
6767 let cell = tableView.dequeueReusableCell(withIdentifier: "MessagesCell", for: indexPath)
6868
6969 switch currentActiveDialogs[indexPath.row].self {
70+
7071 case .groupChat(let group):
7172 cell.textLabel?.text = group.group.name
7273 cell.detailTextLabel?.text = group.lastMessage.body.markdown
7374 case .userChat(let userChat):
74− cell.textLabel?.text = "\(users[userChat.user]!)"
75+ cell.textLabel?.text = "👤 \(users[userChat.user]!.fullName())"
7576 cell.detailTextLabel?.text = userChat.lastMessage.body.markdown
7677 }
7778
GDproject/Controller/Profile/ProfileViewController.swift+1−1
@@ -90,7 +90,7 @@ class ProfileViewController: UIViewController
9090 tableView.register(PostViewCell.self, forCellReuseIdentifier: postCellId)
9191
9292 tableView.register(BasicInfoCell.self, forCellReuseIdentifier: basicInfoCellId)
93−
93+
9494 tableView.register(InfoCell.self, forCellReuseIdentifier: infoCellId)
9595
9696 posts.viewController = self
GDproject/Simple model/Model.swift+52−1
@@ -642,7 +642,7 @@ class Model{
642642 var author: Int
643643 var id: Int
644644
645− private enum MessageCodingKeys: CodingKey{
645+ enum MessageCodingKeys: CodingKey{
646646 case user
647647 case group
648648 case body
@@ -793,4 +793,55 @@ class Model{
793793
794794 // completion()
795795 }
796+
797+ struct SendMessage: Codable {
798+ var body: Attachments
799+ var destination: MessageDestination
800+
801+ init(from decoder: Decoder) throws
802+ {
803+ let container = try decoder.container(keyedBy: LastMessage.MessageCodingKeys.self)
804+ body = try container.decode(Attachments.self, forKey: .body)
805+
806+ if container.contains(.user){
807+ destination = MessageDestination.userChatDestination(try Int(from: container.superDecoder(forKey: .user)))
808+ } else if container.contains(.group){
809+ destination = MessageDestination.groupChatDestination(try Int(from: container.superDecoder(forKey: .group)))
810+ } else {
811+ throw DecodingError.keyNotFound(LastMessage.MessageCodingKeys.group, DecodingError.Context(codingPath: container.codingPath, debugDescription: "hz gr1"))
812+ }
813+ }
814+
815+ func encode(to encoder: Encoder) throws {
816+ var container = encoder.container(keyedBy: LastMessage.MessageCodingKeys.self)
817+ try container.encode(body, forKey: .body)
818+
819+ switch destination {
820+ case .userChatDestination(let uId):
821+ try uId.encode(to: container.superEncoder(forKey: .user))
822+ case .groupChatDestination(let gId):
823+ try gId.encode(to: container.superEncoder(forKey: .group))
824+ }
825+ }
826+
827+ init(body: Attachments, destination: MessageDestination)
828+ {
829+ self.body = body
830+ self.destination = destination
831+ }
832+ }
833+
834+ static func sendMessage(message: SendMessage, completion: @escaping (()->())){
835+
836+ var request = URLRequest(url: messagesSendURL)
837+ request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
838+ request.httpMethod = "POST"
839+ request.httpBody = try? JSONEncoder().encode(message)
840+
841+ AF.request(request).response { (response) in
842+ isValidTocken?(response.response?.statusCode ?? 498)
843+
844+ completion()
845+ }
846+ }
796847}