Last active
          July 12, 2021 21:56 
        
      - 
      
 - 
        
Save asciimike/cc45567cd95ba2a62017cb21e891effd to your computer and use it in GitHub Desktop.  
Revisions
- 
        
asciimike revised this gist
May 21, 2016 . No changes.There are no files selected for viewing
 - 
        
asciimike revised this gist
May 21, 2016 . 3 changed files with 30 additions and 113 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,30 @@ /// // AppDelegate.swift // ZeroToApp // import UIKit import Firebase import FBSDKCoreKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { // Configure Firebase SDK FIRApp.configure() // Configure Facebook SDK FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions) return true } func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool { return FBSDKApplicationDelegate.sharedInstance().application(application, openURL: url, sourceApplication: sourceApplication, annotation: annotation) } } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -2,8 +2,6 @@ // ViewController.swift // ZeroToApp // import UIKit import Firebase This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,111 +0,0 @@  - 
        
asciimike revised this gist
May 21, 2016 . 1 changed file with 111 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,111 @@ <!-- Zero to App --> <!-- Copyright © 2016 Google. All rights reserved. --> <html> <head> <script src="https://www.gstatic.com/firebasejs/3.0.0/firebase.js"></script> <title>ZeroToApp</title> <style> #messages { width: 40em; border: 1px solid grey; min-height: 20em; } #messages img { max-width: 240px; max-height: 160px; display: block; } #header { position: fixed; top: 0; background-color: white; } .push { margin-bottom: 2em; } @keyframes yellow-fade { 0% {background: #f2f2b8 <span class='hexPreview' style='background-color: #f2f2b8'> </span>;} 100% {background: none;} } .highlight { -webkit-animation: yellow-fade 2s ease-in 1; animation: yellow-fade 2s ease-in 1; } </style> <script> document.addEventListener('DOMContentLoaded', function() { // Step 0: HTML defined, variables for elements var messagesList = document.getElementById('messages'), textInput = document.getElementById('text'), sendButton = document.getElementById('send'), login = document.getElementById('login'), googleLogin = document.getElementById('google'), facebookLogin = document.getElementById('facebook'), signedIn = document.getElementById('loggedin'), logout = document.getElementById('logout'), usernameElm = document.getElementById('username'), password = document.getElementById('password'), username = "Web"; var config = { apiKey: "<your-api-key>", authDomain: "<your-auth-domain>", databaseURL: "<your-database-url>", storageBucket: "<your-storage-bucket>" }; sendButton.addEventListener('click', function(evt) { var chat = { name: username, message: textInput.value }; addMessage(chat); textInput.value = ''; }); function handleFileSelect(e) { var file = e.target.files[0]; var reader = new FileReader(); reader.onload = (function(theFile) { return function(e) { addMessage({ name: "Web", message: e.target.result }); }; })(file); reader.readAsDataURL(file); } file.addEventListener('change', handleFileSelect, false); function setUsername(newUsername) { if (newUsername == null) { newUsername = "Web"; } console.log(newUsername); username = newUsername; var isLoggedIn = username != 'Web'; usernameElm.innerText = newUsername; logout.style.display = isLoggedIn ? '' : 'none'; facebookLogin.style.display = isLoggedIn ? 'none' : ''; googleLogin.style.display = isLoggedIn ? 'none' : ''; } function addMessage(chat) { var li = document.createElement('li'); var nameElm = document.createElement('h4'); nameElm.innerText = chat.name; li.appendChild(nameElm); li.className = 'highlight'; if ( chat.message.indexOf("https://firebasestorage.googleapis.com/") == 0 || chat.message.indexOf("https://lh3.googleusercontent.com/") == 0 || chat.message.indexOf("http://pbs.twimg.com/") == 0 || chat.message.indexOf("data:image/") == 0) { var imgElm = document.createElement("img"); imgElm.src = chat.message; li.appendChild(imgElm); } else { var messageElm = document.createElement("span"); messageElm.innerText = chat.message; li.appendChild(messageElm); } messagesList.appendChild(li); li.scrollIntoView(false); sendButton.scrollIntoView(false); } //window.app = app; // NOTE: just for debugging //for (var i=0; i < 10; i++) addMessage({ name: "Web", message: ''+i }); setUsername('Web'); }); </script> </head> <body> <div id='header'> <label for='username'><img src="https://www.gstatic.com/images/icons/material/system/1x/account_box_black_24dp.png" width="24"/></label> <span id='username'></span> <span id='login'> <button id='google' class='idp-button'>Sign in with Google</button> <button id='facebook' class='idp-button'>Sign in with Facebook</button> </span> <button id='logout' class='idp-button'>Sign out</button> </div> <div class="push"></div> <ul id='messages'></ul> <div id='footer'> <img src="https://www.gstatic.com/images/icons/material/system/1x/add_a_photo_black_24dp.png" width="24"/> <input type="file" id="file" name="file" /> <input id='text'></text> <button id='send'>Send</button> </div> </body> </html>  - 
        
