mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-27 22:37:15 +00:00
More needed refactoring steps
This commit is contained in:
1 parent
00509c120b
commit
0bc7e2b115
28 files changed
+635
-432
No files matched your search
@@ -295,7 +295,7 @@
|
||||
7F8B8D411A373B0200C34B88 /* SpeedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F8B8D401A373B0200C34B88 /* SpeedViewController.swift */; };
|
||||
7F8B8D431A373D4400C34B88 /* CourseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F8B8D421A373D4400C34B88 /* CourseViewController.swift */; };
|
||||
7F8CC2081A10D47A00C56D7F /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F8CC2071A10D47A00C56D7F /* SettingsViewController.swift */; };
|
||||
7F950A911A35E967003C8C5C /* LeaderBoardViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F950A901A35E967003C8C5C /* LeaderBoardViewController.swift */; };
|
||||
7F950A911A35E967003C8C5C /* LeaderboardViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F950A901A35E967003C8C5C /* LeaderboardViewController.swift */; };
|
||||
7F99DE3C1A126554009B3619 /* RegattaViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F99DE3B1A126554009B3619 /* RegattaViewController.swift */; };
|
||||
7FA2220B1A25E55400FD364B /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7F83F17519F1574700C53328 /* CoreLocation.framework */; };
|
||||
7FA6551A19F6661900A1B92D /* CoreDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FA6551919F6661900A1B92D /* CoreDataManager.swift */; };
|
||||
@@ -312,16 +312,16 @@
|
||||
C852BAAB1CF736680093B0C5 /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = C852BAAA1CF736680093B0C5 /* Preferences.swift */; };
|
||||
C8603D511C52892A002B2F28 /* Acknowledgements.markdown in Resources */ = {isa = PBXBuildFile; fileRef = C8603D491C528832002B2F28 /* Acknowledgements.markdown */; };
|
||||
C8739D8E1D23D53C00A89F3C /* SendGPSFixesController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739D8D1D23D53C00A89F3C /* SendGPSFixesController.swift */; };
|
||||
C8739DAF1D2539A900A89F3C /* CheckIn+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739DA51D2539A900A89F3C /* CheckIn+CoreDataProperties.swift */; };
|
||||
C8739DB01D2539A900A89F3C /* CheckIn.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739DA61D2539A900A89F3C /* CheckIn.swift */; };
|
||||
C8739DB31D2539A900A89F3C /* Event+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739DA91D2539A900A89F3C /* Event+CoreDataProperties.swift */; };
|
||||
C8739DB41D2539A900A89F3C /* Event.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739DAA1D2539A900A89F3C /* Event.swift */; };
|
||||
C8739DB51D2539A900A89F3C /* Competitor+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739DAB1D2539A900A89F3C /* Competitor+CoreDataProperties.swift */; };
|
||||
C8739DB61D2539A900A89F3C /* Competitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739DAC1D2539A900A89F3C /* Competitor.swift */; };
|
||||
C8739DB71D2539A900A89F3C /* GPSFix+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739DAD1D2539A900A89F3C /* GPSFix+CoreDataProperties.swift */; };
|
||||
C8739DB81D2539A900A89F3C /* GPSFix.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739DAE1D2539A900A89F3C /* GPSFix.swift */; };
|
||||
C8739DBB1D25409700A89F3C /* Leaderboard+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739DB91D25409700A89F3C /* Leaderboard+CoreDataProperties.swift */; };
|
||||
C8739DBC1D25409700A89F3C /* Leaderboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739DBA1D25409700A89F3C /* Leaderboard.swift */; };
|
||||
C8739E041D2AA2A500A89F3C /* Regatta+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739DFA1D2AA2A500A89F3C /* Regatta+CoreDataProperties.swift */; };
|
||||
C8739E051D2AA2A500A89F3C /* Regatta.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739DFB1D2AA2A500A89F3C /* Regatta.swift */; };
|
||||
C8739E061D2AA2A500A89F3C /* GPSFix+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739DFC1D2AA2A500A89F3C /* GPSFix+CoreDataProperties.swift */; };
|
||||
C8739E071D2AA2A500A89F3C /* GPSFix.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739DFD1D2AA2A500A89F3C /* GPSFix.swift */; };
|
||||
C8739E081D2AA2A500A89F3C /* Leaderboard+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739DFE1D2AA2A500A89F3C /* Leaderboard+CoreDataProperties.swift */; };
|
||||
C8739E091D2AA2A500A89F3C /* Leaderboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739DFF1D2AA2A500A89F3C /* Leaderboard.swift */; };
|
||||
C8739E0A1D2AA2A500A89F3C /* Competitor+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739E001D2AA2A500A89F3C /* Competitor+CoreDataProperties.swift */; };
|
||||
C8739E0B1D2AA2A500A89F3C /* Competitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739E011D2AA2A500A89F3C /* Competitor.swift */; };
|
||||
C8739E0C1D2AA2A500A89F3C /* Event+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739E021D2AA2A500A89F3C /* Event+CoreDataProperties.swift */; };
|
||||
C8739E0D1D2AA2A500A89F3C /* Event.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8739E031D2AA2A500A89F3C /* Event.swift */; };
|
||||
C89C5FC51D06A289002AAAD2 /* GradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C89C5FC41D06A289002AAAD2 /* GradientView.swift */; };
|
||||
C89C5FCA1D06CECD002AAAD2 /* StatusTrackingTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C89C5FC91D06CECD002AAAD2 /* StatusTrackingTableViewCell.swift */; };
|
||||
C89C5FCC1D06CF0C002AAAD2 /* GPSAccuracyTrackingTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C89C5FCB1D06CF0C002AAAD2 /* GPSAccuracyTrackingTableViewCell.swift */; };
|
||||
@@ -683,7 +683,7 @@
|
||||
7F8B8D401A373B0200C34B88 /* SpeedViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SpeedViewController.swift; sourceTree = "<group>"; };
|
||||
7F8B8D421A373D4400C34B88 /* CourseViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CourseViewController.swift; sourceTree = "<group>"; };
|
||||
7F8CC2071A10D47A00C56D7F /* SettingsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = "<group>"; };
|
||||
7F950A901A35E967003C8C5C /* LeaderBoardViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LeaderBoardViewController.swift; sourceTree = "<group>"; };
|
||||
7F950A901A35E967003C8C5C /* LeaderboardViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LeaderboardViewController.swift; sourceTree = "<group>"; };
|
||||
7F99DE3B1A126554009B3619 /* RegattaViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RegattaViewController.swift; sourceTree = "<group>"; };
|
||||
7FA6551919F6661900A1B92D /* CoreDataManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = CoreDataManager.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
|
||||
7FAFA7941A126B5700D230F1 /* AboutViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AboutViewController.swift; sourceTree = "<group>"; };
|
||||
@@ -702,16 +702,16 @@
|
||||
C8739D891D21276B00A89F3C /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Main.strings; sourceTree = "<group>"; };
|
||||
C8739D8D1D23D53C00A89F3C /* SendGPSFixesController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SendGPSFixesController.swift; sourceTree = "<group>"; };
|
||||
C8739D9A1D25317100A89F3C /* CoreData 2.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "CoreData 2.xcdatamodel"; sourceTree = "<group>"; };
|
||||
C8739DA51D2539A900A89F3C /* CheckIn+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CheckIn+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
C8739DA61D2539A900A89F3C /* CheckIn.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckIn.swift; sourceTree = "<group>"; };
|
||||
C8739DA91D2539A900A89F3C /* Event+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Event+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
C8739DAA1D2539A900A89F3C /* Event.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Event.swift; sourceTree = "<group>"; };
|
||||
C8739DAB1D2539A900A89F3C /* Competitor+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Competitor+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
C8739DAC1D2539A900A89F3C /* Competitor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Competitor.swift; sourceTree = "<group>"; };
|
||||
C8739DAD1D2539A900A89F3C /* GPSFix+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GPSFix+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
C8739DAE1D2539A900A89F3C /* GPSFix.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GPSFix.swift; sourceTree = "<group>"; };
|
||||
C8739DB91D25409700A89F3C /* Leaderboard+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Leaderboard+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
C8739DBA1D25409700A89F3C /* Leaderboard.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Leaderboard.swift; sourceTree = "<group>"; };
|
||||
C8739DFA1D2AA2A500A89F3C /* Regatta+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Regatta+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
C8739DFB1D2AA2A500A89F3C /* Regatta.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Regatta.swift; sourceTree = "<group>"; };
|
||||
C8739DFC1D2AA2A500A89F3C /* GPSFix+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GPSFix+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
C8739DFD1D2AA2A500A89F3C /* GPSFix.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GPSFix.swift; sourceTree = "<group>"; };
|
||||
C8739DFE1D2AA2A500A89F3C /* Leaderboard+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Leaderboard+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
C8739DFF1D2AA2A500A89F3C /* Leaderboard.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Leaderboard.swift; sourceTree = "<group>"; };
|
||||
C8739E001D2AA2A500A89F3C /* Competitor+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Competitor+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
C8739E011D2AA2A500A89F3C /* Competitor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Competitor.swift; sourceTree = "<group>"; };
|
||||
C8739E021D2AA2A500A89F3C /* Event+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Event+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
C8739E031D2AA2A500A89F3C /* Event.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Event.swift; sourceTree = "<group>"; };
|
||||
C89C5FC41D06A289002AAAD2 /* GradientView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GradientView.swift; sourceTree = "<group>"; };
|
||||
C89C5FC91D06CECD002AAAD2 /* StatusTrackingTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatusTrackingTableViewCell.swift; sourceTree = "<group>"; };
|
||||
C89C5FCB1D06CF0C002AAAD2 /* GPSAccuracyTrackingTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GPSAccuracyTrackingTableViewCell.swift; sourceTree = "<group>"; };
|
||||
@@ -763,16 +763,16 @@
|
||||
children = (
|
||||
7FA6551919F6661900A1B92D /* CoreDataManager.swift */,
|
||||
7F44095919F65B5B0021BF22 /* CoreData.xcdatamodeld */,
|
||||
C8739DA51D2539A900A89F3C /* CheckIn+CoreDataProperties.swift */,
|
||||
C8739DA61D2539A900A89F3C /* CheckIn.swift */,
|
||||
C8739DA91D2539A900A89F3C /* Event+CoreDataProperties.swift */,
|
||||
C8739DAA1D2539A900A89F3C /* Event.swift */,
|
||||
C8739DAB1D2539A900A89F3C /* Competitor+CoreDataProperties.swift */,
|
||||
C8739DAC1D2539A900A89F3C /* Competitor.swift */,
|
||||
C8739DAD1D2539A900A89F3C /* GPSFix+CoreDataProperties.swift */,
|
||||
C8739DAE1D2539A900A89F3C /* GPSFix.swift */,
|
||||
C8739DB91D25409700A89F3C /* Leaderboard+CoreDataProperties.swift */,
|
||||
C8739DBA1D25409700A89F3C /* Leaderboard.swift */,
|
||||
C8739DFA1D2AA2A500A89F3C /* Regatta+CoreDataProperties.swift */,
|
||||
C8739DFB1D2AA2A500A89F3C /* Regatta.swift */,
|
||||
C8739DFC1D2AA2A500A89F3C /* GPSFix+CoreDataProperties.swift */,
|
||||
C8739DFD1D2AA2A500A89F3C /* GPSFix.swift */,
|
||||
C8739DFE1D2AA2A500A89F3C /* Leaderboard+CoreDataProperties.swift */,
|
||||
C8739DFF1D2AA2A500A89F3C /* Leaderboard.swift */,
|
||||
C8739E001D2AA2A500A89F3C /* Competitor+CoreDataProperties.swift */,
|
||||
C8739E011D2AA2A500A89F3C /* Competitor.swift */,
|
||||
C8739E021D2AA2A500A89F3C /* Event+CoreDataProperties.swift */,
|
||||
C8739E031D2AA2A500A89F3C /* Event.swift */,
|
||||
);
|
||||
name = CoreData;
|
||||
sourceTree = "<group>";
|
||||
@@ -1267,7 +1267,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7F99DE3B1A126554009B3619 /* RegattaViewController.swift */,
|
||||
7F950A901A35E967003C8C5C /* LeaderBoardViewController.swift */,
|
||||
7F950A901A35E967003C8C5C /* LeaderboardViewController.swift */,
|
||||
C89C5FC61D06CE62002AAAD2 /* Tracking */,
|
||||
);
|
||||
name = Regatta;
|
||||
@@ -1845,16 +1845,16 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C8739DB61D2539A900A89F3C /* Competitor.swift in Sources */,
|
||||
7F1875B31A10F1B800C25BE0 /* TrackingViewController.swift in Sources */,
|
||||
C8739E081D2AA2A500A89F3C /* Leaderboard+CoreDataProperties.swift in Sources */,
|
||||
7F83F15819F154F000C53328 /* HomeViewController.swift in Sources */,
|
||||
C8739DAF1D2539A900A89F3C /* CheckIn+CoreDataProperties.swift in Sources */,
|
||||
7F8B8D431A373D4400C34B88 /* CourseViewController.swift in Sources */,
|
||||
C8739DB81D2539A900A89F3C /* GPSFix.swift in Sources */,
|
||||
7FAFA7951A126B5700D230F1 /* AboutViewController.swift in Sources */,
|
||||
C8739E0A1D2AA2A500A89F3C /* Competitor+CoreDataProperties.swift in Sources */,
|
||||
C8739E0C1D2AA2A500A89F3C /* Event+CoreDataProperties.swift in Sources */,
|
||||
C8739E071D2AA2A500A89F3C /* GPSFix.swift in Sources */,
|
||||
7F44095B19F65B5B0021BF22 /* CoreData.xcdatamodeld in Sources */,
|
||||
C89C5FD01D06CF46002AAAD2 /* ModeTrackingTableViewCell.swift in Sources */,
|
||||
C8739DB71D2539A900A89F3C /* GPSFix+CoreDataProperties.swift in Sources */,
|
||||
7F1B66F91A0CDCF600904A41 /* BatteryManager.swift in Sources */,
|
||||
7FA6551A19F6661900A1B92D /* CoreDataManager.swift in Sources */,
|
||||
C852BAA21CF5E1EA0093B0C5 /* RequestManager.swift in Sources */,
|
||||
@@ -1863,26 +1863,26 @@
|
||||
7F23F0881A1A3DEF00F03F1C /* CheckInController.swift in Sources */,
|
||||
7F2C605A19F160E400C32D93 /* LocationManager.swift in Sources */,
|
||||
C89C5FCC1D06CF0C002AAAD2 /* GPSAccuracyTrackingTableViewCell.swift in Sources */,
|
||||
C8739E041D2AA2A500A89F3C /* Regatta+CoreDataProperties.swift in Sources */,
|
||||
C89C5FCA1D06CECD002AAAD2 /* StatusTrackingTableViewCell.swift in Sources */,
|
||||
C8739E051D2AA2A500A89F3C /* Regatta.swift in Sources */,
|
||||
7F8B8D3F1A37356C00C34B88 /* TrackingPageViewController.swift in Sources */,
|
||||
7F99DE3C1A126554009B3619 /* RegattaViewController.swift in Sources */,
|
||||
7F8CC2081A10D47A00C56D7F /* SettingsViewController.swift in Sources */,
|
||||
C8739E0D1D2AA2A500A89F3C /* Event.swift in Sources */,
|
||||
7F8B8D411A373B0200C34B88 /* SpeedViewController.swift in Sources */,
|
||||
C8739DB51D2539A900A89F3C /* Competitor+CoreDataProperties.swift in Sources */,
|
||||
C8739DBB1D25409700A89F3C /* Leaderboard+CoreDataProperties.swift in Sources */,
|
||||
9E95C3D61C723AB30016632B /* Constants.swift in Sources */,
|
||||
C8739DB41D2539A900A89F3C /* Event.swift in Sources */,
|
||||
7FD9D3031A1236080058FEAD /* Extensions.swift in Sources */,
|
||||
C8739E091D2AA2A500A89F3C /* Leaderboard.swift in Sources */,
|
||||
C89C5FC51D06A289002AAAD2 /* GradientView.swift in Sources */,
|
||||
C8739DBC1D25409700A89F3C /* Leaderboard.swift in Sources */,
|
||||
C8739DB01D2539A900A89F3C /* CheckIn.swift in Sources */,
|
||||
C852BAAB1CF736680093B0C5 /* Preferences.swift in Sources */,
|
||||
C8739DB31D2539A900A89F3C /* Event+CoreDataProperties.swift in Sources */,
|
||||
7F0658FD19F7D6700077FF95 /* ScanViewController.swift in Sources */,
|
||||
C8739E061D2AA2A500A89F3C /* GPSFix+CoreDataProperties.swift in Sources */,
|
||||
7F193A8F1A39ACF500D71773 /* TimerViewController.swift in Sources */,
|
||||
7F83F15619F154F000C53328 /* AppDelegate.swift in Sources */,
|
||||
7F950A911A35E967003C8C5C /* LeaderBoardViewController.swift in Sources */,
|
||||
7F950A911A35E967003C8C5C /* LeaderboardViewController.swift in Sources */,
|
||||
C89C5FCE1D06CF26002AAAD2 /* CachedFixesTrackingTableViewCell.swift in Sources */,
|
||||
C8739E0B1D2AA2A500A89F3C /* Competitor.swift in Sources */,
|
||||
7F0658FF19F7EE910077FF95 /* CheckInData.swift in Sources */,
|
||||
7F193A911A39E54600D71773 /* GPSAccuracyView.swift in Sources */,
|
||||
);
|
||||
|
||||
@@ -36,7 +36,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
}
|
||||
|
||||
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {
|
||||
Preferences.lastCheckInURLString = urlStringForDeeplink(url)
|
||||
Preferences.newCheckInURL = urlStringForDeeplink(url)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -68,11 +68,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
private func setupNavigationBarApperance() {
|
||||
let tintColor = UIColor(hex: 0x009de0)
|
||||
let font = UIFont(name: "OpenSans-Bold", size: CGFloat(17.0)) ?? UIFont.systemFontOfSize(17.0)
|
||||
UINavigationBar.appearance().tintColor = tintColor
|
||||
UINavigationBar.appearance().titleTextAttributes =
|
||||
[NSForegroundColorAttributeName: tintColor,
|
||||
NSFontAttributeName: UIFont(name: "OpenSans-Bold", size: CGFloat(17.0))!
|
||||
]
|
||||
UINavigationBar.appearance().titleTextAttributes = [NSForegroundColorAttributeName: tintColor, NSFontAttributeName: font]
|
||||
}
|
||||
|
||||
private func setupPageControlApperance() {
|
||||
@@ -89,6 +87,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
// FIXME: - Two prefixes are not allowed
|
||||
// Deeplink needs another structure (if possible) because of allowed characters in URL
|
||||
// https:// -> http//
|
||||
|
||||
urlString = urlString.hasPrefix(appPrefix) ? urlString.substringFromIndex(appPrefix.endIndex) : urlString
|
||||
let httpPrefix : String = "http//"
|
||||
urlString = urlString.hasPrefix(httpPrefix) ? "http://" + urlString.substringFromIndex(httpPrefix.endIndex) : urlString
|
||||
|
||||
@@ -190,6 +190,9 @@
|
||||
<accessibility key="accessibilityConfiguration" label="You can find your QR code on your registration confirmation"/>
|
||||
<fontDescription key="fontDescription" name="OpenSans" family="Open Sans" pointSize="14"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="20" y="200" width="260" height="16.5"/>
|
||||
</variation>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
@@ -384,6 +387,9 @@
|
||||
<rect key="frame" x="526" y="8" width="54" height="22"/>
|
||||
<fontDescription key="fontDescription" name="OpenSans-Bold" family="Open Sans" pointSize="16"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="224.5" y="9.5" width="55.5" height="19"/>
|
||||
</variation>
|
||||
</label>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="DE.png" translatesAutoresizingMaskIntoConstraints="NO" id="szG-Mg-huO">
|
||||
<rect key="frame" x="494" y="7" width="24" height="24"/>
|
||||
@@ -391,11 +397,17 @@
|
||||
<constraint firstAttribute="width" constant="24" id="Ina-uK-atY"/>
|
||||
<constraint firstAttribute="height" constant="24" id="TVX-WF-dOi"/>
|
||||
</constraints>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="192.5" y="7" width="24" height="24"/>
|
||||
</variation>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Max Mustermann" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" preferredMaxLayoutWidth="0.0" translatesAutoresizingMaskIntoConstraints="NO" id="oJS-dM-2B6" userLabel="Name Label">
|
||||
<rect key="frame" x="20" y="8" width="142" height="22"/>
|
||||
<fontDescription key="fontDescription" name="OpenSans-Bold" family="Open Sans" pointSize="16"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="20" y="9.5" width="125.5" height="19"/>
|
||||
</variation>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="0.59999999999999998" colorSpace="calibratedRGB"/>
|
||||
@@ -468,6 +480,9 @@
|
||||
<color key="value" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="50" y="133.5" width="200" height="33"/>
|
||||
</variation>
|
||||
<connections>
|
||||
<action selector="teamImageAddButtonTapped:" destination="G3a-SV-Maf" eventType="touchUpInside" id="cs9-h3-kj2"/>
|
||||
</connections>
|
||||
@@ -533,12 +548,18 @@
|
||||
<rect key="frame" x="8" y="0.0" width="59" height="29"/>
|
||||
<fontDescription key="fontDescription" name="OpenSans-Semibold" family="Open Sans" pointSize="21"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="8" y="0.0" width="55.5" height="24.5"/>
|
||||
</variation>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Days" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="l8F-Sg-cUb" userLabel="Days Description Label">
|
||||
<rect key="frame" x="8" y="28" width="59" height="22"/>
|
||||
<fontDescription key="fontDescription" name="OpenSans" family="Open Sans" pointSize="16"/>
|
||||
<color key="textColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="8" y="31" width="55.5" height="19"/>
|
||||
</variation>
|
||||
</label>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="joW-cG-ai8" userLabel="Separator View">
|
||||
<rect key="frame" x="75" y="10" width="1" height="30"/>
|
||||
@@ -547,6 +568,9 @@
|
||||
<constraint firstAttribute="height" constant="30" id="Jj2-tX-SU9"/>
|
||||
<constraint firstAttribute="width" constant="1" id="sJJ-vK-Ocb"/>
|
||||
</constraints>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="71.5" y="10" width="1" height="30"/>
|
||||
</variation>
|
||||
</view>
|
||||
</subviews>
|
||||
<constraints>
|
||||
@@ -559,6 +583,9 @@
|
||||
<constraint firstItem="sGD-0U-P4b" firstAttribute="top" secondItem="pjH-rV-MGI" secondAttribute="top" id="row-df-nQb"/>
|
||||
<constraint firstAttribute="bottom" secondItem="l8F-Sg-cUb" secondAttribute="bottom" id="zUW-Uk-XQr"/>
|
||||
</constraints>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="0.0" y="0.0" width="73" height="50"/>
|
||||
</variation>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="5is-0I-Kv3" userLabel="Hours View">
|
||||
<rect key="frame" x="76" y="0.0" width="76.5" height="50"/>
|
||||
@@ -567,12 +594,18 @@
|
||||
<rect key="frame" x="8" y="0.0" width="60.5" height="29"/>
|
||||
<fontDescription key="fontDescription" name="OpenSans-Semibold" family="Open Sans" pointSize="21"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="8" y="0.0" width="57" height="24.5"/>
|
||||
</variation>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Hours" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="c2J-Uj-KEg" userLabel="Hours Description Label">
|
||||
<rect key="frame" x="8" y="28" width="60.5" height="22"/>
|
||||
<fontDescription key="fontDescription" name="OpenSans" family="Open Sans" pointSize="16"/>
|
||||
<color key="textColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="8" y="31" width="57" height="19"/>
|
||||
</variation>
|
||||
</label>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="JBv-xm-KUq" userLabel="Separator View">
|
||||
<rect key="frame" x="75" y="10" width="1" height="30"/>
|
||||
@@ -581,6 +614,9 @@
|
||||
<constraint firstAttribute="width" constant="1" id="Gck-dw-et7"/>
|
||||
<constraint firstAttribute="height" constant="30" id="gVK-VO-Bq4"/>
|
||||
</constraints>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="71.5" y="10" width="1" height="30"/>
|
||||
</variation>
|
||||
</view>
|
||||
</subviews>
|
||||
<constraints>
|
||||
@@ -593,6 +629,9 @@
|
||||
<constraint firstItem="gaG-Iv-Xyq" firstAttribute="top" secondItem="5is-0I-Kv3" secondAttribute="top" id="ryA-23-kxC"/>
|
||||
<constraint firstAttribute="trailing" secondItem="JBv-xm-KUq" secondAttribute="trailing" id="z4K-rX-taw"/>
|
||||
</constraints>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="72.5" y="0.0" width="73" height="50"/>
|
||||
</variation>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="tvc-eS-Us6" userLabel="Minutes View">
|
||||
<rect key="frame" x="152" y="0.0" width="76.5" height="50"/>
|
||||
@@ -601,12 +640,18 @@
|
||||
<rect key="frame" x="8" y="0.0" width="60.5" height="29"/>
|
||||
<fontDescription key="fontDescription" name="OpenSans-Semibold" family="Open Sans" pointSize="21"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="8" y="0.0" width="57" height="24.5"/>
|
||||
</variation>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Minutes" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="EES-a9-qxv" userLabel="Minutes Description Label">
|
||||
<rect key="frame" x="8" y="28" width="60.5" height="22"/>
|
||||
<fontDescription key="fontDescription" name="OpenSans" family="Open Sans" pointSize="16"/>
|
||||
<color key="textColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="8" y="31" width="57" height="19"/>
|
||||
</variation>
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
@@ -617,6 +662,9 @@
|
||||
<constraint firstAttribute="bottom" secondItem="EES-a9-qxv" secondAttribute="bottom" id="jdu-Od-J49"/>
|
||||
<constraint firstItem="Txm-uf-MP4" firstAttribute="top" secondItem="tvc-eS-Us6" secondAttribute="top" id="vpc-a8-Iuw"/>
|
||||
</constraints>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="145" y="0.0" width="73" height="50"/>
|
||||
</variation>
|
||||
</view>
|
||||
</subviews>
|
||||
<constraints>
|
||||
@@ -642,6 +690,9 @@
|
||||
<constraint firstAttribute="bottom" secondItem="5is-0I-Kv3" secondAttribute="bottom" id="ngY-tF-5EI"/>
|
||||
<constraint firstItem="tvc-eS-Us6" firstAttribute="top" secondItem="6rV-hv-c3D" secondAttribute="top" id="wUO-8b-mHS"/>
|
||||
</constraints>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="41.5" y="38" width="218.5" height="50"/>
|
||||
</variation>
|
||||
</view>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Lzv-E6-gsr">
|
||||
<rect key="frame" x="20" y="96" width="276" height="48"/>
|
||||
@@ -948,6 +999,9 @@
|
||||
<fontDescription key="fontDescription" name="OpenSans" family="Open Sans" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="20" y="16" width="49" height="20"/>
|
||||
</variation>
|
||||
<variation key="heightClass=regular-widthClass=regular" misplaced="YES">
|
||||
<rect key="frame" x="20" y="35.5" width="49" height="20"/>
|
||||
</variation>
|
||||
@@ -956,6 +1010,9 @@
|
||||
<rect key="frame" x="444" y="14" width="136" height="24"/>
|
||||
<fontDescription key="fontDescription" name="OpenSans" family="Open Sans" pointSize="17"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="448" y="16" width="132" height="20"/>
|
||||
</variation>
|
||||
<variation key="heightClass=regular-widthClass=regular" misplaced="YES">
|
||||
<rect key="frame" x="648" y="35.5" width="132" height="20"/>
|
||||
</variation>
|
||||
@@ -985,6 +1042,9 @@
|
||||
<fontDescription key="fontDescription" name="OpenSans" family="Open Sans" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="20" y="16" width="44" height="20"/>
|
||||
</variation>
|
||||
<variation key="heightClass=regular-widthClass=regular" misplaced="YES">
|
||||
<rect key="frame" x="20" y="96" width="44" height="20"/>
|
||||
</variation>
|
||||
@@ -993,6 +1053,9 @@
|
||||
<rect key="frame" x="527.5" y="14" width="52.5" height="23.5"/>
|
||||
<fontDescription key="fontDescription" name="OpenSans" family="Open Sans" pointSize="17"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="231" y="16" width="49" height="20"/>
|
||||
</variation>
|
||||
<variation key="heightClass=regular-widthClass=regular" misplaced="YES">
|
||||
<rect key="frame" x="731" y="96" width="49" height="20"/>
|
||||
</variation>
|
||||
@@ -1022,6 +1085,9 @@
|
||||
<fontDescription key="fontDescription" name="OpenSans" family="Open Sans" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="20" y="16" width="104" height="20"/>
|
||||
</variation>
|
||||
<variation key="heightClass=regular-widthClass=regular" misplaced="YES">
|
||||
<rect key="frame" x="20" y="64" width="104" height="24"/>
|
||||
</variation>
|
||||
@@ -1030,6 +1096,9 @@
|
||||
<rect key="frame" x="570" y="14" width="10" height="24"/>
|
||||
<fontDescription key="fontDescription" name="OpenSans" family="Open Sans" pointSize="17"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="270" y="16" width="10" height="20"/>
|
||||
</variation>
|
||||
<variation key="heightClass=regular-widthClass=regular" misplaced="YES">
|
||||
<rect key="frame" x="770" y="64" width="10" height="24"/>
|
||||
</variation>
|
||||
@@ -1059,6 +1128,9 @@
|
||||
<fontDescription key="fontDescription" name="OpenSans" family="Open Sans" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="20" y="16" width="111" height="20"/>
|
||||
</variation>
|
||||
<variation key="heightClass=regular-widthClass=regular" misplaced="YES">
|
||||
<rect key="frame" x="20" y="8" width="111" height="20"/>
|
||||
</variation>
|
||||
@@ -1068,6 +1140,9 @@
|
||||
<fontDescription key="fontDescription" name="OpenSans" family="Open Sans" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="501" y="16" width="59" height="20"/>
|
||||
</variation>
|
||||
<variation key="heightClass=regular-widthClass=regular" misplaced="YES">
|
||||
<rect key="frame" x="705" y="8" width="59" height="20"/>
|
||||
</variation>
|
||||
@@ -1179,6 +1254,9 @@
|
||||
<fontDescription key="fontDescription" name="OpenSans" family="Open Sans" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="20" y="8" width="106" height="20"/>
|
||||
</variation>
|
||||
<variation key="heightClass=regular-widthClass=regular" misplaced="YES">
|
||||
<rect key="frame" x="20" y="0.0" width="106" height="24"/>
|
||||
</variation>
|
||||
@@ -1188,6 +1266,9 @@
|
||||
<fontDescription key="fontDescription" name="OpenSans-Light" family="Open Sans" pointSize="72"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="20" y="117" width="560" height="84"/>
|
||||
</variation>
|
||||
<variation key="heightClass=regular-widthClass=regular" misplaced="YES">
|
||||
<rect key="frame" x="20" y="358" width="760" height="84"/>
|
||||
</variation>
|
||||
@@ -1228,12 +1309,18 @@
|
||||
<fontDescription key="fontDescription" name="OpenSans" family="Open Sans" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="20" y="8" width="49.5" height="20"/>
|
||||
</variation>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0.0 kn" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="l5u-i3-029">
|
||||
<rect key="frame" x="203" y="210" width="195.5" height="98.5"/>
|
||||
<fontDescription key="fontDescription" name="OpenSans-Light" family="Open Sans" pointSize="72"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="202" y="117" width="197.5" height="84"/>
|
||||
</variation>
|
||||
<variation key="heightClass=regular-widthClass=regular" misplaced="YES">
|
||||
<rect key="frame" x="301.5" y="358" width="197.5" height="84"/>
|
||||
</variation>
|
||||
@@ -1271,6 +1358,9 @@
|
||||
<fontDescription key="fontDescription" name="OpenSans" family="Open Sans" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="20" y="8" width="38.5" height="20"/>
|
||||
</variation>
|
||||
<variation key="heightClass=regular-widthClass=regular" misplaced="YES">
|
||||
<rect key="frame" x="20" y="0.0" width="38.5" height="20"/>
|
||||
</variation>
|
||||
@@ -1280,6 +1370,9 @@
|
||||
<fontDescription key="fontDescription" name="OpenSans-Light" family="Open Sans" pointSize="72"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="256" y="117" width="89" height="84"/>
|
||||
</variation>
|
||||
<variation key="heightClass=regular-widthClass=regular" misplaced="YES">
|
||||
<rect key="frame" x="355.5" y="358" width="89" height="84"/>
|
||||
</variation>
|
||||
@@ -1532,12 +1625,18 @@ Cg
|
||||
<fontDescription key="fontDescription" name="OpenSans" family="Open Sans" pointSize="13"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="20" y="256" width="43" height="15.5"/>
|
||||
</variation>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="1.0.0" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Jsi-LA-7jU">
|
||||
<rect key="frame" x="20" y="202" width="30" height="18"/>
|
||||
<fontDescription key="fontDescription" name="OpenSans" family="Open Sans" pointSize="13"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="20" y="279.5" width="29" height="15.5"/>
|
||||
</variation>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
@@ -1582,21 +1681,21 @@ Cg
|
||||
</constraints>
|
||||
<variation key="default">
|
||||
<mask key="constraints">
|
||||
<exclude reference="HxP-XV-1as"/>
|
||||
<exclude reference="Htc-F9-k7d"/>
|
||||
<exclude reference="i64-7l-JjE"/>
|
||||
<exclude reference="rI9-vl-bNT"/>
|
||||
<exclude reference="HxP-XV-1as"/>
|
||||
</mask>
|
||||
</variation>
|
||||
<variation key="heightClass=compact">
|
||||
<mask key="constraints">
|
||||
<exclude reference="YBh-Y6-NK3"/>
|
||||
<include reference="HxP-XV-1as"/>
|
||||
<exclude reference="08e-KJ-Dpa"/>
|
||||
<exclude reference="Bht-kB-G6p"/>
|
||||
<include reference="Htc-F9-k7d"/>
|
||||
<include reference="i64-7l-JjE"/>
|
||||
<include reference="rI9-vl-bNT"/>
|
||||
<include reference="HxP-XV-1as"/>
|
||||
</mask>
|
||||
</variation>
|
||||
</view>
|
||||
@@ -1681,6 +1780,9 @@ Cg
|
||||
<fontDescription key="fontDescription" name="OpenSans" family="Open Sans" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="14" y="12" width="111.5" height="20"/>
|
||||
</variation>
|
||||
<variation key="heightClass=regular-widthClass=regular" misplaced="YES">
|
||||
<rect key="frame" x="15" y="10" width="111.5" height="24"/>
|
||||
</variation>
|
||||
@@ -1710,6 +1812,9 @@ Cg
|
||||
<fontDescription key="fontDescription" name="OpenSans-Bold" family="Open Sans" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="14" y="2" width="127" height="20"/>
|
||||
</variation>
|
||||
<variation key="heightClass=regular-widthClass=regular" misplaced="YES">
|
||||
<rect key="frame" x="15" y="10" width="111.5" height="24"/>
|
||||
</variation>
|
||||
@@ -1719,6 +1824,9 @@ Cg
|
||||
<fontDescription key="fontDescription" name="OpenSans" family="Open Sans" pointSize="13"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
<variation key="heightClass=compact" misplaced="YES">
|
||||
<rect key="frame" x="14" y="26" width="32" height="15.5"/>
|
||||
</variation>
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
@@ -1791,7 +1899,7 @@ Cg
|
||||
<!--Leader Board-->
|
||||
<scene sceneID="BcW-Cr-BGq">
|
||||
<objects>
|
||||
<viewController id="86Y-sl-Zhj" customClass="LeaderBoardViewController" customModule="SAPTracker" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<viewController id="86Y-sl-Zhj" customClass="LeaderboardViewController" customModule="SAPTracker" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="Dlt-1X-fN2"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="Ehu-33-1iX"/>
|
||||
@@ -1825,7 +1933,7 @@ Cg
|
||||
<navigationItem key="navigationItem" title="Leader Board" id="8qz-J9-1KL">
|
||||
<barButtonItem key="rightBarButtonItem" systemItem="done" id="NSL-iA-JLn">
|
||||
<connections>
|
||||
<action selector="done:" destination="86Y-sl-Zhj" id="BdJ-Hv-zJb"/>
|
||||
<action selector="doneButtonTapped:" destination="86Y-sl-Zhj" id="Xm9-iN-s5q"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
</navigationItem>
|
||||
@@ -1868,8 +1976,8 @@ Cg
|
||||
<image name="settings" width="22" height="22"/>
|
||||
</resources>
|
||||
<inferredMetricsTieBreakers>
|
||||
<segue reference="QMa-LQ-D8c"/>
|
||||
<segue reference="HaH-Jc-FNR"/>
|
||||
<segue reference="tzB-PL-31j"/>
|
||||
<segue reference="Irs-ey-Uhs"/>
|
||||
</inferredMetricsTieBreakers>
|
||||
<color key="tintColor" red="0.0" green="0.61568627450980395" blue="0.8784313725490196" alpha="1" colorSpace="calibratedRGB"/>
|
||||
</document>
|
||||
@@ -10,7 +10,7 @@ import UIKit
|
||||
|
||||
class CachedFixesTrackingTableViewCell: UITableViewCell {
|
||||
|
||||
var checkIn: CheckIn?
|
||||
var regatta: Regatta?
|
||||
|
||||
@IBOutlet weak var cachedFixesLabel: UILabel!
|
||||
|
||||
@@ -27,7 +27,7 @@ class CachedFixesTrackingTableViewCell: UITableViewCell {
|
||||
// MARK: - Setups
|
||||
|
||||
private func setupCachedFixesLabel() {
|
||||
self.cachedFixesLabel.text = String(format: "%d", checkIn?.gpsFixes?.count ?? 0)
|
||||
self.cachedFixesLabel.text = String(format: "%d", regatta?.gpsFixes?.count ?? 0)
|
||||
}
|
||||
|
||||
// MARK: - Notifications
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
//
|
||||
// CheckIn.swift
|
||||
// SAPTracker
|
||||
//
|
||||
// Created by Raimund Wege on 30.06.16.
|
||||
// Copyright © 2016 com.sap.sailing. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
|
||||
@objc(CheckIn)
|
||||
class CheckIn: NSManagedObject {
|
||||
|
||||
// Insert code here to add functionality to your managed object subclass
|
||||
|
||||
}
|
||||
@@ -42,9 +42,10 @@ class CheckInController : NSObject {
|
||||
static let Name = "name"
|
||||
}
|
||||
|
||||
private let checkInData: CheckInData!
|
||||
private let delegate: CheckInControllerDelegate!
|
||||
private let requestManager: RequestManager!
|
||||
var delegate: CheckInControllerDelegate?
|
||||
|
||||
private var checkInData = CheckInData()
|
||||
private var requestManager = RequestManager()
|
||||
|
||||
// Responses
|
||||
private var eventDictionary: [String: AnyObject]?
|
||||
@@ -52,20 +53,28 @@ class CheckInController : NSObject {
|
||||
private var competitorDictionary: [String: AnyObject]?
|
||||
private var teamImageURL: String?
|
||||
|
||||
init(checkInData: CheckInData, delegate: CheckInControllerDelegate) {
|
||||
// MARK: - Initialize
|
||||
|
||||
private func initialize(checkInData: CheckInData) {
|
||||
self.checkInData = checkInData
|
||||
self.delegate = delegate
|
||||
setupRequestManager()
|
||||
}
|
||||
|
||||
// MARK: - Setups
|
||||
|
||||
private func setupRequestManager() {
|
||||
requestManager = RequestManager(baseURLString: checkInData.serverURL)
|
||||
super.init()
|
||||
}
|
||||
|
||||
// MARK: - Start check-in
|
||||
|
||||
func startCheckIn() {
|
||||
func startCheckIn(checkInData: CheckInData) {
|
||||
initialize(checkInData)
|
||||
checkInDidStart()
|
||||
requestManager.getEvent(checkInData.eventID,
|
||||
success: { (operation, responseObject) -> Void in self.eventSucceed(responseObject) },
|
||||
failure: { (operation, error) -> Void in self.eventFailed(error) })
|
||||
failure: { (operation, error) -> Void in self.eventFailed(error) }
|
||||
)
|
||||
}
|
||||
|
||||
// MARK: - Event
|
||||
@@ -74,7 +83,8 @@ class CheckInController : NSObject {
|
||||
eventDictionary = eventResponseObject as? [String: AnyObject]
|
||||
requestManager.getLeaderboard(checkInData.leaderboardName,
|
||||
success: { (operation, responseObject) -> Void in self.leaderboardSucceed(responseObject) },
|
||||
failure: { (operation, error) -> Void in self.leaderboardFailed(error) })
|
||||
failure: { (operation, error) -> Void in self.leaderboardFailed(error) }
|
||||
)
|
||||
}
|
||||
|
||||
private func eventFailed(error: AnyObject) {
|
||||
@@ -94,7 +104,8 @@ class CheckInController : NSObject {
|
||||
leaderboardDictionary = leaderboardResponseObject as? [String: AnyObject]
|
||||
requestManager.getCompetitor(checkInData.competitorID,
|
||||
success: { (operation, responseObject) in self.competitorSucceed(responseObject) },
|
||||
failure: { (operation, error) in self.competitorFailed(error) })
|
||||
failure: { (operation, error) in self.competitorFailed(error) }
|
||||
)
|
||||
}
|
||||
|
||||
private func leaderboardFailed(error: AnyObject) {
|
||||
@@ -112,7 +123,7 @@ class CheckInController : NSObject {
|
||||
|
||||
private func competitorSucceed(competitorResponseObject: AnyObject) {
|
||||
competitorDictionary = competitorResponseObject as? [String: AnyObject]
|
||||
requestManager.getTeamImageURL(competitorID(), result: { (imageURL) in self.teamImageURLResult(imageURL) })
|
||||
requestManager.getTeamImageURL(competitorID, result: { (imageURL) in self.teamImageURLResult(imageURL) })
|
||||
}
|
||||
|
||||
private func competitorFailed(error: AnyObject) {
|
||||
@@ -131,9 +142,9 @@ class CheckInController : NSObject {
|
||||
private func teamImageURLResult(imageURL: String?) {
|
||||
teamImageURL = imageURL
|
||||
let alertTitle = String(format:NSLocalizedString("Hello %@. Welcome to %@. You are registered as %@.", comment: ""),
|
||||
competitorName(),
|
||||
leaderboardName(),
|
||||
competitorSailID())
|
||||
competitorName,
|
||||
leaderboardName,
|
||||
competitorSailID)
|
||||
let alertController = UIAlertController(title: alertTitle, message: nil, preferredStyle: .Alert)
|
||||
let okTitle = NSLocalizedString("OK", comment: "")
|
||||
let okAction = UIAlertAction(title: okTitle, style: .Default) { (action) in
|
||||
@@ -145,76 +156,67 @@ class CheckInController : NSObject {
|
||||
}
|
||||
alertController.addAction(okAction)
|
||||
alertController.addAction(cancelAction)
|
||||
self.showCheckInAlert(alertController)
|
||||
showCheckInAlert(alertController)
|
||||
}
|
||||
|
||||
// MARK: - Check-in on server
|
||||
|
||||
private func checkInOnServer() {
|
||||
SVProgressHUD.show()
|
||||
requestManager.postCheckIn(leaderboardName(),
|
||||
competitorID: competitorID(),
|
||||
requestManager.postCheckIn(leaderboardName,
|
||||
competitorID: competitorID,
|
||||
success: { (operation, responseObject) -> Void in self.checkInOnServerSucceed() },
|
||||
failure: { (operation, error) -> Void in self.checkInOnServerFailed(error) })
|
||||
failure: { (operation, error) -> Void in self.checkInOnServerFailed(error) }
|
||||
)
|
||||
}
|
||||
|
||||
private func checkInOnServerSucceed() {
|
||||
|
||||
// Check database if check-in already exist
|
||||
if let checkIn = CoreDataManager.sharedManager.fetchCheckIn(checkInData.eventID,
|
||||
leaderboardName: checkInData.leaderboardName,
|
||||
competitorID: checkInData.competitorID) {
|
||||
// Delete old check-in
|
||||
CoreDataManager.sharedManager.deleteCheckIn(checkIn)
|
||||
CoreDataManager.sharedManager.saveContext()
|
||||
}
|
||||
// Regatta
|
||||
let regatta = CoreDataManager.sharedManager.fetchRegatta(checkInData.eventID,
|
||||
leaderboardName: checkInData.leaderboardName,
|
||||
competitorID: checkInData.competitorID
|
||||
) ?? CoreDataManager.sharedManager.newRegatta()
|
||||
regatta.serverURL = checkInData.serverURL
|
||||
regatta.teamImageURL = teamImageURL
|
||||
regatta.teamImageRetry = false
|
||||
|
||||
// Create new check-in
|
||||
let checkIn = CoreDataManager.sharedManager.newCheckIn()
|
||||
checkIn.competitorID = checkInData!.competitorID
|
||||
checkIn.eventID = checkInData.eventID
|
||||
checkIn.lastSyncDate = NSDate().timeIntervalSince1970
|
||||
checkIn.leaderboardName = checkInData!.leaderboardName
|
||||
checkIn.serverURL = checkInData!.serverURL
|
||||
checkIn.teamImageURL = teamImageURL
|
||||
checkIn.teamImageRetry = false
|
||||
// Event
|
||||
let event = regatta.event ?? CoreDataManager.sharedManager.newEvent(regatta)
|
||||
event.endDate = (eventEndDate / 1000)
|
||||
event.eventID = eventID
|
||||
event.name = eventName
|
||||
event.startDate = (eventStartDate / 1000)
|
||||
|
||||
// Create new event
|
||||
let event = CoreDataManager.sharedManager.newEvent(checkIn)
|
||||
event.endDate = (eventEndDate() / 1000)
|
||||
event.eventID = eventID()
|
||||
event.name = eventName()
|
||||
event.startDate = (eventStartDate() / 1000)
|
||||
// Leaderboard
|
||||
let leaderboard = regatta.leaderboard ?? CoreDataManager.sharedManager.newLeaderboard(regatta)
|
||||
leaderboard.name = leaderboardName
|
||||
|
||||
// Create new leaderboard
|
||||
let leaderboard = CoreDataManager.sharedManager.newLeaderBoard(checkIn)
|
||||
leaderboard.name = leaderboardName()
|
||||
// Competitor
|
||||
let competitor = regatta.competitor ?? CoreDataManager.sharedManager.newCompetitor(regatta)
|
||||
competitor.boatClassName = competitorBoatClassName
|
||||
competitor.competitorID = competitorID
|
||||
competitor.countryCode = competitorCountryCode
|
||||
competitor.name = competitorName
|
||||
competitor.nationality = competitorNationality
|
||||
competitor.sailID = competitorSailID
|
||||
|
||||
// Create new competitor
|
||||
let competitor = CoreDataManager.sharedManager.newCompetitor(checkIn)
|
||||
competitor.boatClassName = competitorBoatClassName()
|
||||
competitor.competitorID = competitorID()
|
||||
competitor.countryCode = competitorCountryCode()
|
||||
competitor.name = competitorName()
|
||||
competitor.nationality = competitorNationality()
|
||||
competitor.sailID = competitorSailID()
|
||||
|
||||
// Save objects
|
||||
// Save
|
||||
CoreDataManager.sharedManager.saveContext()
|
||||
|
||||
// Check-in completed
|
||||
self.checkInDidEnd(withSuccess: true)
|
||||
checkInDidEnd(withSuccess: true)
|
||||
}
|
||||
|
||||
private func checkInOnServerFailed(error: AnyObject) {
|
||||
let alertTitle = String(format:NSLocalizedString("Couldn't check-in to %@", comment: ""), checkInData!.leaderboardName)
|
||||
let alertTitle = String(format:NSLocalizedString("Couldn't check-in to %@", comment: ""), checkInData.leaderboardName)
|
||||
let alertController = UIAlertController(title: alertTitle, message: error.localizedDescription, preferredStyle: .Alert)
|
||||
let cancelTitle = NSLocalizedString("Cancel", comment: "")
|
||||
let cancelAction = UIAlertAction(title: cancelTitle, style: .Cancel) { (action) in
|
||||
self.checkInDidEnd(withSuccess: false)
|
||||
}
|
||||
alertController.addAction(cancelAction)
|
||||
self.showCheckInAlert(alertController)
|
||||
showCheckInAlert(alertController)
|
||||
}
|
||||
|
||||
// MARK: - Controller
|
||||
@@ -222,51 +224,52 @@ class CheckInController : NSObject {
|
||||
private func checkInDidStart() {
|
||||
dispatch_async(dispatch_get_main_queue(), {
|
||||
SVProgressHUD.show()
|
||||
self.delegate.checkInDidStart?(self)
|
||||
self.delegate?.checkInDidStart?(self)
|
||||
})
|
||||
}
|
||||
|
||||
private func checkInDidEnd(withSuccess succeed: Bool) {
|
||||
dispatch_async(dispatch_get_main_queue(), {
|
||||
SVProgressHUD.popActivity()
|
||||
self.delegate.checkInDidEnd?(self, withSuccess: succeed)
|
||||
self.delegate?.checkInDidEnd?(self, withSuccess: succeed)
|
||||
})
|
||||
}
|
||||
|
||||
private func showCheckInAlert(alertController: UIAlertController) {
|
||||
dispatch_async(dispatch_get_main_queue(), {
|
||||
SVProgressHUD.popActivity()
|
||||
self.delegate.showCheckInAlert(self, alertController: alertController)
|
||||
self.delegate?.showCheckInAlert(self, alertController: alertController)
|
||||
})
|
||||
}
|
||||
|
||||
// MARK: - Event
|
||||
|
||||
private func eventID() -> String! { return stringFromEvent(forKey: EventKeys.ID) }
|
||||
private func eventName() -> String! { return stringFromEvent(forKey: EventKeys.Name) }
|
||||
private func eventStartDate() -> Double! { return doubleFromEvent(forKey: EventKeys.StartDate) }
|
||||
private func eventEndDate() -> Double! { return doubleFromEvent(forKey: EventKeys.EndDate) }
|
||||
private func doubleFromEvent(forKey key: String) -> Double { return doubleFromDictionary(eventDictionary, forKey: key) }
|
||||
private func stringFromEvent(forKey key: String) -> String { return stringFromDictionary(eventDictionary, forKey: key) }
|
||||
var eventID: String { get { return stringFromEvent(forKey: EventKeys.ID) } }
|
||||
var eventName: String { get { return stringFromEvent(forKey: EventKeys.Name) } }
|
||||
var eventStartDate: Double { get { return doubleFromEvent(forKey: EventKeys.StartDate) } }
|
||||
var eventEndDate: Double { get { return doubleFromEvent(forKey: EventKeys.EndDate) } }
|
||||
|
||||
// MARK: - Leaderboard
|
||||
|
||||
private func leaderboardName() -> String! { return stringFromLeaderboard(forKey: LeaderboardKeys.Name) }
|
||||
private func stringFromLeaderboard(forKey key: String) -> String { return stringFromDictionary(leaderboardDictionary, forKey: key) }
|
||||
var leaderboardName: String { get { return stringFromLeaderboard(forKey: LeaderboardKeys.Name) } }
|
||||
|
||||
// MARK: - Competitor
|
||||
|
||||
private func competitorBoatClassName() -> String! { return stringFromCompetitor(forKey: CompetitorKeys.BoatClassName) }
|
||||
private func competitorCountryCode() -> String! { return stringFromCompetitor(forKey: CompetitorKeys.CountryCode) }
|
||||
private func competitorID() -> String { return stringFromCompetitor(forKey: CompetitorKeys.ID) }
|
||||
private func competitorName() -> String! { return stringFromCompetitor(forKey: CompetitorKeys.Name) }
|
||||
private func competitorNationality() -> String! { return stringFromCompetitor(forKey: CompetitorKeys.Nationality) }
|
||||
private func competitorSailID() -> String! { return stringFromCompetitor(forKey: CompetitorKeys.SailID) }
|
||||
private func stringFromCompetitor(forKey key: String) -> String { return stringFromDictionary(competitorDictionary, forKey: key) }
|
||||
var competitorBoatClassName: String { get { return stringFromCompetitor(forKey: CompetitorKeys.BoatClassName) } }
|
||||
var competitorCountryCode: String { get { return stringFromCompetitor(forKey: CompetitorKeys.CountryCode) } }
|
||||
var competitorID: String { get { return stringFromCompetitor(forKey: CompetitorKeys.ID) } }
|
||||
var competitorName: String { get { return stringFromCompetitor(forKey: CompetitorKeys.Name) } }
|
||||
var competitorNationality: String { get { return stringFromCompetitor(forKey: CompetitorKeys.Nationality) } }
|
||||
var competitorSailID: String { get { return stringFromCompetitor(forKey: CompetitorKeys.SailID) } }
|
||||
|
||||
// MARK: - Helper
|
||||
|
||||
private func doubleFromDictionary(dictionary: [String: AnyObject]?, forKey key: String!) -> Double {
|
||||
private func doubleFromEvent(forKey key: String) -> Double { return doubleFromDictionary(eventDictionary, forKey: key) }
|
||||
private func stringFromEvent(forKey key: String) -> String { return stringFromDictionary(eventDictionary, forKey: key) }
|
||||
private func stringFromLeaderboard(forKey key: String) -> String { return stringFromDictionary(leaderboardDictionary, forKey: key) }
|
||||
private func stringFromCompetitor(forKey key: String) -> String { return stringFromDictionary(competitorDictionary, forKey: key) }
|
||||
|
||||
private func doubleFromDictionary(dictionary: [String: AnyObject]?, forKey key: String) -> Double {
|
||||
if let value = dictionary?[key] as? Double {
|
||||
return value
|
||||
} else {
|
||||
@@ -274,7 +277,7 @@ class CheckInController : NSObject {
|
||||
}
|
||||
}
|
||||
|
||||
private func stringFromDictionary(dictionary: [String: AnyObject]?, forKey key: String!) -> String {
|
||||
private func stringFromDictionary(dictionary: [String: AnyObject]?, forKey key: String) -> String {
|
||||
if let value = dictionary?[key] as? String {
|
||||
return value
|
||||
} else {
|
||||
|
||||
@@ -16,17 +16,16 @@ public class CheckInData: NSObject {
|
||||
static let CompetitorID = "competitor_id"
|
||||
}
|
||||
|
||||
public let serverURL: String!
|
||||
public let eventID: String!
|
||||
public let leaderboardName: String!
|
||||
public let competitorID: String!
|
||||
public let serverURL: String
|
||||
public let eventID: String
|
||||
public let leaderboardName: String
|
||||
public let competitorID: String
|
||||
|
||||
init?(serverURL: String!,
|
||||
eventID: String!,
|
||||
leaderboardName: String!,
|
||||
competitorID: String!)
|
||||
init(serverURL: String = "",
|
||||
eventID: String = "",
|
||||
leaderboardName: String = "",
|
||||
competitorID: String = "")
|
||||
{
|
||||
guard serverURL != nil && eventID != nil && leaderboardName != nil && competitorID != nil else { return nil }
|
||||
self.serverURL = serverURL
|
||||
self.eventID = eventID
|
||||
self.leaderboardName = leaderboardName
|
||||
@@ -34,19 +33,21 @@ public class CheckInData: NSObject {
|
||||
super.init()
|
||||
}
|
||||
|
||||
convenience init?(url: NSURL!) {
|
||||
guard url != nil && url.host != nil && url.query != nil else { return nil }
|
||||
convenience init?(url: NSURL) {
|
||||
guard let host = url.host else { return nil }
|
||||
guard let components = NSURLComponents(string: url.absoluteString) else { return nil }
|
||||
|
||||
// Set server URL
|
||||
let serverURL = url.scheme + "://" + host + (url.port != nil ? ":" + url.port!.stringValue : "")
|
||||
|
||||
// In query component replace '+' occurrences with '%20' as a workaround for bug 3664
|
||||
components.percentEncodedQuery = components.percentEncodedQuery?.stringByReplacingOccurrencesOfString("+", withString: "%20")
|
||||
let queryItems = components.queryItems
|
||||
|
||||
// Set server URL and check-in items
|
||||
let serverURL = url.scheme + "://" + url.host! + (url.port == nil ? "" : ":" + url.port!.stringValue)
|
||||
let eventID = CheckInData.queryItemValue(queryItems, itemName: CheckInData.ItemNames.EventID)
|
||||
let leaderboardName = CheckInData.queryItemValue(queryItems, itemName: CheckInData.ItemNames.LeaderboardName)
|
||||
let competitorID = CheckInData.queryItemValue(queryItems, itemName: CheckInData.ItemNames.CompetitorID)
|
||||
// Get check-in items
|
||||
guard let eventID = CheckInData.queryItemValue(queryItems, itemName: CheckInData.ItemNames.EventID) else { return nil }
|
||||
guard let leaderboardName = CheckInData.queryItemValue(queryItems, itemName: CheckInData.ItemNames.LeaderboardName) else { return nil }
|
||||
guard let competitorID = CheckInData.queryItemValue(queryItems, itemName: CheckInData.ItemNames.CompetitorID) else { return nil }
|
||||
|
||||
// Init with values
|
||||
self.init(serverURL: serverURL,
|
||||
@@ -55,8 +56,10 @@ public class CheckInData: NSObject {
|
||||
competitorID: competitorID)
|
||||
}
|
||||
|
||||
convenience init?(urlString: String!) {
|
||||
convenience init?(urlString: String) {
|
||||
guard let url = NSURL(string: urlString) else { return nil }
|
||||
|
||||
// Init with URL
|
||||
self.init(url: url)
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Competitor+CoreDataProperties.swift
|
||||
// SAPTracker
|
||||
//
|
||||
// Created by Raimund Wege on 01.07.16.
|
||||
// Created by Raimund Wege on 04.07.16.
|
||||
// Copyright © 2016 com.sap.sailing. All rights reserved.
|
||||
//
|
||||
// Choose "Create NSManagedObject Subclass…" from the Core Data editor menu
|
||||
@@ -14,12 +14,12 @@ import CoreData
|
||||
|
||||
extension Competitor {
|
||||
|
||||
@NSManaged var boatClassName: String?
|
||||
@NSManaged var competitorID: String?
|
||||
@NSManaged var countryCode: String?
|
||||
@NSManaged var name: String?
|
||||
@NSManaged var nationality: String?
|
||||
@NSManaged var sailID: String?
|
||||
@NSManaged var checkIn: CheckIn?
|
||||
@NSManaged var boatClassName: String
|
||||
@NSManaged var competitorID: String
|
||||
@NSManaged var countryCode: String
|
||||
@NSManaged var name: String
|
||||
@NSManaged var nationality: String
|
||||
@NSManaged var sailID: String
|
||||
@NSManaged var regatta: Regatta
|
||||
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
// Competitor.swift
|
||||
// SAPTracker
|
||||
//
|
||||
// Created by Raimund Wege on 30.06.16.
|
||||
// Created by Raimund Wege on 04.07.16.
|
||||
// Copyright © 2016 com.sap.sailing. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
+24
-28
@@ -1,34 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="10171" systemVersion="15E65" minimumToolsVersion="Xcode 4.3">
|
||||
<entity name="CheckIn" representedClassName="CheckIn" syncable="YES">
|
||||
<attribute name="competitorID" attributeType="String" syncable="YES"/>
|
||||
<attribute name="eventID" attributeType="String" syncable="YES"/>
|
||||
<attribute name="lastSyncDate" optional="YES" attributeType="Date" syncable="YES"/>
|
||||
<attribute name="leaderboardName" attributeType="String" syncable="YES"/>
|
||||
<attribute name="serverURL" attributeType="String" syncable="YES"/>
|
||||
<attribute name="teamImageData" optional="YES" attributeType="Binary" syncable="YES"/>
|
||||
<attribute name="teamImageRetry" optional="YES" attributeType="Boolean" syncable="YES"/>
|
||||
<attribute name="teamImageURL" optional="YES" attributeType="String" syncable="YES"/>
|
||||
<relationship name="competitor" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="Competitor" inverseName="checkIn" inverseEntity="Competitor" syncable="YES"/>
|
||||
<relationship name="event" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="Event" inverseName="checkIn" inverseEntity="Event" syncable="YES"/>
|
||||
<relationship name="gpsFixes" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="GPSFix" inverseName="checkIn" inverseEntity="GPSFix" syncable="YES"/>
|
||||
<relationship name="leaderboard" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="Leaderboard" inverseName="checkIn" inverseEntity="Leaderboard" syncable="YES"/>
|
||||
</entity>
|
||||
<entity name="Competitor" representedClassName="Competitor" syncable="YES">
|
||||
<attribute name="boatClassName" optional="YES" attributeType="String" syncable="YES"/>
|
||||
<attribute name="boatClassName" attributeType="String" syncable="YES"/>
|
||||
<attribute name="competitorID" attributeType="String" indexed="YES" syncable="YES"/>
|
||||
<attribute name="countryCode" optional="YES" attributeType="String" syncable="YES"/>
|
||||
<attribute name="name" optional="YES" attributeType="String" syncable="YES"/>
|
||||
<attribute name="nationality" optional="YES" attributeType="String" syncable="YES"/>
|
||||
<attribute name="sailID" optional="YES" attributeType="String" syncable="YES"/>
|
||||
<relationship name="checkIn" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="CheckIn" inverseName="competitor" inverseEntity="CheckIn" syncable="YES"/>
|
||||
<attribute name="countryCode" attributeType="String" syncable="YES"/>
|
||||
<attribute name="name" attributeType="String" syncable="YES"/>
|
||||
<attribute name="nationality" attributeType="String" syncable="YES"/>
|
||||
<attribute name="sailID" attributeType="String" syncable="YES"/>
|
||||
<relationship name="regatta" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Regatta" inverseName="competitor" inverseEntity="Regatta" syncable="YES"/>
|
||||
</entity>
|
||||
<entity name="Event" representedClassName="Event" syncable="YES">
|
||||
<attribute name="endDate" optional="YES" attributeType="Date" syncable="YES"/>
|
||||
<attribute name="endDate" attributeType="Date" syncable="YES"/>
|
||||
<attribute name="eventID" attributeType="String" indexed="YES" syncable="YES"/>
|
||||
<attribute name="name" optional="YES" attributeType="String" syncable="YES"/>
|
||||
<attribute name="startDate" optional="YES" attributeType="Date" syncable="YES"/>
|
||||
<relationship name="checkIn" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="CheckIn" inverseName="event" inverseEntity="CheckIn" syncable="YES"/>
|
||||
<attribute name="name" attributeType="String" syncable="YES"/>
|
||||
<attribute name="startDate" attributeType="Date" syncable="YES"/>
|
||||
<relationship name="regatta" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Regatta" inverseName="event" inverseEntity="Regatta" syncable="YES"/>
|
||||
</entity>
|
||||
<entity name="GPSFix" representedClassName="GPSFix" syncable="YES">
|
||||
<attribute name="course" attributeType="Double" defaultValueString="0.0" syncable="YES"/>
|
||||
@@ -36,17 +22,27 @@
|
||||
<attribute name="longitude" attributeType="Double" defaultValueString="0.0" syncable="YES"/>
|
||||
<attribute name="speed" attributeType="Double" defaultValueString="0.0" syncable="YES"/>
|
||||
<attribute name="timestamp" attributeType="Double" defaultValueString="0.0" syncable="YES"/>
|
||||
<relationship name="checkIn" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="CheckIn" inverseName="gpsFixes" inverseEntity="CheckIn" syncable="YES"/>
|
||||
<relationship name="regatta" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Regatta" inverseName="gpsFixes" inverseEntity="Regatta" syncable="YES"/>
|
||||
</entity>
|
||||
<entity name="Leaderboard" representedClassName="Leaderboard" syncable="YES">
|
||||
<attribute name="name" attributeType="String" indexed="YES" syncable="YES"/>
|
||||
<relationship name="checkIn" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="CheckIn" inverseName="leaderboard" inverseEntity="CheckIn" syncable="YES"/>
|
||||
<relationship name="regatta" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Regatta" inverseName="leaderboard" inverseEntity="Regatta" syncable="YES"/>
|
||||
</entity>
|
||||
<entity name="Regatta" representedClassName="Regatta" syncable="YES">
|
||||
<attribute name="serverURL" attributeType="String" syncable="YES"/>
|
||||
<attribute name="teamImageData" optional="YES" attributeType="Binary" syncable="YES"/>
|
||||
<attribute name="teamImageRetry" attributeType="Boolean" syncable="YES"/>
|
||||
<attribute name="teamImageURL" optional="YES" attributeType="String" syncable="YES"/>
|
||||
<relationship name="competitor" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="Competitor" inverseName="regatta" inverseEntity="Competitor" syncable="YES"/>
|
||||
<relationship name="event" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="Event" inverseName="regatta" inverseEntity="Event" syncable="YES"/>
|
||||
<relationship name="gpsFixes" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="GPSFix" inverseName="regatta" inverseEntity="GPSFix" syncable="YES"/>
|
||||
<relationship name="leaderboard" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="Leaderboard" inverseName="regatta" inverseEntity="Leaderboard" syncable="YES"/>
|
||||
</entity>
|
||||
<elements>
|
||||
<element name="CheckIn" positionX="-36" positionY="90" width="128" height="225"/>
|
||||
<element name="Regatta" positionX="-36" positionY="90" width="128" height="165"/>
|
||||
<element name="Competitor" positionX="-9" positionY="81" width="128" height="150"/>
|
||||
<element name="Event" positionX="-63" positionY="27" width="128" height="120"/>
|
||||
<element name="GPSFix" positionX="-63" positionY="-18" width="128" height="133"/>
|
||||
<element name="GPSFix" positionX="-63" positionY="-18" width="128" height="135"/>
|
||||
<element name="Leaderboard" positionX="-36" positionY="72" width="128" height="75"/>
|
||||
</elements>
|
||||
</model>
|
||||
@@ -20,13 +20,13 @@ public class CoreDataManager: NSObject {
|
||||
|
||||
// MARK: - Fetch
|
||||
|
||||
func fetchCheckIn(eventID: String,
|
||||
func fetchRegatta(eventID: String,
|
||||
leaderboardName: String,
|
||||
competitorID: String) -> CheckIn?
|
||||
competitorID: String) -> Regatta?
|
||||
{
|
||||
let fetchRequest = NSFetchRequest()
|
||||
fetchRequest.entity = NSEntityDescription.entityForName("CheckIn", inManagedObjectContext: managedObjectContext!)
|
||||
fetchRequest.predicate = NSPredicate(format: "eventID = %@ AND leaderboardName = %@ AND competitorID = %@",
|
||||
fetchRequest.entity = NSEntityDescription.entityForName("Regatta", inManagedObjectContext: managedObjectContext!)
|
||||
fetchRequest.predicate = NSPredicate(format: "event.eventID = %@ AND leaderboard.name = %@ AND competitor.competitorID = %@",
|
||||
eventID,
|
||||
leaderboardName,
|
||||
competitorID)
|
||||
@@ -35,7 +35,7 @@ public class CoreDataManager: NSObject {
|
||||
if results.count == 0 {
|
||||
return nil
|
||||
} else {
|
||||
return results[0] as? CheckIn
|
||||
return results[0] as? Regatta
|
||||
}
|
||||
} catch {
|
||||
print(error)
|
||||
@@ -43,46 +43,46 @@ public class CoreDataManager: NSObject {
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkInFetchedResultsController() -> NSFetchedResultsController {
|
||||
let fetchRequest = NSFetchRequest(entityName: "CheckIn")
|
||||
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "leaderboardName", ascending: true)]
|
||||
func regattaFetchedResultsController() -> NSFetchedResultsController {
|
||||
let fetchRequest = NSFetchRequest(entityName: "Regatta")
|
||||
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "leaderboard.name", ascending: true)]
|
||||
return NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: managedObjectContext!, sectionNameKeyPath: nil, cacheName: nil)
|
||||
}
|
||||
|
||||
// MARK: - Insert
|
||||
|
||||
func newCheckIn() -> CheckIn {
|
||||
return NSEntityDescription.insertNewObjectForEntityForName("CheckIn", inManagedObjectContext: managedObjectContext!) as! CheckIn
|
||||
func newRegatta() -> Regatta {
|
||||
return NSEntityDescription.insertNewObjectForEntityForName("Regatta", inManagedObjectContext: managedObjectContext!) as! Regatta
|
||||
}
|
||||
|
||||
func newEvent(checkIn: CheckIn) -> Event {
|
||||
func newEvent(regatta: Regatta) -> Event {
|
||||
let event = NSEntityDescription.insertNewObjectForEntityForName("Event", inManagedObjectContext: managedObjectContext!) as! Event
|
||||
event.checkIn = checkIn
|
||||
event.regatta = regatta
|
||||
return event
|
||||
}
|
||||
|
||||
func newLeaderBoard(checkIn: CheckIn) -> Leaderboard {
|
||||
let leaderBoard = NSEntityDescription.insertNewObjectForEntityForName("Leaderboard", inManagedObjectContext: managedObjectContext!) as! Leaderboard
|
||||
leaderBoard.checkIn = checkIn
|
||||
return leaderBoard
|
||||
func newLeaderboard(regatta: Regatta) -> Leaderboard {
|
||||
let leaderboard = NSEntityDescription.insertNewObjectForEntityForName("Leaderboard", inManagedObjectContext: managedObjectContext!) as! Leaderboard
|
||||
leaderboard.regatta = regatta
|
||||
return leaderboard
|
||||
}
|
||||
|
||||
func newCompetitor(checkIn: CheckIn) -> Competitor {
|
||||
func newCompetitor(regatta: Regatta) -> Competitor {
|
||||
let competitor = NSEntityDescription.insertNewObjectForEntityForName("Competitor", inManagedObjectContext: managedObjectContext!) as! Competitor
|
||||
competitor.checkIn = checkIn
|
||||
competitor.regatta = regatta
|
||||
return competitor
|
||||
}
|
||||
|
||||
func newGPSFix(checkIn: CheckIn) -> GPSFix {
|
||||
func newGPSFix(regatta: Regatta) -> GPSFix {
|
||||
let gpsFix = NSEntityDescription.insertNewObjectForEntityForName("GPSFix", inManagedObjectContext: managedObjectContext!) as! GPSFix
|
||||
gpsFix.checkIn = checkIn
|
||||
gpsFix.regatta = regatta
|
||||
return gpsFix
|
||||
}
|
||||
|
||||
// MARK: - Delete
|
||||
|
||||
func deleteCheckIn(checkIn: CheckIn) {
|
||||
managedObjectContext!.deleteObject(checkIn)
|
||||
func deleteRegatta(regatta: Regatta) {
|
||||
managedObjectContext!.deleteObject(regatta)
|
||||
}
|
||||
|
||||
func deleteGPSFixes(gpsFixes: [GPSFix]) {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Event+CoreDataProperties.swift
|
||||
// SAPTracker
|
||||
//
|
||||
// Created by Raimund Wege on 01.07.16.
|
||||
// Created by Raimund Wege on 04.07.16.
|
||||
// Copyright © 2016 com.sap.sailing. All rights reserved.
|
||||
//
|
||||
// Choose "Create NSManagedObject Subclass…" from the Core Data editor menu
|
||||
@@ -15,9 +15,9 @@ import CoreData
|
||||
extension Event {
|
||||
|
||||
@NSManaged var endDate: NSTimeInterval
|
||||
@NSManaged var eventID: String?
|
||||
@NSManaged var name: String?
|
||||
@NSManaged var eventID: String
|
||||
@NSManaged var name: String
|
||||
@NSManaged var startDate: NSTimeInterval
|
||||
@NSManaged var checkIn: CheckIn?
|
||||
@NSManaged var regatta: Regatta
|
||||
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
// Event.swift
|
||||
// SAPTracker
|
||||
//
|
||||
// Created by Raimund Wege on 30.06.16.
|
||||
// Created by Raimund Wege on 04.07.16.
|
||||
// Copyright © 2016 com.sap.sailing. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// GPSFix+CoreDataProperties.swift
|
||||
// SAPTracker
|
||||
//
|
||||
// Created by Raimund Wege on 01.07.16.
|
||||
// Created by Raimund Wege on 04.07.16.
|
||||
// Copyright © 2016 com.sap.sailing. All rights reserved.
|
||||
//
|
||||
// Choose "Create NSManagedObject Subclass…" from the Core Data editor menu
|
||||
@@ -19,6 +19,6 @@ extension GPSFix {
|
||||
@NSManaged var longitude: Double
|
||||
@NSManaged var speed: Double
|
||||
@NSManaged var timestamp: Double
|
||||
@NSManaged var checkIn: CheckIn?
|
||||
@NSManaged var regatta: Regatta
|
||||
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
// GPSFix.swift
|
||||
// SAPTracker
|
||||
//
|
||||
// Created by Raimund Wege on 30.06.16.
|
||||
// Created by Raimund Wege on 04.07.16.
|
||||
// Copyright © 2016 com.sap.sailing. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
@@ -17,24 +17,31 @@ class HomeViewController: UIViewController {
|
||||
@IBOutlet weak var noCodeButton: UIButton!
|
||||
@IBOutlet weak var infoCodeLabel: UILabel!
|
||||
|
||||
private var fetchedResultsController: NSFetchedResultsController?
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
setups()
|
||||
}
|
||||
|
||||
override func viewDidAppear(animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
reviews()
|
||||
subscribeForNewCheckInURLNotifications()
|
||||
}
|
||||
|
||||
override func viewWillDisappear(animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
unsubscribeFromNewCheckInURLNotifications()
|
||||
}
|
||||
|
||||
// MARK: - Setups
|
||||
|
||||
private func setups() {
|
||||
setupButtons()
|
||||
setupLanguage()
|
||||
setupNavigationBar()
|
||||
setupTableViewDataSource()
|
||||
subscribeForNotifications()
|
||||
checkEULA(NSNotification.init(name: "", object: nil))
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.unsubscribeForNotifications()
|
||||
}
|
||||
|
||||
// MARK: - Setups
|
||||
|
||||
private func setupButtons() {
|
||||
scanCodeButton.setBackgroundImage(Images.BlueHighlighted, forState: .Highlighted)
|
||||
noCodeButton.setBackgroundImage(Images.GrayHighlighted, forState: .Highlighted)
|
||||
@@ -53,45 +60,66 @@ class HomeViewController: UIViewController {
|
||||
}
|
||||
|
||||
private func setupTableViewDataSource() {
|
||||
fetchedResultsController = CoreDataManager.sharedManager.checkInFetchedResultsController()
|
||||
fetchedResultsController!.delegate = self
|
||||
do {
|
||||
try fetchedResultsController!.performFetch()
|
||||
try fetchedResultsController.performFetch()
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Reviews
|
||||
|
||||
func reviews() {
|
||||
if !Preferences.termsAccepted {
|
||||
reviewEULA()
|
||||
} else {
|
||||
reviewNewCheckIn()
|
||||
}
|
||||
}
|
||||
|
||||
func reviewEULA() {
|
||||
let alertTitle = NSLocalizedString("EULA_title", comment: "")
|
||||
let alertMessage = NSLocalizedString("EULA_content", comment: "")
|
||||
let alertController = UIAlertController(title: alertTitle, message: alertMessage, preferredStyle: .Alert)
|
||||
let viewTitle = NSLocalizedString("EULA_view", comment: "")
|
||||
let viewAction = UIAlertAction(title: viewTitle, style: .Cancel, handler: { action in
|
||||
UIApplication.sharedApplication().openURL(URLs.EULA)
|
||||
self.reviewEULA() // Reopen alert
|
||||
})
|
||||
let confirmTitle = NSLocalizedString("EULA_confirm", comment: "")
|
||||
let confirmAction = UIAlertAction(title: confirmTitle, style: .Default, handler: { action in
|
||||
Preferences.termsAccepted = true
|
||||
self.reviewNewCheckIn()
|
||||
})
|
||||
alertController.addAction(viewAction)
|
||||
alertController.addAction(confirmAction)
|
||||
presentViewController(alertController, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
func reviewNewCheckIn() {
|
||||
guard Preferences.termsAccepted else { return }
|
||||
guard let urlString = Preferences.newCheckInURL else { return }
|
||||
guard let checkInData = CheckInData(urlString: urlString) else { return }
|
||||
checkInController.startCheckIn(checkInData)
|
||||
}
|
||||
|
||||
// MARK: - Notifications
|
||||
|
||||
private func subscribeForNotifications() {
|
||||
private func subscribeForNewCheckInURLNotifications() {
|
||||
NSNotificationCenter.defaultCenter().addObserver(self,
|
||||
selector: #selector(HomeViewController.checkEULA(_:)),
|
||||
name: UIApplicationWillEnterForegroundNotification,
|
||||
selector: #selector(HomeViewController.newCheckInURLNotification(_:)),
|
||||
name: Preferences.NotificationType.NewCheckInURLChanged,
|
||||
object: nil)
|
||||
}
|
||||
|
||||
private func unsubscribeForNotifications() {
|
||||
private func unsubscribeFromNewCheckInURLNotifications() {
|
||||
NSNotificationCenter.defaultCenter().removeObserver(self)
|
||||
}
|
||||
|
||||
func checkEULA(notification: NSNotification) {
|
||||
if !Preferences.acceptedTerms {
|
||||
let alertTitle = NSLocalizedString("EULA_title", comment: "")
|
||||
let alertMessage = NSLocalizedString("EULA_content", comment: "")
|
||||
let alertController = UIAlertController(title: alertTitle, message: alertMessage, preferredStyle: .Alert)
|
||||
let viewTitle = NSLocalizedString("EULA_view", comment: "")
|
||||
let viewAction = UIAlertAction(title: viewTitle, style: .Cancel, handler: { action in
|
||||
UIApplication.sharedApplication().openURL(URLs.EULA)
|
||||
})
|
||||
let confirmTitle = NSLocalizedString("EULA_confirm", comment: "")
|
||||
let confirmAction = UIAlertAction(title: confirmTitle, style: .Default, handler: { action in
|
||||
Preferences.acceptedTerms = true
|
||||
})
|
||||
alertController.addAction(viewAction)
|
||||
alertController.addAction(confirmAction)
|
||||
self.presentViewController(alertController, animated: true, completion: nil)
|
||||
}
|
||||
func newCheckInURLNotification(notification: NSNotification) {
|
||||
dispatch_async(dispatch_get_main_queue(), {
|
||||
self.reviewNewCheckIn()
|
||||
})
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
@@ -148,13 +176,28 @@ class HomeViewController: UIViewController {
|
||||
|
||||
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
|
||||
if (segue.destinationViewController.isKindOfClass(RegattaViewController)) {
|
||||
let regattaVC = segue.destinationViewController as! RegattaViewController
|
||||
let indexPath = self.tableView.indexPathForSelectedRow
|
||||
regattaVC.checkIn = self.fetchedResultsController?.objectAtIndexPath(indexPath!) as? CheckIn
|
||||
self.tableView.deselectRowAtIndexPath(indexPath!, animated: true)
|
||||
guard let regattaVC = segue.destinationViewController as? RegattaViewController else { return }
|
||||
guard let indexPath = tableView.indexPathForSelectedRow else { return }
|
||||
guard let regatta = fetchedResultsController.objectAtIndexPath(indexPath) as? Regatta else { return }
|
||||
regattaVC.regatta = regatta
|
||||
tableView.deselectRowAtIndexPath(indexPath, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
lazy var checkInController: CheckInController = {
|
||||
let checkInController = CheckInController()
|
||||
checkInController.delegate = self
|
||||
return checkInController
|
||||
}()
|
||||
|
||||
lazy var fetchedResultsController: NSFetchedResultsController = {
|
||||
let fetchedResultsController = CoreDataManager.sharedManager.regattaFetchedResultsController()
|
||||
fetchedResultsController.delegate = self
|
||||
return fetchedResultsController
|
||||
}()
|
||||
|
||||
}
|
||||
|
||||
// MARK: - UITableViewDataSource
|
||||
@@ -162,18 +205,18 @@ class HomeViewController: UIViewController {
|
||||
extension HomeViewController: UITableViewDataSource {
|
||||
|
||||
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return fetchedResultsController!.sections![section].numberOfObjects
|
||||
return fetchedResultsController.sections?[section].numberOfObjects ?? 0
|
||||
}
|
||||
|
||||
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
|
||||
let cell = tableView.dequeueReusableCellWithIdentifier("Regatta") as UITableViewCell!
|
||||
let cell = tableView.dequeueReusableCellWithIdentifier("Regatta") ?? UITableViewCell()
|
||||
self.configureCell(cell, atIndexPath: indexPath)
|
||||
return cell
|
||||
}
|
||||
|
||||
func configureCell(cell: UITableViewCell, atIndexPath indexPath: NSIndexPath) {
|
||||
let checkIn = fetchedResultsController!.objectAtIndexPath(indexPath) as! CheckIn
|
||||
cell.textLabel?.text = checkIn.leaderboardName
|
||||
guard let regatta = fetchedResultsController.objectAtIndexPath(indexPath) as? Regatta else { return }
|
||||
cell.textLabel?.text = regatta.leaderboard.name
|
||||
}
|
||||
|
||||
}
|
||||
@@ -224,3 +267,17 @@ extension HomeViewController: NSFetchedResultsControllerDelegate {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - CheckInControllerDelegate
|
||||
|
||||
extension HomeViewController: CheckInControllerDelegate {
|
||||
|
||||
func showCheckInAlert(checkInController: CheckInController, alertController: UIAlertController) {
|
||||
presentViewController(alertController, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
func checkInDidEnd(checkInController: CheckInController, withSuccess succeed: Bool) {
|
||||
Preferences.newCheckInURL = nil
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
//
|
||||
// LeaderBoardViewController.swift
|
||||
// SAPTracker
|
||||
//
|
||||
// Created by computing on 08/12/14.
|
||||
// Copyright (c) 2014 com.sap.sailing. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class LeaderBoardViewController: UIViewController, UIWebViewDelegate, UIAlertViewDelegate {
|
||||
|
||||
weak var checkIn: CheckIn?
|
||||
|
||||
@IBOutlet weak var webView: UIWebView!
|
||||
@IBOutlet weak var activityIndicator: UIActivityIndicatorView!
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
let serverUrl = self.checkIn?.serverURL
|
||||
let leaderboardName = self.checkIn?.leaderboardName?.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())!
|
||||
let url = "\(serverUrl)/gwt/Leaderboard.html?name=\(leaderboardName)&showRaceDetails=false&embedded=true&hideToolbar=true"
|
||||
webView!.loadRequest(NSURLRequest(URL: NSURL(string: url)!))
|
||||
}
|
||||
|
||||
@IBAction func done(sender: AnyObject) {
|
||||
presentingViewController!.dismissViewControllerAnimated(true, completion: nil)
|
||||
}
|
||||
|
||||
func webViewDidFinishLoad(webView: UIWebView) {
|
||||
activityIndicator.stopAnimating()
|
||||
}
|
||||
|
||||
func wwebView(webView: UIWebView, didFailLoadWithError error: NSError) {
|
||||
activityIndicator.hidden = true
|
||||
let alertView = UIAlertView(title: NSLocalizedString("Couldn't load about view", comment: ""), message: nil, delegate: nil, cancelButtonTitle: NSLocalizedString("Cancel", comment: ""))
|
||||
alertView.show()
|
||||
}
|
||||
|
||||
func alertView(alertView: UIAlertView, clickedButtonAtIndex buttonIndex: Int) {
|
||||
presentingViewController!.dismissViewControllerAnimated(true, completion: nil)
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
// Leaderboard+CoreDataProperties.swift
|
||||
// SAPTracker
|
||||
//
|
||||
// Created by Raimund Wege on 01.07.16.
|
||||
// Created by Raimund Wege on 04.07.16.
|
||||
// Copyright © 2016 com.sap.sailing. All rights reserved.
|
||||
//
|
||||
// Choose "Create NSManagedObject Subclass…" from the Core Data editor menu
|
||||
@@ -14,7 +14,7 @@ import CoreData
|
||||
|
||||
extension Leaderboard {
|
||||
|
||||
@NSManaged var name: String?
|
||||
@NSManaged var checkIn: CheckIn?
|
||||
@NSManaged var name: String
|
||||
@NSManaged var regatta: Regatta
|
||||
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
// Leaderboard.swift
|
||||
// SAPTracker
|
||||
//
|
||||
// Created by Raimund Wege on 30.06.16.
|
||||
// Created by Raimund Wege on 04.07.16.
|
||||
// Copyright © 2016 com.sap.sailing. All rights reserved.
|
||||
//
|
||||
|
||||
@@ -12,6 +12,8 @@ import CoreData
|
||||
@objc(Leaderboard)
|
||||
class Leaderboard: NSManagedObject {
|
||||
|
||||
// Insert code here to add functionality to your managed object subclass
|
||||
func nameWithQueryAllowedCharacters() -> String? {
|
||||
return name.stringByAddingPercentEncodingWithAllowedCharacters(.URLQueryAllowedCharacterSet())
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// LeaderboardViewController.swift
|
||||
// SAPTracker
|
||||
//
|
||||
// Created by Raimund Wege on 04.07.16.
|
||||
// Copyright © 2016 com.sap.sailing. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
class LeaderboardViewController: UIViewController {
|
||||
|
||||
weak var regatta: Regatta?
|
||||
|
||||
@IBOutlet weak var webView: UIWebView!
|
||||
@IBOutlet weak var activityIndicator: UIActivityIndicatorView!
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
setupWebView()
|
||||
}
|
||||
|
||||
// MARK: - Setups
|
||||
|
||||
private func setupWebView() {
|
||||
guard let url = regatta?.leaderboardURL() else { return }
|
||||
webView.loadRequest(NSURLRequest(URL: url))
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
@IBAction func doneButtonTapped(sender: AnyObject) {
|
||||
presentingViewController!.dismissViewControllerAnimated(true, completion: nil)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - UIWebViewDelegate
|
||||
|
||||
extension LeaderboardViewController: UIWebViewDelegate {
|
||||
|
||||
func webViewDidFinishLoad(webView: UIWebView) {
|
||||
activityIndicator.stopAnimating()
|
||||
}
|
||||
|
||||
func webView(webView: UIWebView, didFailLoadWithError error: NSError?) {
|
||||
activityIndicator.stopAnimating()
|
||||
// FIXME: - Translation
|
||||
let alertTitle = NSLocalizedString("Couldn't load leaderboard view", comment: "")
|
||||
let alertController = UIAlertController(title: alertTitle, message: nil, preferredStyle: .Alert)
|
||||
let okTitle = NSLocalizedString("OK", comment: "")
|
||||
let okAction = UIAlertAction(title: okTitle, style: .Default) { (action) in
|
||||
self.presentingViewController!.dismissViewControllerAnimated(true, completion: nil)
|
||||
}
|
||||
alertController.addAction(okAction)
|
||||
presentViewController(alertController, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,35 +10,43 @@ import UIKit
|
||||
|
||||
class Preferences: NSObject {
|
||||
|
||||
struct NotificationType {
|
||||
static let NewCheckInURLChanged = "NewCheckInURLStringChanged"
|
||||
}
|
||||
|
||||
struct PreferenceKey {
|
||||
static let BatterySaving = "BatterySaving"
|
||||
static let LastCheckInURLString = "lastCheckInURLString"
|
||||
static let AcceptedTerms = "acceptedTerms"
|
||||
static let NewCheckInURL = "NewCheckInURL"
|
||||
static let TermsAccepted = "TermsAccepted"
|
||||
static let UUID = "udid"
|
||||
}
|
||||
|
||||
private static let preferences = NSUserDefaults.standardUserDefaults()
|
||||
|
||||
// MARK: - LastCheckInData
|
||||
// MARK: - NewCheckInURL
|
||||
|
||||
class var lastCheckInURLString: String? {
|
||||
class var newCheckInURL: String? {
|
||||
get {
|
||||
return preferences.stringForKey(PreferenceKey.LastCheckInURLString)
|
||||
return preferences.stringForKey(PreferenceKey.NewCheckInURL)
|
||||
}
|
||||
set(value) {
|
||||
preferences.setObject(value, forKey: PreferenceKey.LastCheckInURLString)
|
||||
preferences.setObject(value, forKey: PreferenceKey.NewCheckInURL)
|
||||
preferences.synchronize()
|
||||
|
||||
// Send notification
|
||||
let notification = NSNotification(name: NotificationType.NewCheckInURLChanged, object: self)
|
||||
NSNotificationQueue.defaultQueue().enqueueNotification(notification, postingStyle: NSPostingStyle.PostASAP)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - AcceptedTerms
|
||||
// MARK: - TermsAccepted
|
||||
|
||||
class var acceptedTerms: Bool {
|
||||
class var termsAccepted: Bool {
|
||||
get {
|
||||
return preferences.boolForKey(PreferenceKey.AcceptedTerms)
|
||||
return preferences.boolForKey(PreferenceKey.TermsAccepted)
|
||||
}
|
||||
set(value) {
|
||||
preferences.setBool(value, forKey:PreferenceKey.AcceptedTerms)
|
||||
preferences.setBool(value, forKey:PreferenceKey.TermsAccepted)
|
||||
preferences.synchronize()
|
||||
}
|
||||
}
|
||||
|
||||
+8
-12
@@ -1,8 +1,8 @@
|
||||
//
|
||||
// CheckIn+CoreDataProperties.swift
|
||||
// Regatta+CoreDataProperties.swift
|
||||
// SAPTracker
|
||||
//
|
||||
// Created by Raimund Wege on 01.07.16.
|
||||
// Created by Raimund Wege on 04.07.16.
|
||||
// Copyright © 2016 com.sap.sailing. All rights reserved.
|
||||
//
|
||||
// Choose "Create NSManagedObject Subclass…" from the Core Data editor menu
|
||||
@@ -12,19 +12,15 @@
|
||||
import Foundation
|
||||
import CoreData
|
||||
|
||||
extension CheckIn {
|
||||
extension Regatta {
|
||||
|
||||
@NSManaged var competitorID: String?
|
||||
@NSManaged var eventID: String?
|
||||
@NSManaged var teamImageURL: String?
|
||||
@NSManaged var lastSyncDate: NSTimeInterval
|
||||
@NSManaged var leaderboardName: String?
|
||||
@NSManaged var serverURL: String?
|
||||
@NSManaged var serverURL: String
|
||||
@NSManaged var teamImageData: NSData?
|
||||
@NSManaged var teamImageRetry: Bool
|
||||
@NSManaged var competitor: Competitor?
|
||||
@NSManaged var event: Event?
|
||||
@NSManaged var teamImageURL: String?
|
||||
@NSManaged var competitor: Competitor
|
||||
@NSManaged var event: Event
|
||||
@NSManaged var gpsFixes: NSSet?
|
||||
@NSManaged var leaderboard: Leaderboard?
|
||||
@NSManaged var leaderboard: Leaderboard
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// Regatta.swift
|
||||
// SAPTracker
|
||||
//
|
||||
// Created by Raimund Wege on 04.07.16.
|
||||
// Copyright © 2016 com.sap.sailing. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
|
||||
@objc(Regatta)
|
||||
class Regatta: NSManagedObject {
|
||||
|
||||
func eventURL() -> NSURL? {
|
||||
return NSURL(string: "\(serverURL)/gwt/Home.html?navigationTab=Regattas#EventPlace:eventId=\(event.eventID)")
|
||||
}
|
||||
|
||||
func leaderboardURL() -> NSURL? {
|
||||
guard let name = leaderboard.nameWithQueryAllowedCharacters() else { return nil }
|
||||
return NSURL(string: "\(serverURL)/gwt/Leaderboard.html?name=\(name)&showRaceDetails=false&embedded=true&hideToolbar=true")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -37,17 +37,18 @@ class RegattaViewController : UIViewController, UINavigationControllerDelegate {
|
||||
@IBOutlet weak var startTrackingButton: UIButton!
|
||||
@IBOutlet weak var announcementsLabel: UILabel!
|
||||
|
||||
var checkIn: CheckIn!
|
||||
var regatta: Regatta!
|
||||
var requestManager: RequestManager!
|
||||
|
||||
var countdownTimer: NSTimer?
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
requestManager = RequestManager(baseURLString: checkIn!.serverURL)
|
||||
requestManager = RequestManager(baseURLString: regatta.serverURL)
|
||||
setupButtons()
|
||||
setupCompetitor()
|
||||
setupCountdownTimer()
|
||||
setupNavigationBar()
|
||||
setupImageSourceTypes()
|
||||
setupTeamImage()
|
||||
}
|
||||
@@ -61,9 +62,9 @@ class RegattaViewController : UIViewController, UINavigationControllerDelegate {
|
||||
}
|
||||
|
||||
private func setupCompetitor() {
|
||||
competitorNameLabel.text = checkIn?.competitor?.name ?? ""
|
||||
competitorFlagImageView.image = UIImage(named: checkIn?.competitor?.countryCode ?? "")
|
||||
competitorSailLabel.text = checkIn?.competitor?.sailID ?? ""
|
||||
competitorNameLabel.text = regatta.competitor.name
|
||||
competitorFlagImageView.image = UIImage(named: regatta.competitor.countryCode)
|
||||
competitorSailLabel.text = regatta.competitor.sailID
|
||||
}
|
||||
|
||||
private func setupCountdownTimer() {
|
||||
@@ -87,11 +88,15 @@ class RegattaViewController : UIViewController, UINavigationControllerDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
private func setupNavigationBar() {
|
||||
navigationItem.title = regatta.leaderboard.name
|
||||
}
|
||||
|
||||
private func setupTeamImage() {
|
||||
if checkIn.teamImageData != nil {
|
||||
setupTeamImageWithImageData(checkIn.teamImageData)
|
||||
} else if checkIn.teamImageURL != nil {
|
||||
setupTeamImageWithURL(checkIn.teamImageURL)
|
||||
if regatta.teamImageData != nil {
|
||||
setupTeamImageWithImageData(regatta.teamImageData)
|
||||
} else if regatta.teamImageURL != nil {
|
||||
setupTeamImageWithURL(regatta.teamImageURL)
|
||||
} else {
|
||||
setupTeamImageFinished()
|
||||
}
|
||||
@@ -115,8 +120,8 @@ class RegattaViewController : UIViewController, UINavigationControllerDelegate {
|
||||
|
||||
private func setupTeamImageWithURLSuccess(image: UIImage) {
|
||||
teamImageView.image = image
|
||||
checkIn.teamImageData = UIImageJPEGRepresentation(image, 0.8)
|
||||
checkIn.teamImageRetry = false
|
||||
regatta.teamImageData = UIImageJPEGRepresentation(image, 0.8)
|
||||
regatta.teamImageRetry = false
|
||||
CoreDataManager.sharedManager.saveContext()
|
||||
setupTeamImageFinished()
|
||||
}
|
||||
@@ -126,9 +131,9 @@ class RegattaViewController : UIViewController, UINavigationControllerDelegate {
|
||||
}
|
||||
|
||||
private func setupTeamImageFinished() {
|
||||
if checkIn.teamImageData != nil {
|
||||
if regatta.teamImageData != nil {
|
||||
teamImageAddButton.hidden = true
|
||||
teamImageEditButton.hidden = checkIn.teamImageRetry
|
||||
teamImageEditButton.hidden = regatta.teamImageRetry
|
||||
teamImageRetryButton.hidden = !teamImageEditButton.hidden
|
||||
} else {
|
||||
teamImageAddButton.hidden = false
|
||||
@@ -140,23 +145,21 @@ class RegattaViewController : UIViewController, UINavigationControllerDelegate {
|
||||
// MARK: - Refresh
|
||||
|
||||
func refreshCountdown() {
|
||||
if let event = checkIn.event {
|
||||
if event.startDate - NSDate().timeIntervalSince1970 > 0 {
|
||||
regattaStartLabel.text = NSLocalizedString("Regatta will start in", comment: "")
|
||||
let duration = event.startDate - NSDate().timeIntervalSince1970
|
||||
let days = Int(duration / (60 * 60 * 24))
|
||||
let hours = Int(duration / (60 * 60)) - (days * 24)
|
||||
let minutes = Int(duration / 60) - (days * 24 * 60) - (hours * 60)
|
||||
countdownDaysLabel.text = String(format: "%02d", days)
|
||||
countdownHoursLabel.text = String(format: "%02d", hours)
|
||||
countdownMinutesLabel.text = String(format: "%02d", minutes)
|
||||
countdownView.hidden = false
|
||||
countdownViewHeight.constant = 60
|
||||
} else {
|
||||
regattaStartLabel.text = NSLocalizedString("Regatta in progress", comment: "")
|
||||
countdownView.hidden = true
|
||||
countdownViewHeight.constant = 0
|
||||
}
|
||||
if regatta.event.startDate - NSDate().timeIntervalSince1970 > 0 {
|
||||
regattaStartLabel.text = NSLocalizedString("Regatta will start in", comment: "")
|
||||
let duration = regatta.event.startDate - NSDate().timeIntervalSince1970
|
||||
let days = Int(duration / (60 * 60 * 24))
|
||||
let hours = Int(duration / (60 * 60)) - (days * 24)
|
||||
let minutes = Int(duration / 60) - (days * 24 * 60) - (hours * 60)
|
||||
countdownDaysLabel.text = String(format: "%02d", days)
|
||||
countdownHoursLabel.text = String(format: "%02d", hours)
|
||||
countdownMinutesLabel.text = String(format: "%02d", minutes)
|
||||
countdownView.hidden = false
|
||||
countdownViewHeight.constant = 60
|
||||
} else {
|
||||
regattaStartLabel.text = NSLocalizedString("Regatta in progress", comment: "")
|
||||
countdownView.hidden = true
|
||||
countdownViewHeight.constant = 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,14 +174,12 @@ class RegattaViewController : UIViewController, UINavigationControllerDelegate {
|
||||
}
|
||||
|
||||
@IBAction func teamImageRetryButtonTapped(sender: AnyObject) {
|
||||
postTeamImageData(checkIn.teamImageData)
|
||||
postTeamImageData(regatta.teamImageData)
|
||||
}
|
||||
|
||||
@IBAction func eventButtonTapped(sender: UIButton) {
|
||||
let serverURL = checkIn.serverURL!
|
||||
let eventID = checkIn.eventID!
|
||||
let urlString = "\(serverURL)/gwt/Home.html?navigationTab=Regattas#EventPlace:eventId=\(eventID)"
|
||||
let url = NSURL(string: urlString)!
|
||||
// FIXME: - Alert?
|
||||
guard let url = regatta.eventURL() else { return }
|
||||
UIApplication.sharedApplication().openURL(url)
|
||||
}
|
||||
|
||||
@@ -259,12 +260,12 @@ class RegattaViewController : UIViewController, UINavigationControllerDelegate {
|
||||
}
|
||||
|
||||
func preformCheckOut() {
|
||||
requestManager.postCheckOut(checkIn.leaderboardName,
|
||||
competitorId: checkIn.competitorID,
|
||||
requestManager.postCheckOut(regatta.leaderboard.name,
|
||||
competitorId: regatta.competitor.competitorID,
|
||||
success: { (operation, responseObject) in },
|
||||
failure: { (operation, error) in
|
||||
})
|
||||
CoreDataManager.sharedManager.deleteCheckIn(self.checkIn!)
|
||||
CoreDataManager.sharedManager.deleteRegatta(regatta!)
|
||||
CoreDataManager.sharedManager.saveContext()
|
||||
navigationController!.popViewControllerAnimated(true)
|
||||
}
|
||||
@@ -275,7 +276,7 @@ class RegattaViewController : UIViewController, UINavigationControllerDelegate {
|
||||
if (segue.identifier == "Tracking") {
|
||||
let nc = segue.destinationViewController as! UINavigationController
|
||||
let vc = nc.viewControllers[0] as! TrackingViewController
|
||||
vc.checkIn = checkIn
|
||||
vc.regatta = regatta
|
||||
}
|
||||
}
|
||||
|
||||
@@ -300,14 +301,14 @@ extension RegattaViewController: UIImagePickerControllerDelegate {
|
||||
teamImageAddButton.hidden = true
|
||||
teamImageEditButton.hidden = false
|
||||
teamImageRetryButton.hidden = true
|
||||
checkIn.teamImageData = UIImageJPEGRepresentation(image, 0.8)
|
||||
regatta.teamImageData = UIImageJPEGRepresentation(image, 0.8)
|
||||
CoreDataManager.sharedManager.saveContext()
|
||||
postTeamImageData(checkIn.teamImageData)
|
||||
postTeamImageData(regatta.teamImageData)
|
||||
}
|
||||
|
||||
private func postTeamImageData(imageData: NSData!) {
|
||||
requestManager.postTeamImageData(imageData,
|
||||
competitorId: checkIn.competitorID,
|
||||
competitorId: regatta.competitor.competitorID,
|
||||
success: { (responseObject) in self.postTeamImageSuccess(responseObject) },
|
||||
failure: { (error) in self.postTeamImageFailure(error) })
|
||||
}
|
||||
@@ -317,8 +318,8 @@ extension RegattaViewController: UIImagePickerControllerDelegate {
|
||||
// Save image URL and upload success
|
||||
let teamImageDictionary = responseObject as! [String: AnyObject]
|
||||
let teamImageURL = (teamImageDictionary[TeamImageKeys.TeamImageURL]) as! String
|
||||
checkIn.teamImageURL = teamImageURL
|
||||
checkIn.teamImageRetry = false
|
||||
regatta.teamImageURL = teamImageURL
|
||||
regatta.teamImageRetry = false
|
||||
CoreDataManager.sharedManager.saveContext()
|
||||
|
||||
// Setup team image
|
||||
@@ -328,7 +329,7 @@ extension RegattaViewController: UIImagePickerControllerDelegate {
|
||||
private func postTeamImageFailure(error: AnyObject) {
|
||||
|
||||
// Save image upload failure
|
||||
checkIn.teamImageRetry = true
|
||||
regatta.teamImageRetry = true
|
||||
CoreDataManager.sharedManager.saveContext()
|
||||
|
||||
// Show alert
|
||||
|
||||
@@ -36,11 +36,11 @@ class RequestManager: NSObject {
|
||||
static let IOS = "iOS"
|
||||
}
|
||||
|
||||
let baseURLString: String!
|
||||
let manager: AFHTTPRequestOperationManager!
|
||||
let sessionManager: AFURLSessionManager!
|
||||
let baseURLString: String
|
||||
let manager: AFHTTPRequestOperationManager
|
||||
let sessionManager: AFURLSessionManager
|
||||
|
||||
init(baseURLString: String!) {
|
||||
init(baseURLString: String = "") {
|
||||
self.baseURLString = baseURLString
|
||||
manager = AFHTTPRequestOperationManager(baseURL: NSURL(string: baseURLString))
|
||||
manager.requestSerializer = AFJSONRequestSerializer() as AFHTTPRequestSerializer
|
||||
@@ -54,7 +54,8 @@ class RequestManager: NSObject {
|
||||
|
||||
func getEvent(eventID: String!,
|
||||
success: (AFHTTPRequestOperation!, AnyObject!) -> Void,
|
||||
failure: (AFHTTPRequestOperation!, AnyObject!) -> Void) {
|
||||
failure: (AFHTTPRequestOperation!, AnyObject!) -> Void)
|
||||
{
|
||||
let encodedEventID = eventID.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLPathAllowedCharacterSet()) ?? ""
|
||||
let urlString = "\(basePathString)/events/\(encodedEventID)"
|
||||
manager.GET(urlString, parameters: nil, success: success, failure: failure)
|
||||
|
||||
@@ -14,7 +14,7 @@ class ScanViewController: UIViewController {
|
||||
@IBOutlet weak var previewView: UIView!
|
||||
@IBOutlet weak var targetImageView: UIImageView!
|
||||
|
||||
private var checkInController: CheckInController?
|
||||
private let checkInController = CheckInController()
|
||||
|
||||
private var session: AVCaptureSession!
|
||||
private var output: AVCaptureMetadataOutput!
|
||||
@@ -22,36 +22,41 @@ class ScanViewController: UIViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
self.setupSession()
|
||||
setupCheckInController()
|
||||
setupSession()
|
||||
}
|
||||
|
||||
override func viewWillAppear(animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
self.startScanning()
|
||||
startScanning()
|
||||
}
|
||||
|
||||
// MARK: - Setups
|
||||
|
||||
private func setupCheckInController() {
|
||||
checkInController.delegate = self
|
||||
}
|
||||
|
||||
private func setupSession() {
|
||||
self.session = AVCaptureSession()
|
||||
self.output = AVCaptureMetadataOutput()
|
||||
session = AVCaptureSession()
|
||||
output = AVCaptureMetadataOutput()
|
||||
do {
|
||||
let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
|
||||
let input = try AVCaptureDeviceInput(device: device);
|
||||
self.output.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
|
||||
self.session.canSetSessionPreset(AVCaptureSessionPresetHigh)
|
||||
output.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
|
||||
session.canSetSessionPreset(AVCaptureSessionPresetHigh)
|
||||
if session.canAddInput(input) {
|
||||
session.addInput(input)
|
||||
}
|
||||
if session.canAddOutput(output) {
|
||||
session.addOutput(output)
|
||||
}
|
||||
self.output.metadataObjectTypes = [AVMetadataObjectTypeQRCode]
|
||||
self.previewLayer = AVCaptureVideoPreviewLayer(session: self.session)
|
||||
self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
|
||||
self.previewLayer.frame = previewView.bounds
|
||||
self.previewLayer.position = CGPointMake(CGRectGetMidX(previewView.bounds), CGRectGetMidY(previewView.bounds))
|
||||
self.previewView.layer.addSublayer(previewLayer)
|
||||
output.metadataObjectTypes = [AVMetadataObjectTypeQRCode]
|
||||
previewLayer = AVCaptureVideoPreviewLayer(session: self.session)
|
||||
previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
|
||||
previewLayer.frame = previewView.bounds
|
||||
previewLayer.position = CGPointMake(CGRectGetMidX(previewView.bounds), CGRectGetMidY(previewView.bounds))
|
||||
previewView.layer.addSublayer(previewLayer)
|
||||
} catch {
|
||||
print(error)
|
||||
}
|
||||
@@ -75,14 +80,14 @@ class ScanViewController: UIViewController {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
|
||||
self.session.startRunning()
|
||||
})
|
||||
self.targetImageView.image = UIImage(named: "scan_white")
|
||||
targetImageView.image = UIImage(named: "scan_white")
|
||||
}
|
||||
|
||||
private func stopScanning() {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
|
||||
self.session.stopRunning()
|
||||
})
|
||||
self.targetImageView.image = UIImage(named: "scan_green")
|
||||
targetImageView.image = UIImage(named: "scan_green")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -97,9 +102,9 @@ extension ScanViewController: CheckInControllerDelegate {
|
||||
|
||||
func checkInDidEnd(checkInController: CheckInController, withSuccess succeed: Bool) {
|
||||
if succeed {
|
||||
self.navigationController?.popViewControllerAnimated(true)
|
||||
navigationController?.popViewControllerAnimated(true)
|
||||
} else {
|
||||
self.startScanning()
|
||||
startScanning()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,9 +121,8 @@ extension ScanViewController: AVCaptureMetadataOutputObjectsDelegate {
|
||||
if metadataObjects.count > 0 {
|
||||
let metadataObject: AVMetadataMachineReadableCodeObject = metadataObjects[0] as! AVMetadataMachineReadableCodeObject
|
||||
if let checkInData = CheckInData(urlString: metadataObject.stringValue) {
|
||||
self.stopScanning()
|
||||
checkInController = CheckInController(checkInData: checkInData, delegate: self)
|
||||
checkInController!.startCheckIn()
|
||||
stopScanning()
|
||||
checkInController.startCheckIn(checkInData)
|
||||
} else {
|
||||
let alertTitle = NSLocalizedString("Incorrect QR Code", comment: "")
|
||||
let alertController = UIAlertController(title: alertTitle, message: "", preferredStyle: .Alert)
|
||||
|
||||
@@ -15,14 +15,14 @@ class SendGPSFixesController: NSObject {
|
||||
static let BatterySaving: NSTimeInterval = 30
|
||||
}
|
||||
|
||||
private let checkIn: CheckIn!
|
||||
private let regatta: Regatta!
|
||||
private let requestManager: RequestManager!
|
||||
|
||||
private var isRunning: Bool = false
|
||||
|
||||
init(checkIn: CheckIn) {
|
||||
self.checkIn = checkIn
|
||||
requestManager = RequestManager(baseURLString: checkIn.serverURL)
|
||||
init(regatta: Regatta) {
|
||||
self.regatta = regatta
|
||||
requestManager = RequestManager(baseURLString: regatta.serverURL)
|
||||
super.init()
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ class SendGPSFixesController: NSObject {
|
||||
dispatch_async(dispatch_get_main_queue(), {
|
||||
if let userInfo = notification.userInfo {
|
||||
if userInfo[LocationManager.UserInfo.IsValid] as? Bool ?? false {
|
||||
let gpsFix = CoreDataManager.sharedManager.newGPSFix(self.checkIn)
|
||||
let gpsFix = CoreDataManager.sharedManager.newGPSFix(self.regatta)
|
||||
gpsFix.course = userInfo[LocationManager.UserInfo.Course] as! Double
|
||||
gpsFix.latitude = userInfo[LocationManager.UserInfo.Latitude] as! Double
|
||||
gpsFix.longitude = userInfo[LocationManager.UserInfo.Longitude] as! Double
|
||||
@@ -72,10 +72,8 @@ class SendGPSFixesController: NSObject {
|
||||
|
||||
func sendGPSFixes() {
|
||||
var gpsFixes = [GPSFix]()
|
||||
if checkIn.gpsFixes != nil {
|
||||
checkIn.gpsFixes!.forEach { (gpsFix) in
|
||||
gpsFixes.append(gpsFix as! GPSFix)
|
||||
}
|
||||
if regatta.gpsFixes != nil {
|
||||
regatta.gpsFixes!.forEach { (gpsFix) in gpsFixes.append(gpsFix as! GPSFix) }
|
||||
}
|
||||
if gpsFixes.count > 0 {
|
||||
log("\(gpsFixes.count) GPS fixes will be sent")
|
||||
|
||||
@@ -10,7 +10,7 @@ import Foundation
|
||||
|
||||
class TrackingViewController : UIViewController {
|
||||
|
||||
var checkIn: CheckIn?
|
||||
var regatta: Regatta?
|
||||
|
||||
@IBOutlet weak var tableView: UITableView!
|
||||
@IBOutlet weak var tableViewHeight: NSLayoutConstraint!
|
||||
@@ -18,8 +18,7 @@ class TrackingViewController : UIViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
setupButtons()
|
||||
setupNavigationBarTitle()
|
||||
setups()
|
||||
}
|
||||
|
||||
override func updateViewConstraints() {
|
||||
@@ -29,12 +28,17 @@ class TrackingViewController : UIViewController {
|
||||
|
||||
// MARK: - Setups
|
||||
|
||||
private func setups() {
|
||||
setupButtons()
|
||||
setupNavigationBar()
|
||||
}
|
||||
|
||||
private func setupButtons() {
|
||||
stopTrackingButton.setBackgroundImage(Images.RedHighlighted, forState: .Highlighted)
|
||||
}
|
||||
|
||||
private func setupNavigationBarTitle() {
|
||||
navigationItem.title = checkIn?.leaderboardName
|
||||
private func setupNavigationBar() {
|
||||
navigationItem.title = regatta?.leaderboard.name
|
||||
}
|
||||
|
||||
// MARK: - Actions
|
||||
@@ -85,7 +89,7 @@ extension TrackingViewController: UITableViewDataSource {
|
||||
let cell = tableView.dequeueReusableCellWithIdentifier(TrackingViewController.Rows[indexPath.row]) ?? UITableViewCell()
|
||||
if (cell.isKindOfClass(CachedFixesTrackingTableViewCell)) {
|
||||
let cachedFixesCell = cell as! CachedFixesTrackingTableViewCell
|
||||
cachedFixesCell.checkIn = checkIn
|
||||
cachedFixesCell.regatta = regatta
|
||||
}
|
||||
return cell
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user