Skip to content

Commit

Permalink
Updated the UI for scan QR Code and Show QR Code. Added support for s…
Browse files Browse the repository at this point in the history
…aving QR Code to photos and sharing QR Code. Also added support for scanning QR from image. Minor bug fixes.
  • Loading branch information
Raghav Bhasin authored and Raghav Bhasin committed Aug 30, 2018
1 parent 34e77bb commit 271e8dc
Show file tree
Hide file tree
Showing 15 changed files with 301 additions and 27 deletions.
Binary file modified img/qr_code.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions ios App/Dracker.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
3CA9DD6C20F6EF04000EB47F /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CA9DD6B20F6EF04000EB47F /* Extensions.swift */; };
3CA9DD6E20F6EF2D000EB47F /* Global Functions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CA9DD6D20F6EF2D000EB47F /* Global Functions.swift */; };
3CA9DD7020F6EF4F000EB47F /* Global Variables.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CA9DD6F20F6EF4F000EB47F /* Global Variables.swift */; };
3CABE2E32137A04F00F46100 /* ShareButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CABE2E22137A04F00F46100 /* ShareButton.swift */; };
3CB1B07C20FADB8F004EB7CF /* FriendDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CB1B07B20FADB8F004EB7CF /* FriendDetail.swift */; };
3CB48E9320F6EFD000019DC9 /* Keys.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CB48E9220F6EFD000019DC9 /* Keys.swift */; };
3CB48E9620F6F02100019DC9 /* API.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CB48E9520F6F02100019DC9 /* API.swift */; };
Expand Down Expand Up @@ -125,6 +126,7 @@
3CA9DD6B20F6EF04000EB47F /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = "<group>"; };
3CA9DD6D20F6EF2D000EB47F /* Global Functions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Global Functions.swift"; sourceTree = "<group>"; };
3CA9DD6F20F6EF4F000EB47F /* Global Variables.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Global Variables.swift"; sourceTree = "<group>"; };
3CABE2E22137A04F00F46100 /* ShareButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareButton.swift; sourceTree = "<group>"; };
3CB1B07B20FADB8F004EB7CF /* FriendDetail.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FriendDetail.swift; sourceTree = "<group>"; };
3CB48E9220F6EFD000019DC9 /* Keys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Keys.swift; sourceTree = "<group>"; };
3CB48E9520F6F02100019DC9 /* API.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = API.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -403,6 +405,7 @@
3CEAA10220F99D61005D7D82 /* PasscodeButton.swift */,
3CEAA10420F99D73005D7D82 /* PasscodeIndicator.swift */,
3CE32CA22130F92400071891 /* MessageView.swift */,
3CABE2E22137A04F00F46100 /* ShareButton.swift */,
);
path = "Custom Components";
sourceTree = "<group>";
Expand Down Expand Up @@ -588,6 +591,7 @@
3CB48E9620F6F02100019DC9 /* API.swift in Sources */,
3C96B8D620F7CB5700DDF924 /* HomeCell.swift in Sources */,
3C81E51A20F93AF200693677 /* SettingsCell.swift in Sources */,
3CABE2E32137A04F00F46100 /* ShareButton.swift in Sources */,
3CEAA0F820F99336005D7D82 /* QRScanner.swift in Sources */,
3C03F5C820F7EFE0002697BB /* Detail.swift in Sources */,
3CEAA10520F99D73005D7D82 /* PasscodeIndicator.swift in Sources */,
Expand Down
155 changes: 135 additions & 20 deletions ios App/Dracker/Application Flow/QR/QRCode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,68 +2,142 @@ import UIKit
import Firebase

