Created
February 6, 2019 05:53
-
-
Save shreyas-v-agnihotri/d6763984028bd871c9fad64cf435502b to your computer and use it in GitHub Desktop.
Coding sample #2 for DALI Lab application
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// ChatViewController.swift | |
// Flash Chat | |
// | |
// Created by Shreyas Agnihotri on 1/10/19. | |
// Copyright (c) 2019 Shreyas Agnihotri. All rights reserved. | |
// | |
import UIKit | |
import Firebase | |
import ChameleonFramework | |
class ChatViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate { | |
// Global variables | |
@IBOutlet var heightConstraint: NSLayoutConstraint! | |
@IBOutlet var sendButton: UIButton! | |
@IBOutlet var messageTextfield: UITextField! | |
@IBOutlet var messageTableView: UITableView! | |
var messageArray: [Message] = [Message]() // List of all messages in chat | |
var topButton = UIButton() | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
// Sets up delegates to fetch and send data | |
messageTableView.delegate = self | |
messageTableView.dataSource = self | |
messageTextfield.delegate = self | |
// Sets up table view cell design | |
messageTableView.register(UINib(nibName: "MessageCell", bundle: nil) , forCellReuseIdentifier: "customMessageCell") | |
let tapGesture = UITapGestureRecognizer(target: self, action: #selector (tableViewTapped)) | |
messageTableView.addGestureRecognizer(tapGesture) | |
configureTableView() // Sets table's display properties | |
retrieveMessages() // Fetches messages from Firebase | |
messageTableView.separatorStyle = .none // Removes lines between rows | |
} | |
// MARK: TableView Delegate Methods | |
// Sets image, message text, and sender for a given message in the table | |
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { | |
let cell = tableView.dequeueReusableCell(withIdentifier: "customMessageCell", for: indexPath) as! CustomMessageCell | |
cell.messageBody.text = messageArray[indexPath.row].messageBody | |
cell.senderUsername.text = messageArray[indexPath.row].sender | |
cell.avatarImageView.image = UIImage(named: "egg") | |
// Sets background to blue if message is from logged in user. | |
if cell.senderUsername.text == Auth.auth().currentUser?.email! { | |
cell.avatarImageView.backgroundColor = UIColor.flatMint() | |
cell.messageBackground.backgroundColor = UIColor.flatSkyBlue() | |
} | |
// Sets background to grey if message is from another user. | |
else { | |
cell.avatarImageView.backgroundColor = UIColor.flatWatermelon() | |
cell.messageBackground.backgroundColor = UIColor.flatGray() | |
} | |
return cell | |
} | |
// Sets number of rows in table to number of messages | |
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { | |
return messageArray.count | |
} | |
// Stops accepting message input when user clicks off of keyboard and textbox | |
@objc func tableViewTapped() { | |
messageTextfield.endEditing(true) | |
} | |
// Sets display properties of table | |
func configureTableView() { | |
messageTableView.rowHeight = UITableView.automaticDimension | |
messageTableView.estimatedRowHeight = 120.0 | |
} | |
// MARK: TextField Delegate Methods | |
// Moves message content upwards to accomodate keyboard when user begins typing (animated) | |
func textFieldDidBeginEditing(_ textField: UITextField) { | |
UIView.animate(withDuration: 0.5) { | |
self.heightConstraint.constant = 308 // Necessary height to fit keyboard & textbox | |
self.view.layoutIfNeeded() | |
} | |
} | |
// Moves message content downward once keyboard is dismissed (animated) | |
func textFieldDidEndEditing(_ textField: UITextField) { | |
UIView.animate(withDuration: 0.5) { | |
self.heightConstraint.constant = 50 // Necessary height to fit textbox | |
self.view.layoutIfNeeded() | |
} | |
} | |
//MARK: Send & Recieve Messages from Firebase | |
@IBAction func sendPressed(_ sender: AnyObject) { | |
// Disables user's ability to compose and send messages until message is sent to Firebase | |
messageTextfield.endEditing(true) | |
messageTextfield.isEnabled = false | |
sendButton.isEnabled = false | |
// Fetches database of messages and creates dictionary representing message with [user, message] | |
let messagesDB = Database.database().reference().child("Messages") | |
let messageDictionary = ["Sender": Auth.auth().currentUser?.email, | |
"MessageBody": messageTextfield.text!] | |
// Adds sent message to database | |
messagesDB.childByAutoId().setValue(messageDictionary) { (error, reference) in | |
// Print statements for error debugging | |
if error != nil { | |
print(error!) | |
} | |
else { | |
print("Message saved successfully!") | |
} | |
// Re-establishes user's ability to compose and send messages | |
self.messageTextfield.isEnabled = true | |
self.sendButton.isEnabled = true | |
self.messageTextfield.text = "" | |
} | |
} | |
// Fetches messages from Firebase and adds them to list of messages in chat | |
func retrieveMessages() { | |
let messageDB = Database.database().reference().child("Messages") // Fetches database | |
// Loops through children of database (dictionaries of messages) | |
messageDB.observe(.childAdded) { (snapshot) in | |
let snapshotValue = snapshot.value as! Dictionary<String, String> // Unwraps snapshot as [user, message] | |
let text = snapshotValue["MessageBody"]! | |
let sender = snapshotValue["Sender"]! | |
// Creates new message with data from current message dictionary | |
let message = Message() | |
message.messageBody = text | |
message.sender = sender | |
self.messageArray.append(message) | |
// Updates table with new message | |
self.configureTableView() | |
self.messageTableView.reloadData() | |
// Scrolls table to bottom-most message | |
let iPath = NSIndexPath(row: self.messageTableView.numberOfRows(inSection: 0)-1, | |
section: self.messageTableView.numberOfSections-1) | |
self.messageTableView.scrollToRow(at: iPath as IndexPath, | |
at: UITableView.ScrollPosition.bottom, | |
animated: true) | |
} | |
} | |
// MARK: Logout Method | |
// Signs user out of Firebase and returns to sign-in screen | |
@IBAction func logOutPressed(_ sender: AnyObject) { | |
do { | |
try Auth.auth().signOut() | |
navigationController?.popToRootViewController(animated: true) | |
} | |
catch { | |
print("error: there was a problem logging out") | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment