DetailViewButtonsViewController.swift 9.68 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
//
//  DetailViewButtonsViewController.swift
//  WhatsOpen
//
//  Created by Zach Knox on 4/16/18.
//  Copyright © 2018 SRCT. All rights reserved.
//

import UIKit
import MapKit
11
import WhatsOpenKit
Zach Knox's avatar
Zach Knox committed
12
13
import Intents
import IntentsUI
14

Zach Knox's avatar
Zach Knox committed
15
16
class DetailViewButtonsViewController: UIViewController, INUIAddVoiceShortcutViewControllerDelegate {
	
17
18

	@IBOutlet var facilityDetailView: UIView!
Zach Knox's avatar
Zach Knox committed
19
20
    private var infoHUD: HUDViewController!
	private var isInfoHUDDisplayed = false
21
    
Zach Knox's avatar
Zach Knox committed
22
	var detailViewController: WOPFacilityDetailViewController?
23
	var facility: WOPFacility!
24
25
26
	
	@IBOutlet var favoritesButton: UIButton!
	@IBOutlet var shareButton: UIButton!
Zach Knox's avatar
Zach Knox committed
27
	@IBOutlet var addToSiriButton: UIButton!
28
	
Zach Knox's avatar
Zach Knox committed
29
30
	let activity = NSUserActivity(activityType: "facility")

Zach Knox's avatar
Zach Knox committed
31
	let feedback = UISelectionFeedbackGenerator()
32
33
34
35
36
37
38
	/**
	Favorites button touch handler
	
	Adds a facility to favorites if it isn't a favorite,
	removes from favorites if it is a favorite.
	*/
	@IBAction func setFavButton(_ sender: Any) {
Zach Knox's avatar
Zach Knox committed
39
40
		feedback.selectionChanged()

41
42
		if(WOPUtilities.isFavoriteFacility(facility)) { // if the facility is a favorite
			_ = WOPUtilities.removeFavoriteFacility(facility) // remove it from favorites
Zach Knox's avatar
Zach Knox committed
43
			
Zach Knox's avatar
Zach Knox committed
44
45
46
47
48
49
50
51
			if !isInfoHUDDisplayed {
				isInfoHUDDisplayed = true
				loadChild("Removed from Favorites", image: UIImage(named: "empty_heart_big"))
				
				DispatchQueue.main.asyncAfter(deadline: .now() + 1.1) { [weak self] in
					self?.unloadChild()
					self?.isInfoHUDDisplayed = false
				}
Zach Knox's avatar
Zach Knox committed
52
			}
Zach Knox's avatar
Zach Knox committed
53
			
54
55
		}
		else { // else add it to favorites
56
			_ = WOPUtilities.addFavoriteFacility(facility)
Zach Knox's avatar
Zach Knox committed
57
			
Zach Knox's avatar
Zach Knox committed
58
59
60
61
			if !isInfoHUDDisplayed {
				isInfoHUDDisplayed = true
				loadChild("Added to Favorites", image: UIImage(named: "filled_heart_big"))
				
Zach Knox's avatar
1.1    
Zach Knox committed
62
				DispatchQueue.main.asyncAfter(deadline: .now() + 1.1) { [weak self] in
Zach Knox's avatar
Zach Knox committed
63
64
65
66
67
					self?.unloadChild()
					self?.isInfoHUDDisplayed = false
				}
			}
			
Eyad Hasan's avatar
Eyad Hasan committed
68
            
69
		}
Zach Knox's avatar
Zach Knox committed
70
		setFavoriteButtonText()		
71
	}
72
    
Zach Knox's avatar
Zach Knox committed
73
74
	func loadChild(_ title: String, image: UIImage?) {
		DispatchQueue.main.async {
Zach Knox's avatar
Zach Knox committed
75
76
77
78
			self.addSubview(self.infoHUD.view, toView: (self.detailViewController?.view)!)
			self.infoHUD.view.alpha = 0
			self.detailViewController!.addChild(self.infoHUD)
			self.infoHUD.didMove(toParent: self.detailViewController)
Zach Knox's avatar
Zach Knox committed
79
			UIView.animate(withDuration: 0.35, animations: {
Zach Knox's avatar
Zach Knox committed
80
				self.infoHUD.view.alpha = 1
Zach Knox's avatar
Zach Knox committed
81
82
			})
			
Zach Knox's avatar
Zach Knox committed
83
84
			self.infoHUD.label.text = title
			self.infoHUD.image.image = image
Zach Knox's avatar
Zach Knox committed
85
		}
Eyad Hasan's avatar
Eyad Hasan committed
86
87
88
    }
    
    func unloadChild() {
Zach Knox's avatar
Zach Knox committed
89
90
		DispatchQueue.main.async {
			UIView.animate(withDuration: 0.35, animations: {
Zach Knox's avatar
Zach Knox committed
91
				self.infoHUD.view.alpha = 0
Zach Knox's avatar
Zach Knox committed
92
			}, completion: { (completed) in
Zach Knox's avatar
Zach Knox committed
93
94
95
				self.infoHUD.willMove(toParent: nil)
				self.infoHUD.removeFromParent()
				self.infoHUD.view.removeFromSuperview()
Zach Knox's avatar
Zach Knox committed
96
97
			})
		}
Eyad Hasan's avatar
Eyad Hasan committed
98
99
    }
    
100
	func getDirections(_ sender: Any) {
Zach Knox's avatar
Zach Knox committed
101
		let appToUse = WOPDatabaseController.getDefaults().value(forKey: "mapsApp") as? String
102
103
104
		
		if appToUse == "Google Maps" && UIApplication.shared.canOpenURL(URL(string:"comgooglemaps://")!) {
			if let url = URL(string: "comgooglemaps://?q=\((facility.facilityLocation?.coordinates?.coords?.last)!)),\((facility.facilityLocation?.coordinates?.coords?.first)!)") {
Zach Knox's avatar
Zach Knox committed
105
				UIApplication.shared.open(url, options: convertToUIApplicationOpenExternalURLOptionsKeyDictionary([:]), completionHandler: nil)
106
107
108
109
			}
		}
		else if appToUse == "Waze" && UIApplication.shared.canOpenURL(URL(string:"comgooglemaps://")!) {
			if let url = URL(string: "https://waze.com/ul?ll=\((facility.facilityLocation?.coordinates?.coords?.last)!)),\((facility.facilityLocation?.coordinates?.coords?.first)!))") {
Zach Knox's avatar
Zach Knox committed
110
				UIApplication.shared.open(url, options: convertToUIApplicationOpenExternalURLOptionsKeyDictionary([:]), completionHandler: nil)
111
112
113
114
115
116
			}
		}
		else {
			let regionDistance:CLLocationDistance = 100
			let coordinates = CLLocationCoordinate2DMake((facility.facilityLocation?.coordinates?.coords?.last)!, (facility.facilityLocation?.coordinates?.coords?.first)!)
			dump(coordinates)
Zach Knox's avatar
Zach Knox committed
117
			let regionSpan = MKCoordinateRegion.init(center: coordinates, latitudinalMeters: regionDistance, longitudinalMeters: regionDistance)
118
119
120
121
122
123
124
125
126
127
128
129
130
			let options = [
				MKLaunchOptionsMapCenterKey: NSValue(mkCoordinate: regionSpan.center),
				MKLaunchOptionsMapSpanKey: NSValue(mkCoordinateSpan: regionSpan.span)
			]
			let placemark = MKPlacemark(coordinate: coordinates, addressDictionary: nil)
			let mapItem = MKMapItem(placemark: placemark)
			mapItem.name = facility.facilityName
			mapItem.openInMaps(launchOptions: options)
		}
	}
	
	
	@IBAction func shareFacility(_ sender: Any) {
Zach Knox's avatar
Zach Knox committed
131
132
		feedback.selectionChanged()

133
		let str = "\(facility.facilityName) is \(WOPUtilities.openOrClosedUntil(facility)!.lowercased())"
134
135
		// TODO in future: add URL based on facility once web supports it
		let shareSheet = UIActivityViewController(activityItems: [str, (URL(string: "https://whatsopen.gmu.edu") ?? nil), facility], applicationActivities: [ViewInMapsActionActivity()])
136
137
138
139
140
141
142
143
		shareSheet.excludedActivityTypes = [.print, .openInIBooks, .addToReadingList] // Sorry you can't print a Facility
		present(shareSheet, animated: true, completion: nil)
	}
	
	/**
	Change the favorite button text depending on if the facility is a favorite
	*/
	func setFavoriteButtonText() {
144
		if(WOPUtilities.isFavoriteFacility(facility)) {
145
146
147
			favoritesButton.accessibilityLabel = "Remove from Favorites"
			favoritesButton.titleLabel?.text = ""
			favoritesButton.setImage(UIImage(named: "heart_filled"), for: .normal)
148
149
		}
		else {
150
151
152
			favoritesButton.accessibilityLabel = "Add to Favorites"
			favoritesButton.titleLabel?.text = ""
			favoritesButton.setImage(UIImage(named: "heart_empty"), for: .normal)
153
154
155
156
157
158
159
		}
	}
	