class QRCode: UIViewController {
var current_brightness: CGFloat?
let image = UIImageView()
let base_padding: CGFloat = 60
let image_padding: CGFloat = 80
let profile_size: CGFloat = 70
let top_padding: CGFloat = 90

lazy var share_button: ShareButton = {
let button = ShareButton(image: #imageLiteral(resourceName: "share"), text: "Share my code", selected_color: .black, unselected_color: .text_color, bacground_selected: .share_button_highlighted_light)
button.addTarget(self, action: #selector(share_image), for: .touchUpInside)
return button
}()

lazy var save_button: ShareButton = {
let button = ShareButton(image: #imageLiteral(resourceName: "download"), text: "Save to photos", selected_color: .black, unselected_color: .text_color, bacground_selected: .share_button_highlighted_light)
button.addTarget(self, action: #selector(save_image), for: .touchUpInside)
return button
}()


let image: UIImageView = {
let image = UIImageView()
image.clipsToBounds = true
image.layer.borderWidth = 2.5
image.layer.borderColor = UIColor.qr_back.cgColor
return image
}()

lazy var profile_image: UIImageView = {
let image = UIImageView()
image.clipsToBounds = true
image.layer.borderWidth = 2
image.layer.borderColor = UIColor.white.cgColor
image.layer.cornerRadius = profile_size/2
return image
}()

let navigation_title: UILabel = {
let title = UILabel()
title.textColor = .white
title.font = UIFont.boldSystemFont(ofSize: 20)
title.font = .systemFont(ofSize: 15)
title.text = "QR Code"
return title
}()

let base_view: UIView = {
let view = UIView()
view.backgroundColor = .white
view.layer.cornerRadius = 4.0
view.clipsToBounds = true
return view
}()

let name: UILabel = {
let label = UILabel()
label.font = UIFont(name: "Avenir-Book", size: 30)
label.font = UIFont(name: "HelveticaNeue-Bold", size: 20)
label.textAlignment = .center
label.textColor = .text_color
label.textColor = .black
return label
}()

override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
current_brightness = UIScreen.main.brightness
view.backgroundColor = .qr_back
authorize(completion: setup)
}

override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(true)
UIScreen.main.brightness = current_brightness!
}

fileprivate func setup_graphic() {
navigationItem.titleView = navigation_title
}

fileprivate func setup_code() {
view.addSubview(image)
let height = view.frame.width - 60.0
view.addConstraintsWithFormat(format: "H:|-30-[v0]-30-|", views: image)
view.addConstraintsWithFormat(format: "V:|-100-[v0(\(height))]-10-[v1(40)]", views: image, name)
base_view.addSubview(image)
let height = view.frame.width - (image_padding + base_padding)
base_view.addConstraintsWithFormat(format: "H:|-\(image_padding/2)-[v0]-\(image_padding/2)-|", views: image)
base_view.addConstraintsWithFormat(format: "V:[v0]-12-[v1(\(height))]-25-|", views: name, image)

}

fileprivate func setup_name() {
view.addSubview(name)
view.addConstraintsWithFormat(format: "H:|[v0]|", views: name)
base_view.addSubview(name)
base_view.addConstraintsWithFormat(format: "H:|[v0]|", views: name)
}

fileprivate func setup_profile() {
view.addSubview(profile_image)
view.center_X(item: profile_image)
profile_image.widthAnchor.constraint(equalToConstant: profile_size).isActive = true
profile_image.heightAnchor.constraint(equalToConstant: profile_size).isActive = true
let top = top_padding - profile_size/2
view.addConstraintsWithFormat(format: "V:|-\(top)-[v0]", views: profile_image)
let uid = UserDefaults.standard.object(forKey: "uid") as? String
profile_image.init_from_S3(key: uid!, bucket_name: .profiles)
}

fileprivate func setup_base() {
view.addSubview(base_view)
view.addConstraintsWithFormat(format: "H:|-\(base_padding/2)-[v0]-\(base_padding/2)-|", views: base_view)
view.addConstraintsWithFormat(format: "V:|-\(top_padding)-[v0]-170-|", views: base_view)
}

fileprivate func setup() {
setup_base()
setup_graphic()
setup_name()
setup_code()
setup_profile()
self.name.text = "@" + (UserDefaults.standard.object(forKey: "name") as! String)
let json = get_data().encrypt()
image.image = generate_QRCode(from: json!)
UIScreen.main.brightness = 1.0
setup_buttons()
}

fileprivate func setup_buttons() {

//MARK: Share Button
view.addSubview(share_button)
view.center_X(item: share_button)
share_button.widthAnchor.constraint(equalToConstant: 160).isActive = true

//MARK: Save Buttons
view.addSubview(save_button)
view.center_X(item: save_button)
save_button.widthAnchor.constraint(equalToConstant: 160).isActive = true
view.addConstraintsWithFormat(format: "V:[v0(30)]-10-[v1(30)]-40-|", views: save_button, share_button)
}

fileprivate func generate_QRCode(from string: String) -> UIImage? {
let data = string.data(using: String.Encoding.ascii)
if let filter = CIFilter(name: "CIQRCodeGenerator") {
guard let color_filter = CIFilter(name: "CIFalseColor") else { return nil }
filter.setValue(data, forKey: "inputMessage")
filter.setValue("H", forKey: "inputCorrectionLevel")
color_filter.setValue(filter.outputImage, forKey: "inputImage")
color_filter.setValue(CIColor(red: 1, green: 1, blue: 1), forKey: "inputColor1")
color_filter.setValue(CIColor(red: 1 - 226/255 , green: 1 - 233/255, blue: 1 - 237/255), forKey: "inputColor0")
let transform = CGAffineTransform(scaleX: 3, y: 3)
if let output = filter.outputImage?.transformed(by: transform) {
if let output = color_filter.outputImage?.transformed(by: transform) {
return UIImage(ciImage: output)
}
}
Expand All @@ -79,3 +153,44 @@ class QRCode: UIViewController {
return String(data: json!, encoding: .utf8)!
}
}

//MARK: Actions

extension QRCode {
@objc func share_image() {
let share_image = get_image()
let share_activity = UIActivityViewController(activityItems: [share_image], applicationActivities: [])
present(share_activity, animated: true, completion: nil)
}

fileprivate func get_image() -> UIImage{
let size = self.image.frame.width
UIGraphicsBeginImageContextWithOptions(CGSize(width: size, height: size), false, 0)
self.image.drawHierarchy(in: CGRect(x: 0, y: 0, width: size, height: size), afterScreenUpdates: true)
let image = UIGraphicsGetImageFromCurrentImageContext()
return image!
}

@objc fileprivate func save_image() {
UIImageWriteToSavedPhotosAlbum(self.get_image(), self, #selector(self.image_saved(_:didFinishSavingWithError:contextInfo:)), nil)
}

@objc func image_saved(_ image: UIImage, didFinishSavingWithError error: NSError?, contextInfo: UnsafeRawPointer) {
if error == nil {
let shift = UIApplication.shared.statusBarFrame.height + (navigationController?.navigationBar.frame.height)!
let message = MessageView(superView_frame: view.frame, center: CGPoint(x: view.center.x, y: view.center.y - shift), text: "QR Code saved to photos", image: #imageLiteral(resourceName: "saved"))
view.addSubview(message)
message.alpha = 0.0
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
message.alpha = 1.0
}, completion: nil)
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
UIView.animate(withDuration: 0.5, delay: 1, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
message.alpha = 0.0
}, completion: { (_) in
message.removeFromSuperview()
})
}
}
}
}
51 changes: 51 additions & 0 deletions ios App/Dracker/Application Flow/QR/QRScanner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ class QRScanner: UIViewController {
var preview: AVCaptureVideoPreviewLayer!
let kSoundCode_Tink = 1057

lazy var picker: UIImagePickerController = {
let image_picker = UIImagePickerController()
image_picker.delegate = self
image_picker.navigationBar.titleTextAttributes = [.foregroundColor: UIColor.white]
return image_picker
}()

let navigation_title: UILabel = {
let title = UILabel()
title.textColor = .white
Expand All @@ -15,6 +22,12 @@ class QRScanner: UIViewController {
return title
}()

lazy var scan_photo_button: ShareButton = {
let button = ShareButton(image:#imageLiteral(resourceName: "no-image.png") , text: "Scan from photos", selected_color: .white, unselected_color: .white, bacground_selected: .share_button_highlighted_dark)
button.addTarget(self, action: #selector(select_qr_image), for: .touchUpInside)
return button
}()

let box: UIView = {
let view = UIView()
view.backgroundColor = .clear
Expand Down Expand Up @@ -77,6 +90,12 @@ class QRScanner: UIViewController {
box.frame = CGRect(x: padding, y: y_axis, width: width, height: width)
view.bringSubview(toFront: box)
box.alpha = 0.5

//Setup Button
view.addSubview(scan_photo_button)
view.center_X(item: scan_photo_button)
scan_photo_button.widthAnchor.constraint(equalToConstant: 190).isActive = true
view.addConstraintsWithFormat(format: "V:[v0(30)]-40-|", views: scan_photo_button)
}

fileprivate func convert_to_dictionary(result: String) -> [String : Any]? {
Expand Down Expand Up @@ -129,6 +148,11 @@ extension QRScanner: AVCaptureMetadataOutputObjectsDelegate {
}
let data = convert_to_dictionary(result: decrypted!)
if data == nil { return }
if (data!["uid"] as? String) ==
(UserDefaults.standard.object(forKey: "uid") as? String) {
present_alert_error(message: .self_qr, target: self)
return
}
//Setup Controller to transition to and the values
let controller = AddTransaction()
controller.dahsboard = home?.Homecomponent
Expand All @@ -139,3 +163,30 @@ extension QRScanner: AVCaptureMetadataOutputObjectsDelegate {
navigationController?.pushViewController(controller, animated: true)
}
}

//MARK: Library photo selection Delegates
extension QRScanner: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
let detector:CIDetector=CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy:CIDetectorAccuracyHigh])!
let reconstructed_image:CIImage=CIImage(image:image)!
var data=""
let features = detector.features(in: reconstructed_image)
for feature in features as! [CIQRCodeFeature] {
data += feature.messageString!
}
scan_succeeded(code: data)
} else { return }
dismiss(animated: true, completion: nil)
}

func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
dismiss(animated: true, completion: nil)
}

@objc fileprivate func select_qr_image() {
picker.allowsEditing = false
picker.sourceType = .photoLibrary
present(picker, animated: true, completion: nil)
}
}
4 changes: 2 additions & 2 deletions ios App/Dracker/Application Flow/Transaction/Detail.swift
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ class Detail: UIViewController {

fileprivate func setup_components() {
navigation_title.text = data?.name
description_view.text = data?.description
description_view.text = "\"" + (data?.description)! + "\""
let time = (data?.time.as_date(format: .full))!
let amount = (Double((data?.amount)!))!

Expand Down Expand Up @@ -330,7 +330,7 @@ extension Detail {

@objc func image_saved(_ image: UIImage, didFinishSavingWithError error: NSError?, contextInfo: UnsafeRawPointer) {
if error == nil {
let message = MessageView(superView_frame: view.frame, center: transaction_image.center, text: "Image Saved to Camera Roll", image: #imageLiteral(resourceName: "saved"))
let message = MessageView(superView_frame: view.frame, center: transaction_image.center, text: "Image saved to Camera roll", image: #imageLiteral(resourceName: "saved"))
view.addSubview(message)
message.alpha = 0.0
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
Expand Down
21 changes: 21 additions & 0 deletions ios App/Dracker/Assets.xcassets/download.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "download.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 21 additions & 0 deletions ios App/Dracker/Assets.xcassets/share.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "share.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions ios App/Dracker/Configrations/Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ extension UIColor {
static let settle_action = debt
static let delete_action = credit
static let bank_back = UIColor(r: 247, g: 247, b: 247)
static let qr_back = UIColor(r: 226, g: 233, b: 237)
static let share_button_highlighted_light = UIColor(r: 222, g: 227, b: 231)
static let share_button_highlighted_dark = UIColor(r: 84, g: 81, b: 71).withAlphaComponent(0.30)
}

//MARK: Visual Constraints
Expand Down
Loading

0 comments on commit 271e8dc

Please sign in to comment.