asciimike created this gist
May 21, 2016 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,250 @@ // // ViewController.swift // ZeroToApp // // Copyright © 2016 Google. All rights reserved. // import UIKit import Firebase import FBSDKLoginKit import Photos struct ChatMessage { var name: String! var message: String! var image: UIImage? } class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate { // Outlets @IBOutlet weak var messageTextField: UITextField! @IBOutlet weak var sendButton: UIButton! @IBOutlet weak var tableView: UITableView! // Useful app properties let imagePicker = UIImagePickerController() var messages: [ChatMessage]! var username: String! // Firebase services var database: FIRDatabase! var auth: FIRAuth! var storage: FIRStorage! override func viewDidLoad() { super.viewDidLoad() // Initialize navigation bar self.title = "Zero To App" navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Log in", style: UIBarButtonItemStyle.Plain, target: self, action: #selector(toggleAuthState)) navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Camera, target: self, action: #selector(selectImage)) // Initialize send button sendButton.addTarget(self, action: #selector(sendMessage), forControlEvents: .TouchUpInside) // Initialize UIImagePicker imagePicker.delegate = self // Initialize other properties messages = [] username = "iOS" // Initialize UITableView tableView.delegate = self tableView.dataSource = self let nib = UINib(nibName: "ChatMessageTableViewCell", bundle: nil) tableView.registerNib(nib, forCellReuseIdentifier: "chatMessageCell") // Initialize Database, Auth, Storage database = FIRDatabase.database() auth = FIRAuth.auth() storage = FIRStorage.storage() // Listen for when child nodes get added to the collection let chatRef = database.reference().child("chat") chatRef.observeEventType(.ChildAdded, withBlock: { (snapshot) -> Void in // Get the chat message from the snapshot and add it to the UI let data = snapshot.value as! Dictionary<String, String> guard let name = data["name"] as String! else { return } guard let message = data["message"] as String! else { return } let chatMessage = ChatMessage(name: name, message: message, image: nil) self.addMessage(chatMessage) }) // Observe auth state change self.auth.addAuthStateDidChangeListener { (auth, user) in if (user != nil) { self.username = user?.displayName self.navigationItem.rightBarButtonItem?.title = "Log out" } else { self.username = "iOS" self.navigationItem.rightBarButtonItem?.title = "Log in" } } } // Send a chat message func sendMessage(sender: AnyObject) { // Create chat message let chatMessage = ChatMessage(name: self.username, message: messageTextField.text!, image: nil) messageTextField.text = "" // Create a reference to our chat message let chatRef = database.reference().child("chat") // Push the chat message to the database chatRef.childByAutoId().setValue(["name": chatMessage.name, "message": chatMessage.message]) } // Show a popup when the user asks to sign in func toggleAuthState() { if (auth.currentUser != nil) { // Allow the user to sign out do { try auth.signOut() } catch {} } else { // Log in to Facebook let login = FBSDKLoginManager() login.logInWithReadPermissions(["public_profile"], fromViewController: self, handler: { (result, error) in if (error != nil || result.isCancelled) { print(error) } else { // Log in to Firebase via Facebook let credential = FIRFacebookAuthProvider.credentialWithAccessToken(result.token.tokenString) FIRAuth.auth()?.signInWithCredential(credential) { (user, error) in if (error != nil) { print(error) } } } }) } } // Handle photo uploads button func selectImage() { imagePicker.allowsEditing = false imagePicker.sourceType = .PhotoLibrary presentViewController(imagePicker, animated: true, completion: nil) } // pragma mark - UIImagePickerDelegate overrides func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) { // Get local file URLs guard let image: UIImage = info[UIImagePickerControllerOriginalImage] as? UIImage else { return } let imageData = UIImagePNGRepresentation(image)! guard let imageURL: NSURL = info[UIImagePickerControllerReferenceURL] as? NSURL else { return } // Get a reference to the location where we'll store our photos let photosRef = storage.reference().child("chat_photos") // Get a reference to store the file at chat_photos/<FILENAME> let photoRef = photosRef.child("\(NSUUID().UUIDString).png") // Upload file to Firebase Storage let metadata = FIRStorageMetadata() metadata.contentType = "image/png" photoRef.putData(imageData, metadata: metadata).observeStatus(.Success) { (snapshot) in // When the image has successfully uploaded, we get it's download URL let text = snapshot.metadata?.downloadURL()?.absoluteString // Set the download URL to the message box, so that the user can send it to the database self.messageTextField.text = text } // Clean up picker dismissViewControllerAnimated(true, completion: nil) } func addMessage(var chatMessage: ChatMessage) { // Handle remote image messages if (chatMessage.message.containsString("https://firebasestorage.googleapis.com")) { self.storage.referenceForURL(chatMessage.message).dataWithMaxSize(25 * 1024 * 1024, completion: { (data, error) -> Void in let image = UIImage(data: data!) chatMessage.image = image! self.messages.append(chatMessage) self.tableView.reloadData() self.scrollToBottom() }) // Handle asset library messages } else if (chatMessage.message.containsString("assets-library://")) { let assetURL = NSURL(string: chatMessage.message) let assets = PHAsset.fetchAssetsWithALAssetURLs([assetURL!], options: nil) let asset: PHAsset = assets.firstObject as! PHAsset let manager = PHImageManager.defaultManager() manager.requestImageForAsset(asset, targetSize: CGSize(width: 100.0, height: 100.0), contentMode: .AspectFit, options: nil, resultHandler: {(result, info)->Void in chatMessage.image = result! self.messages.append(chatMessage) self.tableView.reloadData() self.scrollToBottom() }) // Handle regular messages } else { self.messages.append(chatMessage) self.tableView.reloadData() self.scrollToBottom() } } func scrollToBottom() { if (self.messages.count > 8) { let bottomOffset = CGPoint(x: 0, y: tableView.contentSize.height - tableView.bounds.size.height) tableView.setContentOffset(bottomOffset, animated: true) } } // pragma mark - UITableViewDataSource overrides func numberOfSectionsInTableView(tableView: UITableView) -> Int { return 1 } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("chatMessageCell", forIndexPath: indexPath) as! ChatMessageTableViewCell let chatMessage = messages[indexPath.row] cell.nameLabel.text = chatMessage.name cell.messageLabel.text = chatMessage.message cell.photoView.image = chatMessage.image return cell } // pragma mark - UITableViewDelegate overrides func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { let chatMessage = messages[indexPath.row] if (chatMessage.image != nil) { return 345.0 } else { return 58.0 } } func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return messages.count } func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { tableView.deselectRowAtIndexPath(indexPath, animated: true) } // Create a chat message from a FIRDataSnapshot func chatMessageFromSnapshot(snapshot: FIRDataSnapshot) -> ChatMessage? { let data = snapshot.value as! Dictionary<String, String> guard let name = data["name"] as String! else { return nil } guard let message = data["message"] as String! else { return nil } let chatMessage = ChatMessage(name: name, message: message, image: nil) return chatMessage } }