	override func viewDidLoad() {
		// Dealing with container views and subviews
		// https://spin.atomicobject.com/2015/10/13/switching-child-view-controllers-ios-auto-layout/
		self.detailViewController!.view.translatesAutoresizingMaskIntoConstraints = false
Zach Knox's avatar
Zach Knox committed
160
		self.addChild(self.detailViewController!)
161
162
163
164
165
166
167
168
169
170
171
172
173
		self.addSubview(self.detailViewController!.view, toView: self.facilityDetailView)
        super.viewDidLoad()

		setFavoriteButtonText()
		favoritesButton.tintColor = UIColor.white
		favoritesButton.backgroundColor = UIColor(red:0.00, green:0.40, blue:0.20, alpha:1.0)
		favoritesButton.layer.cornerRadius = 10
		
		shareButton.tintColor = UIColor.white
		shareButton.backgroundColor = UIColor.orange
		shareButton.layer.cornerRadius = 10
		shareButton.setImage(#imageLiteral(resourceName: "shareIcon"), for: .normal)
		shareButton.setTitle("", for: .normal)
174
		shareButton.accessibilityLabel = "Share"
175

Zach Knox's avatar
Zach Knox committed
176
		setActivityUp()
177
		
178
179
		addToSiriButton.tintColor = UIColor.white
		addToSiriButton.backgroundColor = UIColor.black
180
		addToSiriButton.layer.cornerRadius = 10
181
		addToSiriButton.accessibilityLabel = "Add to Siri"
182
		
Zach Knox's avatar
Zach Knox committed
183
184
		let interaction = INInteraction(intent: facility.createIntent(), response: WOPViewFacilityIntentUtils.getIntentResponse(facility, userActivity: activity))
		interaction.donate(completion: nil)
Zach Knox's avatar
Zach Knox committed
185
		
Zach Knox's avatar
Zach Knox committed
186
		infoHUD = storyboard?.instantiateViewController(withIdentifier: "HUD") as! HUDViewController
187
        // Do any additional setup after loading the view.
188
        // yah yah, yah yAH
189
190
    }
	
Zach Knox's avatar
Zach Knox committed
191
192
193
	func setActivityUp() {
		activity.isEligibleForHandoff = true
		activity.isEligibleForSearch = true
194
		activity.addUserInfoEntries(from: ["facility": facility.slug])
Zach Knox's avatar
Zach Knox committed
195
196
197
198
199
200
201
202
203
		activity.title = facility.facilityName
		activity.keywords = Set<String>(arrayLiteral: facility.facilityName, facility.facilityLocation!.building)
		//activity.keywords = [facility.facilityName, facility.facilityLocation?.building]
		activity.webpageURL = URL(string: "https://whatsopen.gmu.edu/")
		
		activity.becomeCurrent()
	}
	
	@IBAction func addToSiri(_ sender: Any) {
Zach Knox's avatar
Zach Knox committed
204
		feedback.selectionChanged()
Zach Knox's avatar
Zach Knox committed
205
		let intent = facility.createIntent()
206
		let shortcuts = INVoiceShortcutCenter.shared
Zach Knox's avatar
Zach Knox committed
207
		if let shortcut = INShortcut(intent: intent) {
208
			let viewController = INUIAddVoiceShortcutViewController(shortcut: shortcut)
Zach Knox's avatar
Zach Knox committed
209
210
211
212
213
214
			viewController.modalPresentationStyle = .formSheet
			viewController.delegate = self // Object conforming to `INUIAddVoiceShortcutViewControllerDelegate`.
			present(viewController, animated: true, completion: nil)
		}
	}

215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
	func addSubview(_ subView: UIView, toView parentView: UIView) {
		parentView.addSubview(subView)
		
		var viewBindingsDict = [String: AnyObject]()
		viewBindingsDict["subView"] = subView
		parentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[subView]|",
																 options: [], metrics: nil, views: viewBindingsDict))
		parentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[subView]|",
																 options: [], metrics: nil, views: viewBindingsDict))
	}

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
Zach Knox's avatar
Zach Knox committed
230
231
232
233
234
235
236
237
238
239
	
	// MARK: INUIAdd... Delegate
	
	func addVoiceShortcutViewController(_ controller: INUIAddVoiceShortcutViewController, didFinishWith voiceShortcut: INVoiceShortcut?, error: Error?) {
		controller.dismiss(animated: true, completion: nil)
	}
	
	func addVoiceShortcutViewControllerDidCancel(_ controller: INUIAddVoiceShortcutViewController) {
		controller.dismiss(animated: true, completion: nil)
	}
240
241
242
243
244
245
246
247
248
249

    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using segue.destinationViewController.
        // Pass the selected object to the new view controller.
    }
    */
250
251
    
    
252
253

}
Zach Knox's avatar
Zach Knox committed
254
255
256
257
258

// Helper function inserted by Swift 4.2 migrator.
fileprivate func convertToUIApplicationOpenExternalURLOptionsKeyDictionary(_ input: [String: Any]) -> [UIApplication.OpenExternalURLOptionsKey: Any] {
	return Dictionary(uniqueKeysWithValues: input.map { key, value in (UIApplication.OpenExternalURLOptionsKey(rawValue: key), value)})
}