Skip to content

Instantly share code, notes, and snippets.

@shreyas-v-agnihotri
Created February 6, 2019 05:53
Show Gist options
  • Save shreyas-v-agnihotri/d6763984028bd871c9fad64cf435502b to your computer and use it in GitHub Desktop.
Save shreyas-v-agnihotri/d6763984028bd871c9fad64cf435502b to your computer and use it in GitHub Desktop.
Coding sample #2 for DALI Lab application
//
// 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