From 02e7efbf5839d96983b8e5461d94591cabeb7447 Mon Sep 17 00:00:00 2001 From: merlos Date: Sun, 28 May 2023 11:22:49 +0300 Subject: [PATCH 01/27] Implement toast --- OpenGpxTracker/Toast.swift | 191 +++++++++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 OpenGpxTracker/Toast.swift diff --git a/OpenGpxTracker/Toast.swift b/OpenGpxTracker/Toast.swift new file mode 100644 index 0000000..cb08a48 --- /dev/null +++ b/OpenGpxTracker/Toast.swift @@ -0,0 +1,191 @@ +// +// Toast.swift +// OpenGpxTracker +// +// Created by Merlos on 5/28/23. +// + +import Foundation +import UIKit + +/// Supporting UILabel for Toast. +class ToastLabel: UILabel { + var textInsets = UIEdgeInsets.zero { + didSet { invalidateIntrinsicContentSize() } + } + override func textRect(forBounds bounds: CGRect, limitedToNumberOfLines numberOfLines: Int) -> CGRect { + let insetRect = bounds.inset(by: textInsets) + let textRect = super.textRect(forBounds: insetRect, limitedToNumberOfLines: numberOfLines) + let invertedInsets = UIEdgeInsets(top: -textInsets.top, left: -textInsets.left, bottom: -textInsets.bottom, right: -textInsets.right) + return textRect.inset(by: invertedInsets) + } + override func drawText(in rect: CGRect) { + super.drawText(in: rect.inset(by: textInsets)) + } +} + + +/// +/// Display a toast message in a label for a few seconds and dissapears +/// +/// Usage: +/// +/// Toast.regular("My message") // It accepts delay in seconds and position (.top, .center .bottom) +/// +/// // There are .info, .warning, .error and .success toasts. +/// Toast.info("My message", position: .top, delay: 10) +/// +/// Originally extracted from https://stackoverflow.com/questions/31540375/how-to-create-a-toast-message-in-swift +/// +class Toast { + + /// Short delay + static let kDelayShort = 2.0 + + /// Long delay + static let kDelayLong = 5.0 + + /// Background opacity + static let kBackgroundOpacity: Double = 0.9 + + /// height of the toast + static let kToastHeight = 20 + + /// withd of the toast + static let kToastWidth = 24 + + /// Offset from the closest screen edge (top or bottom). + static let kToastOffset = 120 + + /// Font size of the toast + static let kFontSize = 16 + + /// Toast.regular text color + static let kRegularTextColor: UIColor = UIColor(ciColor: .white) + /// Toast.regular background color + static let kRegularBackgroundColor: UIColor = UIColor(ciColor: .black) + + /// Toast.info text color + static let kInfoTextColor: UIColor = UIColor(ciColor: .white) + /// Toast.info background color + static let kInfoBackgroundColor: UIColor = UIColor(red: 0/255, green: 100/255, blue: 225/255, alpha: kBackgroundOpacity) + + /// Toast.success text color + static let kSuccessTextColor: UIColor = UIColor(ciColor: .white) + /// Toast.success background color + static let kSuccessBackgroundColor: UIColor = UIColor(red: 0/255, green: 150/255, blue: 0/255, alpha: kBackgroundOpacity) + + /// Toast.warning text color + static let kWarningTextColor: UIColor = UIColor(ciColor: .black) + + static let kWarningBackgroundColor: UIColor = UIColor(red: 255/255, green: 175/255, blue: 0/255, alpha: kBackgroundOpacity) + + /// Toast.error text color + static let kErrorTextColor: UIColor = UIColor(ciColor: .white) + /// Toast.error background color + static let kErrorBackgroundColor: UIColor = UIColor(red: 175/255, green: 0/255, blue: 0/255, alpha: kBackgroundOpacity) + + + /// Position of the toast in the vertical access + enum Position { + case bottom + case center + case top + } + + /// + /// Generic implementation to show toast + /// - Parameters: + /// - message: Text message to display + /// - textColor: Color of the text + /// - backgroundColor: Color of the text + /// - position: Position within the screen (.bottom, .center, .top) + /// - delay: time in seconds that the toast will be displayed + static func showToast(_ message: String, textColor: UIColor, backgroundColor: UIColor, position: Position, delay: Double) { + guard let window = UIApplication.shared.keyWindow else { + return + } + let label = ToastLabel() + label.textColor = textColor + label.backgroundColor = backgroundColor + label.textAlignment = .center + label.font = UIFont.systemFont(ofSize: CGFloat(kFontSize)) + label.alpha = 0 + label.text = message + label.numberOfLines = 0 + var vertical: CGFloat = 0 + var size = label.intrinsicContentSize + var width = min(size.width, window.frame.width - 60) + if width != size.width { + vertical = 1000 + label.textAlignment = .justified + } + label.textInsets = UIEdgeInsets(top: vertical, left: 15, bottom: vertical, right: 15) + size = label.intrinsicContentSize + width = min(size.width, window.frame.width - 60) + + if (position == Position.bottom) { + label.frame = CGRect(x: CGFloat(kToastWidth), y: window.frame.height - CGFloat(kToastOffset), width: width, height: size.height + CGFloat(kToastHeight)) + } else if (position == Position.center) { + label.frame = CGRect(x: CGFloat(kToastWidth), y: window.frame.height / 2, width: width, height: size.height + CGFloat(kToastHeight)) + } else if (position == Position.top) { + label.frame = CGRect(x: CGFloat(kToastWidth), y: CGFloat(kToastOffset), width: width, height: size.height + CGFloat(kToastHeight)) + } + + label.center.x = window.center.x + label.layer.cornerRadius = min(label.frame.height / 2, 32) + label.layer.masksToBounds = true + window.addSubview(label) + UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseIn, animations: { + label.alpha = 1 + }, completion: { _ in + UIView.animate(withDuration: 0.5, delay: delay, options: .curveEaseOut, animations: { + label.alpha = 0 + }, completion: {_ in + label.removeFromSuperview() + }) + }) + } + + /// + /// Displays a regular toast (black) + /// - SeeAlso showToast + /// + class func regular(_ message: String, position: Position = Position.bottom, delay: Double = kDelayLong) { + showToast(message, textColor: kRegularTextColor, backgroundColor: kRegularBackgroundColor, position: position, delay:delay) + } + + /// + /// Information toast (blue) + /// + /// - SeeAlso showToast + class func info(_ message: String, position: Position = Position.bottom, delay: Double = kDelayLong) { + showToast(String("\u{24D8}")+" "+message, textColor: kInfoTextColor, backgroundColor: kInfoBackgroundColor, position:position, delay:delay) + } + + /// + /// Display a warning toast (orange) + /// + /// - SeeAlso showToast + class func warning(_ message: String, position: Position = Position.bottom, delay: Double = kDelayLong) { + showToast(String("\u{26A0}")+" "+message, textColor: kWarningTextColor, backgroundColor: kWarningBackgroundColor, position: position, delay: delay) + } + + /// + /// Display a Success toast + /// + /// - SeeAlso showToast + class func success(_ message: String, position: Position = Position.bottom, delay: Double = kDelayLong) { + showToast(String("\u{2705}")+" "+message, textColor: kSuccessTextColor, backgroundColor: kSuccessBackgroundColor, position: position, delay:delay) + } + + /// + /// Display a error toast + /// + /// - SeeAlso showToast + class func error(_ message: String, position: Position = Position.bottom, delay: Double = kDelayLong) {//2757 + showToast(String("\u{274C}")+" "+message, textColor: kErrorTextColor, backgroundColor: kErrorBackgroundColor, position: position, delay: delay) + } + +} + From 40432474032218c88fdc94b6963f1d58c667046f Mon Sep 17 00:00:00 2001 From: merlos Date: Sun, 28 May 2023 11:25:11 +0300 Subject: [PATCH 02/27] auto load last session --- OpenGpxTracker/CoreDataHelper.swift | 33 ++++++----------------------- 1 file changed, 6 insertions(+), 27 deletions(-) diff --git a/OpenGpxTracker/CoreDataHelper.swift b/OpenGpxTracker/CoreDataHelper.swift index 5e559d0..9c9c19a 100644 --- a/OpenGpxTracker/CoreDataHelper.swift +++ b/OpenGpxTracker/CoreDataHelper.swift @@ -384,35 +384,13 @@ class CoreDataHelper { root.add(track: track) } root.waypoints = self.waypoints + // asks user on what to do with recovered data DispatchQueue.main.sync { - // for debugging - // print(root.gpx()) - - // main action sheet setup - let alertController = UIAlertController(title: NSLocalizedString("CONTINUE_SESSION_TITLE", comment: "no comment"), - message: NSLocalizedString("CONTINUE_SESSION_MESSAGE", comment: "no comment"), - preferredStyle: .actionSheet) - - // option to cancel - let cancelAction = UIAlertAction(title: NSLocalizedString("CANCEL", comment: "no comment"), style: .cancel) { _ in - self.clearAll() - } - // option to continue previous session, which will load it, but not save - let continueAction = UIAlertAction(title: NSLocalizedString("CONTINUE_SESSION", comment: "no comment"), style: .default) { _ in - NotificationCenter.default.post(name: .loadRecoveredFile, object: nil, - userInfo: ["recoveredRoot": root, "fileName": self.lastFileName]) - } - - // option to save silently as file, session remains new - let saveAction = UIAlertAction(title: NSLocalizedString("SAVE_START_NEW", comment: "no comment"), style: .default) { _ in - self.saveFile(from: root, andIfAvailable: self.lastFileName) - } - - alertController.addAction(cancelAction) - alertController.addAction(continueAction) - alertController.addAction(saveAction) - CoreDataAlertView().showActionSheet(alertController) + NotificationCenter.default.post(name: .loadRecoveredFile, object: nil, + userInfo: ["recoveredRoot": root, "fileName": self.lastFileName]) + let toastMessage = NSLocalizedString("LAST_SESSION_LOADED", comment: "the filename displayed after the text") + " " + self.lastFileName + Toast.regular(toastMessage, position: .top) } } else { // no recovery file will be generated if nothing is recovered (or did not crash). @@ -421,6 +399,7 @@ class CoreDataHelper { } /// saves recovered data to a gpx file, silently, without loading on map. + func saveFile(from gpx: GPXRoot, andIfAvailable lastfileName: String) { // date format same as usual. let dateFormatter = DateFormatter() From 0c02dae29a8a8ccffeb71c0e1b24da93dd1b6f87 Mon Sep 17 00:00:00 2001 From: merlos Date: Sun, 28 May 2023 11:26:25 +0300 Subject: [PATCH 03/27] ensure only tracks are removed if there is one at least --- OpenGpxTracker/GPXSession.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/OpenGpxTracker/GPXSession.swift b/OpenGpxTracker/GPXSession.swift index b888f8f..ddb86c3 100644 --- a/OpenGpxTracker/GPXSession.swift +++ b/OpenGpxTracker/GPXSession.swift @@ -157,7 +157,9 @@ class GPXSession { self.trackSegments = lastTrack.segments // remove last track as that track is packaged by Core Data, but should its tracksegments should be seperated, into self.tracksegments. - self.tracks.removeLast() + if self.tracks.count > 0 { + self.tracks.removeLast() + } } From f475f7e34dd3b09e17acaa3b19832e58edc9861a Mon Sep 17 00:00:00 2001 From: merlos Date: Sun, 28 May 2023 11:26:40 +0300 Subject: [PATCH 04/27] remove some spaces --- OpenGpxTracker/CoreDataHelper+BatchDelete.swift | 2 -- OpenGpxTracker/CoreDataHelper+FetchRequests.swift | 13 +++++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/OpenGpxTracker/CoreDataHelper+BatchDelete.swift b/OpenGpxTracker/CoreDataHelper+BatchDelete.swift index d13bde2..7157db8 100644 --- a/OpenGpxTracker/CoreDataHelper+BatchDelete.swift +++ b/OpenGpxTracker/CoreDataHelper+BatchDelete.swift @@ -36,7 +36,6 @@ extension CoreDataHelper { } catch { print("Failed to delete all from core data, error: \(error)") } - } } @@ -75,6 +74,5 @@ extension CoreDataHelper { } catch let error { print("NSAsynchronousFetchRequest (while deleting \(T.self) error: \(error)") } - } } diff --git a/OpenGpxTracker/CoreDataHelper+FetchRequests.swift b/OpenGpxTracker/CoreDataHelper+FetchRequests.swift index f9685a7..a575c0a 100644 --- a/OpenGpxTracker/CoreDataHelper+FetchRequests.swift +++ b/OpenGpxTracker/CoreDataHelper+FetchRequests.swift @@ -16,11 +16,13 @@ extension CoreDataHelper { guard let rootResults = asynchronousFetchResult.finalResult else { return } DispatchQueue.main.async { + print("Core Data Helper: fetching recoverable CDRoot") guard let objectID = rootResults.last?.objectID else { self.lastFileName = ""; return } guard let safePoint = self.appDelegate.managedObjectContext.object(with: objectID) as? CDRoot else { self.lastFileName = ""; return } self.lastFileName = safePoint.lastFileName ?? "" self.lastTracksegmentId = safePoint.lastTrackSegmentId self.isContinued = safePoint.continuedAfterSave + print("Core Data Helper: fetched CDRoot lastFileName:\(self.lastFileName) lastTracksegmentId: \(self.lastTracksegmentId) isContinued: \(self.isContinued)") } } return asyncRootFetchRequest @@ -36,7 +38,7 @@ extension CoreDataHelper { // Creates `asynchronousFetchRequest` with the fetch request and the completion closure let asynchronousTrackPointFetchRequest = NSAsynchronousFetchRequest(fetchRequest: trkptFetchRequest) { asynchronousFetchResult in - print("Core Data Helper: fetching recoverable trackpoints from Core Data") + print("Core Data Helper: fetching recoverable CDTrackpoints") guard let trackPointResults = asynchronousFetchResult.finalResult else { return } // Dispatches to use the data in the main queue @@ -68,9 +70,9 @@ extension CoreDataHelper { } self.trackpointId = trackPointResults.last?.trackpointId ?? Int64() self.tracksegments.append(self.currentSegment) + print("Core Data Helper: fetched CDTrackpoints. # of tracksegments: \(self.tracksegments.count). trackPointId: \(self.trackpointId) trackSegmentId: \(self.tracksegmentId)") } } - return asynchronousTrackPointFetchRequest } @@ -81,7 +83,7 @@ extension CoreDataHelper { let asynchronousWaypointFetchRequest = NSAsynchronousFetchRequest(fetchRequest: wptFetchRequest) { asynchronousFetchResult in - print("Core Data Helper: fetching recoverable waypoints from Core Data") + print("Core Data Helper: fetching recoverable CDWaypoints") // Retrieves an array of points from Core Data guard let waypointResults = asynchronousFetchResult.finalResult else { return } @@ -102,19 +104,18 @@ extension CoreDataHelper { if safePoint.elevation != .greatestFiniteMagnitude { pt.elevation = safePoint.elevation } - + self.waypoints.append(pt) } - self.waypointId = waypointResults.last?.waypointId ?? Int64() // trackpoint request first, followed by waypoint request // hence, crashFileRecovery method is ran in this. self.crashFileRecovery() // should always be in the LAST fetch request! + print("Core Data Helper: fetched \(self.waypoints.count) CDWaypoints ") print("Core Data Helper: async fetches complete.") } } - return asynchronousWaypointFetchRequest } From 08fd727e8faff2905cd814808d58267ac33d7dac Mon Sep 17 00:00:00 2001 From: merlos Date: Sun, 28 May 2023 11:27:04 +0300 Subject: [PATCH 05/27] remove map view print user interaction --- OpenGpxTracker/MapViewDelegate.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenGpxTracker/MapViewDelegate.swift b/OpenGpxTracker/MapViewDelegate.swift index 651c5ad..436c848 100644 --- a/OpenGpxTracker/MapViewDelegate.swift +++ b/OpenGpxTracker/MapViewDelegate.swift @@ -205,7 +205,7 @@ class MapViewDelegate: NSObject, MKMapViewDelegate, UIAlertViewDelegate { guard let map = mapView as? GPXMapView else { return } - print("MapView: User interaction has ended") + //print("MapView: User interaction has ended") map.updateHeading() From 9118dd948883ded35f98fff0108b7a061e96e305 Mon Sep 17 00:00:00 2001 From: merlos Date: Sun, 28 May 2023 11:27:39 +0300 Subject: [PATCH 06/27] update all localizable strings using ChatGPT translation --- OpenGpxTracker.xcodeproj/project.pbxproj | 6 +++++- OpenGpxTracker/PreferencesTableViewController.swift | 11 +++++------ OpenGpxTracker/de.lproj/Localizable.strings | 3 +++ OpenGpxTracker/en.lproj/Localizable.strings | 4 ++-- OpenGpxTracker/es.lproj/Localizable.strings | 3 +++ OpenGpxTracker/fi-FI.lproj/Localizable.strings | 3 +++ OpenGpxTracker/fr.lproj/Localizable.strings | 3 +++ OpenGpxTracker/it.lproj/Localizable.strings | 5 ++++- OpenGpxTracker/nl.lproj/Localizable.strings | 3 +++ OpenGpxTracker/pt-BR.lproj/Localizable.strings | 4 ++++ OpenGpxTracker/uk.lproj/Localizable.strings | 3 +++ OpenGpxTracker/zh-Hans.lproj/Localizable.strings | 4 +++- 12 files changed, 41 insertions(+), 11 deletions(-) diff --git a/OpenGpxTracker.xcodeproj/project.pbxproj b/OpenGpxTracker.xcodeproj/project.pbxproj index bd81fc9..1e34340 100644 --- a/OpenGpxTracker.xcodeproj/project.pbxproj +++ b/OpenGpxTracker.xcodeproj/project.pbxproj @@ -19,6 +19,7 @@ 8913CD8E1BDB2477009EC729 /* PreferencesTableViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8913CD8D1BDB2477009EC729 /* PreferencesTableViewControllerDelegate.swift */; }; 893BEC8619C7E62200C77354 /* GPXWaypoint+MKAnnotation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 893BEC8519C7E62200C77354 /* GPXWaypoint+MKAnnotation.swift */; }; 895F04B41A7143CE004BEE8A /* GPXExtentCoordinates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 895F04B31A7143CE004BEE8A /* GPXExtentCoordinates.swift */; }; + 897056132A230AAF0004F133 /* Toast.swift in Sources */ = {isa = PBXBuildFile; fileRef = 897056122A230AAF0004F133 /* Toast.swift */; }; 898EECDB19C49B5800B4B207 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 898EECDA19C49B5800B4B207 /* AppDelegate.swift */; }; 898EECDE19C49B5800B4B207 /* OpenGpxTracker.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 898EECDC19C49B5800B4B207 /* OpenGpxTracker.xcdatamodeld */; }; 898EECE019C49B5800B4B207 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 898EECDF19C49B5800B4B207 /* ViewController.swift */; }; @@ -189,6 +190,7 @@ 892A57402838A865003FE8C5 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/InfoPlist.strings; sourceTree = ""; }; 893BEC8519C7E62200C77354 /* GPXWaypoint+MKAnnotation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "GPXWaypoint+MKAnnotation.swift"; sourceTree = ""; }; 895F04B31A7143CE004BEE8A /* GPXExtentCoordinates.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GPXExtentCoordinates.swift; sourceTree = ""; }; + 897056122A230AAF0004F133 /* Toast.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toast.swift; sourceTree = ""; }; 898E2BDD23129FE000DC4E3F /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Main.strings; sourceTree = ""; }; 898E2BDE23129FE000DC4E3F /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Interface.strings; sourceTree = ""; }; 898E2BDF23129FE000DC4E3F /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; @@ -332,7 +334,6 @@ 895F04B31A7143CE004BEE8A /* GPXExtentCoordinates.swift */, 89F8749A1BBB7362004EF41A /* GPXTrack+length.swift */, 89F8749E1BBCB97F004EF41A /* GPXRoot+length.swift */, - BFE026C1244A01DB005423E6 /* UIInsetLabel.swift */, 89EA86602157A08E002E03A7 /* Date+timeAgo.swift */, 89EA86642157C444002E03A7 /* Int+asFilesize.swift */, 89EA86622157B42C002E03A7 /* GPXFileInfo.swift */, @@ -342,6 +343,7 @@ BF214B5D22E60B64000E96AA /* CLActivityType+Info.swift */, BF15092123916FC100F51F1B /* UIColor+DarkMode.swift */, BFB06F01244A037300AC0CDC /* UIColor+Keyboard.swift */, + BFE026C1244A01DB005423E6 /* UIInsetLabel.swift */, BFE026BF244A0160005423E6 /* String+CountInstances.swift */, BFE026C3244A0281005423E6 /* DateField.swift */, BF9AE57D2410012700B103A0 /* DefaultDateFormat.swift */, @@ -457,6 +459,7 @@ DC4908A01C4A136F009484AE /* TrackerButton.swift */, BFE026C5244A02A4005423E6 /* DatePatternButton.swift */, BF68ECC52448B887005C779F /* DateFieldTypeView.swift */, + 897056122A230AAF0004F133 /* Toast.swift */, ); name = Views; sourceTree = ""; @@ -855,6 +858,7 @@ 893BEC8619C7E62200C77354 /* GPXWaypoint+MKAnnotation.swift in Sources */, DC4908A31C4A332E009484AE /* MapViewDelegate.swift in Sources */, 898EED3619C6402900B4B207 /* GPXFilesTableViewController.swift in Sources */, + 897056132A230AAF0004F133 /* Toast.swift in Sources */, DC4908A11C4A136F009484AE /* TrackerButton.swift in Sources */, 89F8749F1BBCB97F004EF41A /* GPXRoot+length.swift in Sources */, ); diff --git a/OpenGpxTracker/PreferencesTableViewController.swift b/OpenGpxTracker/PreferencesTableViewController.swift index b213610..f040684 100644 --- a/OpenGpxTracker/PreferencesTableViewController.swift +++ b/OpenGpxTracker/PreferencesTableViewController.swift @@ -119,7 +119,7 @@ class PreferencesTableViewController: UITableViewController, UINavigationBarDele case kMapSourceSection: return NSLocalizedString("MAP_SOURCE", comment: "no comment") case kActivityTypeSection: return NSLocalizedString("ACTIVITY_TYPE", comment: "no comment") case kDefaultNameSection: return NSLocalizedString("DEFAULT_NAME_SECTION", comment: "no comment") - case kGPXFilesLocationSection: return NSLocalizedString("GPX_FILES_LOCATION_SECTION", comment: "no comment") + case kGPXFilesLocationSection: return NSLocalizedString("GPX_FILES_FOLDER", comment: "no comment") default: fatalError("Unknown section") } } @@ -221,13 +221,12 @@ class PreferencesTableViewController: UITableViewController, UINavigationBarDele } if indexPath.section == kGPXFilesLocationSection { - cell = UITableViewCell(style: .subtitle, reuseIdentifier: "GPXFilesLocation") - cell.textLabel?.text = NSLocalizedString("PRESS_TO_SELECT_FOLDER", comment: "no comment") + cell = UITableViewCell(style: .value1, reuseIdentifier: "GPXFilesLocation") if let url = preferences.gpxFilesFolderURL { - cell.detailTextLabel?.lineBreakMode = .byTruncatingHead - cell.detailTextLabel?.text = url.lastPathComponent + //cell.textLabel?.lineBreakMode = .byTruncatingHead + cell.textLabel?.text = url.lastPathComponent } else { - cell.detailTextLabel?.text = NSLocalizedString("USING_DEFAULT_FOLDER", comment: "no comment") + cell.textLabel?.text = NSLocalizedString("USING_DEFAULT_FOLDER", comment: "no comment") } cell.accessoryType = .disclosureIndicator } diff --git a/OpenGpxTracker/de.lproj/Localizable.strings b/OpenGpxTracker/de.lproj/Localizable.strings index 6a4a0c7..6855f88 100644 --- a/OpenGpxTracker/de.lproj/Localizable.strings +++ b/OpenGpxTracker/de.lproj/Localizable.strings @@ -43,6 +43,9 @@ "CACHE_IS_EMPTY" = "Die Cache ist jetzt leer"; "EDIT_WAYPOINT_NAME_TITLE" = "Wegpunkt ändern"; "EDIT_WAYPOINT_NAME_MESSAGE" = "Hinweis: Um einen Wegpunkt zu verändern, verschiebe den Pin."; +"GPX_FILES_FOLDER" = "GPX-Dateien-Ordner"; +"USING_DEFAULT_FOLDER" = "Standardordner verwenden"; +"LAST_SESSION_LOADED" = "Letzte Sitzung geladen"; // Watch "SENDING" = "Sende:"; diff --git a/OpenGpxTracker/en.lproj/Localizable.strings b/OpenGpxTracker/en.lproj/Localizable.strings index fffad78..4531b44 100644 --- a/OpenGpxTracker/en.lproj/Localizable.strings +++ b/OpenGpxTracker/en.lproj/Localizable.strings @@ -44,9 +44,9 @@ "CACHE_IS_EMPTY" = "Cache is now empty"; "EDIT_WAYPOINT_NAME_TITLE" = "Edit waypoint name"; "EDIT_WAYPOINT_NAME_MESSAGE" = "Hint: To change the waypoint location drag and drop the pin"; -"GPX_FILES_LOCATION_SECTION" = "GPX files location"; -"PRESS_TO_SELECT_FOLDER" = "Press to select folder"; +"GPX_FILES_FOLDER" = "GPX files folder"; "USING_DEFAULT_FOLDER" = "Using default folder"; +"LAST_SESSION_LOADED" = "Last session loaded"; // Watch "SENDING" = "Sending:"; diff --git a/OpenGpxTracker/es.lproj/Localizable.strings b/OpenGpxTracker/es.lproj/Localizable.strings index 3a4b626..2e2e53b 100644 --- a/OpenGpxTracker/es.lproj/Localizable.strings +++ b/OpenGpxTracker/es.lproj/Localizable.strings @@ -44,6 +44,9 @@ "CACHE_IS_EMPTY" = "La caché está ahora vacía"; "EDIT_WAYPOINT_NAME_TITLE" = "Editar punto de interés"; "EDIT_WAYPOINT_NAME_MESSAGE" = "Sugerencia: arrastra y suelta el pin para mover el punto."; +"GPX_FILES_FOLDER" = "Carpeta de ficheros GPX"; +"USING_DEFAULT_FOLDER" = "Usando carpeta por defecto"; +"LAST_SESSION_LOADED" = "Última sesión recuperada"; // Watch "SENDING" = "Enviando:"; diff --git a/OpenGpxTracker/fi-FI.lproj/Localizable.strings b/OpenGpxTracker/fi-FI.lproj/Localizable.strings index 94241f5..d1c7543 100644 --- a/OpenGpxTracker/fi-FI.lproj/Localizable.strings +++ b/OpenGpxTracker/fi-FI.lproj/Localizable.strings @@ -44,6 +44,9 @@ Created by Phiilman on 28.03.20. "CACHE_IS_EMPTY" = "Välimuisti on tyhjä"; "EDIT_WAYPOINT_NAME_TITLE" = "Nimeä merkkipiste"; "EDIT_WAYPOINT_NAME_MESSAGE" = "Vihje: Vedä ja pudota nuppineulaa siirtääksesi merkin paikkaa."; +"GPX_FILES_FOLDER" = "GPX-tiedostojen kansio"; +"USING_DEFAULT_FOLDER" = "Käytetään oletuskansiota"; +"LAST_SESSION_LOADED" = "Viimeisin istunto ladattu"; // Watch "SENDING" = "Lähettää:"; diff --git a/OpenGpxTracker/fr.lproj/Localizable.strings b/OpenGpxTracker/fr.lproj/Localizable.strings index 1983b3a..8c15665 100644 --- a/OpenGpxTracker/fr.lproj/Localizable.strings +++ b/OpenGpxTracker/fr.lproj/Localizable.strings @@ -45,6 +45,9 @@ "CACHE_IS_EMPTY" = "Le cache est actuellement vide"; "EDIT_WAYPOINT_NAME_TITLE" = "Editer le nom du point de repère"; "EDIT_WAYPOINT_NAME_MESSAGE" = "Conseil: pour changer la position du point de repère, glissez-déposez l'épingle"; +"GPX_FILES_FOLDER" = "Dossier des fichiers GPX"; +"USING_DEFAULT_FOLDER" = "Utilisation du dossier par défaut"; +"LAST_SESSION_LOADED" = "Dernière session chargée"; // Watch "SENDING" = "Envoi en cours:"; diff --git a/OpenGpxTracker/it.lproj/Localizable.strings b/OpenGpxTracker/it.lproj/Localizable.strings index 4854524..8fbd97c 100644 --- a/OpenGpxTracker/it.lproj/Localizable.strings +++ b/OpenGpxTracker/it.lproj/Localizable.strings @@ -43,6 +43,9 @@ "CACHE_IS_EMPTY" = "La Cache ora è vuota"; "EDIT_WAYPOINT_NAME_TITLE" = "Cambia intersezioni"; "EDIT_WAYPOINT_NAME_MESSAGE" = "Nota: per modificare una intersezione, spostare il segnaposto."; +"GPX_FILES_FOLDER" = "Cartella dei file GPX"; +"USING_DEFAULT_FOLDER" = "Utilizzo della cartella predefinita"; +"LAST_SESSION_LOADED" = "Ultima sessione caricata"; // Watch "SENDING" = "Invia:"; @@ -120,4 +123,4 @@ "DEFAULT_NAME_SAMPLE_OUTPUT_TITLE" = "Esempio: "; "DEFAULT_NAME_USE_UTC" = "Usare fuso orario UTC?"; -"DEFAULT_NAME_ENGLISH_LOCALE" = "Forza la formattazione della data basata sulla lingua inglese?"; \ No newline at end of file +"DEFAULT_NAME_ENGLISH_LOCALE" = "Forza la formattazione della data basata sulla lingua inglese?"; diff --git a/OpenGpxTracker/nl.lproj/Localizable.strings b/OpenGpxTracker/nl.lproj/Localizable.strings index f43c397..28fc1cf 100644 --- a/OpenGpxTracker/nl.lproj/Localizable.strings +++ b/OpenGpxTracker/nl.lproj/Localizable.strings @@ -44,6 +44,9 @@ "CACHE_IS_EMPTY" = "Cache is nu verwijderd"; "EDIT_WAYPOINT_NAME_TITLE" = "Waypoint naam wijzigen"; "EDIT_WAYPOINT_NAME_MESSAGE" = "Tip: Om het the waypoint te wijzigen drag en drop de locatie pin."; +"GPX_FILES_FOLDER" = "GPX-bestandenmap"; +"USING_DEFAULT_FOLDER" = "Gebruik standaardmap"; +"LAST_SESSION_LOADED" = "Laatste sessie geladen"; // Watch "SENDING" = "Aan het versturen:"; diff --git a/OpenGpxTracker/pt-BR.lproj/Localizable.strings b/OpenGpxTracker/pt-BR.lproj/Localizable.strings index 7d18766..4ca5587 100644 --- a/OpenGpxTracker/pt-BR.lproj/Localizable.strings +++ b/OpenGpxTracker/pt-BR.lproj/Localizable.strings @@ -45,6 +45,10 @@ "CACHE_IS_EMPTY" = "Cache vazio"; "EDIT_WAYPOINT_NAME_TITLE" = "Edite o nome do ponto"; "EDIT_WAYPOINT_NAME_MESSAGE" = "Dica: Para alterar a localização do ponto arraste o pin"; +"GPX_FILES_FOLDER" = "Pasta de arquivos GPX"; +"USING_DEFAULT_FOLDER" = "Usando pasta padrão"; +"LAST_SESSION_LOADED" = "Última sessão carregada"; + // Watch "SENDING" = "Enviando:"; diff --git a/OpenGpxTracker/uk.lproj/Localizable.strings b/OpenGpxTracker/uk.lproj/Localizable.strings index 5b3a8f8..b628618 100644 --- a/OpenGpxTracker/uk.lproj/Localizable.strings +++ b/OpenGpxTracker/uk.lproj/Localizable.strings @@ -44,6 +44,9 @@ "CACHE_IS_EMPTY" = "Кеш порожній"; "EDIT_WAYPOINT_NAME_TITLE" = "Редагувати назву маршрутної точки"; "EDIT_WAYPOINT_NAME_MESSAGE" = "Підказка: щоб змініти місце розташування маршрутної точки, перетягніть шпильку"; +"GPX_FILES_FOLDER" = "Папка з файлами GPX"; +"USING_DEFAULT_FOLDER" = "Використання типової папки"; +"LAST_SESSION_LOADED" = "Остання сесія завантажена"; // Watch "SENDING" = "Надсилання:"; diff --git a/OpenGpxTracker/zh-Hans.lproj/Localizable.strings b/OpenGpxTracker/zh-Hans.lproj/Localizable.strings index 75584bd..069b936 100644 --- a/OpenGpxTracker/zh-Hans.lproj/Localizable.strings +++ b/OpenGpxTracker/zh-Hans.lproj/Localizable.strings @@ -48,7 +48,9 @@ "CACHE_IS_EMPTY" = "高速缓存已被清空。"; "EDIT_WAYPOINT_NAME_TITLE" = "改变导航点名"; "EDIT_WAYPOINT_NAME_MESSAGE" = "暗示:要更改导航点位置吗?您只需要把地图上的红色针图案,拖和搬到新位置。"; - +"GPX_FILES_FOLDER" = "GPX文件夹"; +"USING_DEFAULT_FOLDER" = "使用默认文件夹"; +"LAST_SESSION_LOADED" = "加载上次会话"; // Watch "SENDING" = "正在发送中:"; "X_FILES" = "%d 个文件"; From bce670bd38151ae4fd99d40454eb9a4c0f34e642 Mon Sep 17 00:00:00 2001 From: merlos Date: Sun, 28 May 2023 21:26:34 +0300 Subject: [PATCH 07/27] fix swiftlint issue in arm64 chips --- OpenGpxTracker.xcodeproj/project.pbxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenGpxTracker.xcodeproj/project.pbxproj b/OpenGpxTracker.xcodeproj/project.pbxproj index 1e34340..b444f6e 100644 --- a/OpenGpxTracker.xcodeproj/project.pbxproj +++ b/OpenGpxTracker.xcodeproj/project.pbxproj @@ -790,7 +790,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "if which swiftlint >/dev/null; then\nswiftlint\nelse\necho \"SwiftLint does not exist, download from https://github.com/realm/SwiftLint\"\nfi\n"; + shellScript = "if [[ \"$(uname -m)\" == arm64 ]]; then\n export PATH=\"/opt/homebrew/bin:$PATH\"\nfi\n\nif which swiftlint >/dev/null; then\nswiftlint\nelse\necho \"SwiftLint does not exist, download from https://github.com/realm/SwiftLint\"\nfi\n"; }; ED9A4042AD567E254EB31430 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; From 884a2eec3bb6182ef03f0fb64b8354443d00045f Mon Sep 17 00:00:00 2001 From: merlos Date: Sun, 28 May 2023 21:44:36 +0300 Subject: [PATCH 08/27] remove CoreDataAlertView (no longer being used) --- OpenGpxTracker.xcodeproj/project.pbxproj | 4 ---- OpenGpxTracker/CoreDataAlertView.swift | 30 ------------------------ 2 files changed, 34 deletions(-) delete mode 100644 OpenGpxTracker/CoreDataAlertView.swift diff --git a/OpenGpxTracker.xcodeproj/project.pbxproj b/OpenGpxTracker.xcodeproj/project.pbxproj index b444f6e..516f6be 100644 --- a/OpenGpxTracker.xcodeproj/project.pbxproj +++ b/OpenGpxTracker.xcodeproj/project.pbxproj @@ -82,7 +82,6 @@ BF692F892209B82500F8A0F1 /* StopWatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 899D677119CE8B3600C88A0A /* StopWatch.swift */; }; BF9AE57C2410011D00B103A0 /* DefaultNameSetupViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF9AE57B2410011D00B103A0 /* DefaultNameSetupViewController.swift */; }; BF9AE57E2410012700B103A0 /* DefaultDateFormat.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF9AE57D2410012700B103A0 /* DefaultDateFormat.swift */; }; - BFA3CE8222C23B2300A8B965 /* CoreDataAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFA3CE8122C23B2300A8B965 /* CoreDataAlertView.swift */; }; BFB06F02244A037300AC0CDC /* UIColor+Keyboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFB06F01244A037300AC0CDC /* UIColor+Keyboard.swift */; }; BFE026C0244A0160005423E6 /* String+CountInstances.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFE026BF244A0160005423E6 /* String+CountInstances.swift */; }; BFE026C2244A01DB005423E6 /* UIInsetLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFE026C1244A01DB005423E6 /* UIInsetLabel.swift */; }; @@ -262,7 +261,6 @@ BF692F702209AAFC00F8A0F1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; BF9AE57B2410011D00B103A0 /* DefaultNameSetupViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultNameSetupViewController.swift; sourceTree = ""; }; BF9AE57D2410012700B103A0 /* DefaultDateFormat.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultDateFormat.swift; sourceTree = ""; }; - BFA3CE8122C23B2300A8B965 /* CoreDataAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataAlertView.swift; sourceTree = ""; }; BFB06F01244A037300AC0CDC /* UIColor+Keyboard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Keyboard.swift"; sourceTree = ""; }; BFE026BF244A0160005423E6 /* String+CountInstances.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+CountInstances.swift"; sourceTree = ""; }; BFE026C1244A01DB005423E6 /* UIInsetLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIInsetLabel.swift; sourceTree = ""; }; @@ -455,7 +453,6 @@ children = ( 899D677E19D2366100C88A0A /* GPXMapView.swift */, BF5C0D2122D771D0001C2575 /* DistanceLabel.swift */, - BFA3CE8122C23B2300A8B965 /* CoreDataAlertView.swift */, DC4908A01C4A136F009484AE /* TrackerButton.swift */, BFE026C5244A02A4005423E6 /* DatePatternButton.swift */, BF68ECC52448B887005C779F /* DateFieldTypeView.swift */, @@ -838,7 +835,6 @@ BF177EEA24D54F9200D5E021 /* CoreDataHelper+BatchDelete.swift in Sources */, BFB06F02244A037300AC0CDC /* UIColor+Keyboard.swift in Sources */, 12491EA328D7057D009F6BE1 /* MKMapView+ConvenientOverlayInserts.swift in Sources */, - BFA3CE8222C23B2300A8B965 /* CoreDataAlertView.swift in Sources */, 899D678219D351DA00C88A0A /* AboutViewController.swift in Sources */, 89EA86612157A08E002E03A7 /* Date+timeAgo.swift in Sources */, 895F04B41A7143CE004BEE8A /* GPXExtentCoordinates.swift in Sources */, diff --git a/OpenGpxTracker/CoreDataAlertView.swift b/OpenGpxTracker/CoreDataAlertView.swift deleted file mode 100644 index 5aef892..0000000 --- a/OpenGpxTracker/CoreDataAlertView.swift +++ /dev/null @@ -1,30 +0,0 @@ -// -// CoreDataAlertView.swift -// OpenGpxTracker -// -// Created by Vincent on 25/6/19. -// - -import UIKit - -/// To display Core Data alert action sheet anywhere when needed. -/// -/// It should display anywhere possible, in case if a gpx file loads too long when file recovery with previous session's file is too big. -struct CoreDataAlertView { - - /// shows the action sheet that prompts user on what to do with recovered data. - func showActionSheet(_ alertController: UIAlertController) { - guard let appDelegate = UIApplication.shared.delegate else { return } - guard let rootVC = appDelegate.window!?.rootViewController else { return } - - if let popoverController = alertController.popoverPresentationController { - guard let view = rootVC.view else { return } - popoverController.sourceView = view - popoverController.sourceRect = CGRect(x: view.bounds.midX, y: view.bounds.midY, width: 0, height: 0) - popoverController.permittedArrowDirections = [] - } - - rootVC.present(alertController, animated: true, completion: nil) - } - -} From 7cf4b83c6d7d15605a6c2acd93f6e1067aba2d45 Mon Sep 17 00:00:00 2001 From: merlos Date: Sun, 28 May 2023 21:44:53 +0300 Subject: [PATCH 09/27] fix some lint issues in toast --- OpenGpxTracker/Toast.swift | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/OpenGpxTracker/Toast.swift b/OpenGpxTracker/Toast.swift index cb08a48..575a042 100644 --- a/OpenGpxTracker/Toast.swift +++ b/OpenGpxTracker/Toast.swift @@ -24,7 +24,6 @@ class ToastLabel: UILabel { } } - /// /// Display a toast message in a label for a few seconds and dissapears /// @@ -85,7 +84,6 @@ class Toast { /// Toast.error background color static let kErrorBackgroundColor: UIColor = UIColor(red: 175/255, green: 0/255, blue: 0/255, alpha: kBackgroundOpacity) - /// Position of the toast in the vertical access enum Position { case bottom @@ -93,6 +91,7 @@ class Toast { case top } + /// /// Generic implementation to show toast /// - Parameters: @@ -124,14 +123,16 @@ class Toast { size = label.intrinsicContentSize width = min(size.width, window.frame.width - 60) - if (position == Position.bottom) { - label.frame = CGRect(x: CGFloat(kToastWidth), y: window.frame.height - CGFloat(kToastOffset), width: width, height: size.height + CGFloat(kToastHeight)) - } else if (position == Position.center) { + if position == Position.bottom { + label.frame = CGRect(x: CGFloat(kToastWidth), + y: window.frame.height - CGFloat(kToastOffset), + width: width, + height: size.height + CGFloat(kToastHeight)) + } else if position == Position.center { label.frame = CGRect(x: CGFloat(kToastWidth), y: window.frame.height / 2, width: width, height: size.height + CGFloat(kToastHeight)) - } else if (position == Position.top) { + } else if position == Position.top { label.frame = CGRect(x: CGFloat(kToastWidth), y: CGFloat(kToastOffset), width: width, height: size.height + CGFloat(kToastHeight)) } - label.center.x = window.center.x label.layer.cornerRadius = min(label.frame.height / 2, 32) label.layer.masksToBounds = true @@ -152,7 +153,7 @@ class Toast { /// - SeeAlso showToast /// class func regular(_ message: String, position: Position = Position.bottom, delay: Double = kDelayLong) { - showToast(message, textColor: kRegularTextColor, backgroundColor: kRegularBackgroundColor, position: position, delay:delay) + showToast(message, textColor: kRegularTextColor, backgroundColor: kRegularBackgroundColor, position: position, delay: delay) } /// @@ -160,7 +161,8 @@ class Toast { /// /// - SeeAlso showToast class func info(_ message: String, position: Position = Position.bottom, delay: Double = kDelayLong) { - showToast(String("\u{24D8}")+" "+message, textColor: kInfoTextColor, backgroundColor: kInfoBackgroundColor, position:position, delay:delay) + showToast(String("\u{24D8}")+" "+message, textColor: kInfoTextColor, backgroundColor: kInfoBackgroundColor, + position: position, delay: delay) } /// @@ -168,7 +170,8 @@ class Toast { /// /// - SeeAlso showToast class func warning(_ message: String, position: Position = Position.bottom, delay: Double = kDelayLong) { - showToast(String("\u{26A0}")+" "+message, textColor: kWarningTextColor, backgroundColor: kWarningBackgroundColor, position: position, delay: delay) + showToast(String("\u{26A0}")+" "+message, textColor: kWarningTextColor, backgroundColor: kWarningBackgroundColor, + position: position, delay: delay) } /// From 5ea8b449f3a97650a0a4568f4ce9b566a60fbaa5 Mon Sep 17 00:00:00 2001 From: merlos Date: Sun, 28 May 2023 22:39:45 +0300 Subject: [PATCH 10/27] fix warning variable_name has been renamed to identifier_name --- .swiftlint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.swiftlint.yml b/.swiftlint.yml index 49a318e..a94e833 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -1,7 +1,7 @@ disabled_rules: - trailing_whitespace - nesting - - variable_name + - identifier_name excluded: - Pods From 7f29316bd1b32e48a3e21caaeaff42fd935e4365 Mon Sep 17 00:00:00 2001 From: merlos Date: Sun, 28 May 2023 22:40:27 +0300 Subject: [PATCH 11/27] fix error that prevented to compile due too long body in viewcontroller --- .swiftlint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.swiftlint.yml b/.swiftlint.yml index a94e833..8dffe8a 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -12,7 +12,7 @@ line_length: 150 # try and remove these after we refactor some concerns out of the main view controller type_body_length: - 300 # warning - - 665 # error + - 800 # error function_body_length: - 40 - 246 From 1f1b4c671c4577f1362eada33cdaa0bf0a0da713 Mon Sep 17 00:00:00 2001 From: merlos Date: Sun, 28 May 2023 22:42:02 +0300 Subject: [PATCH 12/27] fixed warning that mentioned that swiftlint did not have outputs --- OpenGpxTracker.xcodeproj/project.pbxproj | 40 +++++++++++++++++++----- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/OpenGpxTracker.xcodeproj/project.pbxproj b/OpenGpxTracker.xcodeproj/project.pbxproj index 516f6be..6360a28 100644 --- a/OpenGpxTracker.xcodeproj/project.pbxproj +++ b/OpenGpxTracker.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -777,6 +777,7 @@ }; DC6FB8E11C49DF2C00B378D4 /* SwiftLint */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -1116,7 +1117,8 @@ IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; @@ -1133,7 +1135,10 @@ DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = OpenGpxTracker/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 12.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); MARKETING_VERSION = 1.8.0; PRODUCT_BUNDLE_IDENTIFIER = org.merlos.OpenGpxTracker; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1154,7 +1159,10 @@ DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = OpenGpxTracker/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 12.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); MARKETING_VERSION = 1.8.0; PRODUCT_BUNDLE_IDENTIFIER = org.merlos.OpenGpxTracker; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1178,7 +1186,11 @@ "$(inherited)", ); INFOPLIST_FILE = OpenGpxTrackerTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); PRODUCT_BUNDLE_IDENTIFIER = "org.transitbox.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; @@ -1196,7 +1208,11 @@ "$(inherited)", ); INFOPLIST_FILE = OpenGpxTrackerTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); PRODUCT_BUNDLE_IDENTIFIER = "org.transitbox.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; @@ -1283,7 +1299,11 @@ DEVELOPMENT_TEAM = ""; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = "OpenGpxTracker-Watch Extension/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); MARKETING_VERSION = 1.8.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; @@ -1315,7 +1335,11 @@ DEVELOPMENT_TEAM = ""; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = "OpenGpxTracker-Watch Extension/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); MARKETING_VERSION = 1.8.0; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = org.merlos.OpenGpxTracker.watchkitapp.ext; From 6f3d3528c0ee10c789da57fe7f90b7aa2a7ace4c Mon Sep 17 00:00:00 2001 From: merlos Date: Sun, 28 May 2023 22:50:16 +0300 Subject: [PATCH 13/27] Update readme - Add privacy --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0822b96..f42cd41 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,8 @@ This app has no annoying time restrictions, no ads and no in-app-purchases. Crea If you are goint to track without Internet... don't worry! Just browse the area where you'll be tracking and it will be cached. -Requires iOS 9.0 or above. Open GPX tracker is an open source app. +We care about your privacy, all the data recorded using the application is kept in your phone (or in your iCloud), wherever you store it. The app does not share any GPS data with us or any other 3rd pary. For more information see the [Privacy Policy](https://github.com/merlos/iOS-Open-GPX-Tracker/wiki/Privacy-Policy) + ![GPS Tracker logs](https://merlos.github.io/iOS-Open-GPX-Tracker/images/open-gpx-tracker-4-screenshots.png) From b03785cd406e2c31e83dec816c7ab0eeded5f023 Mon Sep 17 00:00:00 2001 From: merlos Date: Sun, 28 May 2023 22:51:55 +0300 Subject: [PATCH 14/27] Readme: Update iOS version --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index f42cd41..0a7b9b8 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ If you are goint to track without Internet... don't worry! Just browse the area We care about your privacy, all the data recorded using the application is kept in your phone (or in your iCloud), wherever you store it. The app does not share any GPS data with us or any other 3rd pary. For more information see the [Privacy Policy](https://github.com/merlos/iOS-Open-GPX-Tracker/wiki/Privacy-Policy) +Requires iOS 11.0 or above. Open GPX tracker is an open source app. ![GPS Tracker logs](https://merlos.github.io/iOS-Open-GPX-Tracker/images/open-gpx-tracker-4-screenshots.png) From b2da894ffb679422f5ab9aa8440632eed178a43a Mon Sep 17 00:00:00 2001 From: merlos Date: Sun, 28 May 2023 22:52:42 +0300 Subject: [PATCH 15/27] Readme: update contribute section --- README.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0a7b9b8..7f707bb 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,24 @@ The application is being documented using [jazzy](https://github.com/realm/jazzy [Read Source code documentation](https://www.merlos.org/iOS-Open-GPX-Tracker/docs/index.html) ## Contribute -You can contribute by forking and submitting a pull request. + +You can contribute by forking and submitting a pull request (PR). + +Some conditions for a PR to be accepted: + +1) Text displayed in the application shall be internationalized. + - To do that use `NSLocalizedString`. Search on the code to see examples of usage. + - Add the localized string in all the lproj files in the same position. Use ChatGPT or DeepL to translate them to other languages. +2) You need to install [swiftlint](https://github.com/realm/SwiftLint) and ensure you're not introducing additional lint warnings. +3) You need to document the classes and methods that you create explaining what do they do from a blackbox perspective. We use [jazzy](https://github.com/realm/jazzy) for the documentation. To install jazzy run: + ```shell + gem install jazzy + ``` + Then, to view the documentation run + ```shell + jazzy + ``` + **Note that it will generate the documents in the `../gh-pages/docs`.** Please note that by submitting any pull request you are providing me (Juan M. Merlos) the rights to include and distribute those changes also on the binary app published on the App Store (which is released under Apple's Standard License Agreement) From 2c8ea70600175f0b8dc286bfded83cc4c8bff686 Mon Sep 17 00:00:00 2001 From: merlos Date: Sun, 28 May 2023 22:53:21 +0300 Subject: [PATCH 16/27] Readme: Update supported languages --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7f707bb..8f31a96 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ You can use Open GPX tracker for: - Clear cache - Select the map server. - Darkmode - - i18n support: English, German, Chinese (simplified), Spanish + - Multi-language support (thanks to volunteers): German, English, Spanish, Finnish, French, Italian, Dutch, Portuguese (Brazil), Russian, Ukranian Chinese (simplified) ### Apple Watch Features (since 1.6.0) - Create GPX Files on your Apple Watch From c50295d0734ef4bb7492473b47e888062e4f0e8f Mon Sep 17 00:00:00 2001 From: merlos Date: Sun, 28 May 2023 22:53:57 +0300 Subject: [PATCH 17/27] Readme: small puntualizations & updates --- README.md | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 8f31a96..c527c86 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@ Open GPX Tracker for iOS + WatchOS Open GPX Tracker is a GPS logger for iOS (iPhone, iPad, iPod) with offline map cache support. Track your location, add waypoints and send your logs by email as GPX files. -This app has no annoying time restrictions, no ads and no in-app-purchases. Create unlimited GPX traces :). +This app has no annoying time restrictions, no ads and no in-app-purchases. You can create unlimited GPX traces :). -If you are goint to track without Internet... don't worry! Just browse the area where you'll be tracking and it will be cached. +If you are goint to track without Internet... don't worry! Before you go offline, browse the area where you'll be tracking and it will be cached and available offline. We care about your privacy, all the data recorded using the application is kept in your phone (or in your iCloud), wherever you store it. The app does not share any GPS data with us or any other 3rd pary. For more information see the [Privacy Policy](https://github.com/merlos/iOS-Open-GPX-Tracker/wiki/Privacy-Policy) @@ -20,11 +20,12 @@ You can use Open GPX tracker for: - Creating routes and waypoints for editing Open Street Map. - Publishing Open Street Map Traces. - [Creating GPX files for testing your iOS apps in Xcode](https://medium.com/@merlos/how-to-simulate-locations-in-xcode-b0f7f16e126d). + - Use it as GPS companion when you take pictures with your reflex camera. ## Main Features - Displays tracking route in a map - - Supports Apple Map Kit, [Open Street Map](http://wiki.openstreetmap.org/wiki/Tile_usage_policy) and [Carto DB](http://www.cartodb.com) as map sources + - Supports Apple Map Kit, [Open Street Map](http://wiki.openstreetmap.org/wiki/Tile_usage_policy), and [Carto DB](http://www.cartodb.com) as map sources - Offline maps support (of browsed areas) - Pause / Resume tracking - Add waypoint to user location @@ -59,14 +60,15 @@ You can use Open GPX tracker for: ## Install -The app is [available on the App Store](https://itunes.apple.com/app/open-gpx-tracker/id984503772) since May 2015. +The app is [available on the App Store](https://itunes.apple.com/app/open-gpx-tracker/id984503772), available since May 2015. -Another option to install the app is to download the source code and compile it by yourself using Xcode. If you want to run it on a device, you also need an Apple developer account. +Another option to install the app is to download the source code and compile it by yourself using [Xcode](https://developer.apple.com/xcode/) and the iOS simulator. If you want to run it on a iOS device, you also need an Apple developer account. ## Translate Open GPX Tracker Open GPX tracker supports language translations (since 1.7.0). [See list of supported languages and how to translate the app into your language](https://github.com/merlos/iOS-Open-GPX-Tracker/wiki/How-to-translate-Open-GPX-Tracker-into-my-language). -## Download Source code +## Development + This application is written in Swift. To download the code run this command in a console: ``` @@ -75,9 +77,11 @@ This application is written in Swift. To download the code run this command in a Then, to test it open the file `OpenGpxTracker.xcworkspace` with XCode. +Although the application uses some Cocoapods, all the pods are already included in our repo. So no need to run `pod install`. + Please note the [limitations of using Open Street Maps Tile Servers](http://wiki.openstreetmap.org/wiki/Tile_usage_policy) -### Add a tile server +### Add a custom tile server Adding a tile server is easy, just edit the file `GPXTileServer.swift`, uncomment the lines with `AnotherMap` and modify the templateUrl to point to the new tile server. You have a list of tile servers in [Open Street Map Wiki](http://wiki.openstreetmap.org/wiki/Tile_servers) @@ -88,7 +92,7 @@ The application is being documented using [jazzy](https://github.com/realm/jazzy ![Documentation Status](https://www.merlos.org/iOS-Open-GPX-Tracker/docs/badge.svg) -[Read Source code documentation](https://www.merlos.org/iOS-Open-GPX-Tracker/docs/index.html) +**[Read Source code documentation](https://www.merlos.org/iOS-Open-GPX-Tracker/docs/index.html)** ## Contribute @@ -110,10 +114,11 @@ Some conditions for a PR to be accepted: ``` **Note that it will generate the documents in the `../gh-pages/docs`.** -Please note that by submitting any pull request you are providing me (Juan M. Merlos) the rights to include and distribute those changes also on the binary app published on the App Store (which is released under Apple's Standard License Agreement) +**PR License** +Please note that though the source code is licensed under GPL 3.0 by submitting a pull request you are also providing me (Juan M. Merlos) the rights to distribute those changes also on the binary app published on the App Store (which is released under Apple's Standard License Agreement) ## License -Open GPX Tracker app for iOS. Copyright (C) 2014 Juan M. Merlos (@merlos) +Open GPX Tracker app for iOS. Copyright (C) 2014 Juan M. Merlos (@merlos) & Contributors This program is free software: you can redistribute it and/or modify it under the terms of the **GNU General Public License** as published by From 6b3c49cd841182b2c54fdce4a0877fb7d276588e Mon Sep 17 00:00:00 2001 From: merlos Date: Sun, 28 May 2023 22:54:19 +0300 Subject: [PATCH 18/27] toast: fix space lint warning --- OpenGpxTracker/Toast.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenGpxTracker/Toast.swift b/OpenGpxTracker/Toast.swift index 575a042..97fca76 100644 --- a/OpenGpxTracker/Toast.swift +++ b/OpenGpxTracker/Toast.swift @@ -91,7 +91,7 @@ class Toast { case top } - + /// /// Generic implementation to show toast /// - Parameters: From 1edc7ad9dda291ac81856f8d057c0bd14770b9a6 Mon Sep 17 00:00:00 2001 From: merlos Date: Thu, 1 Jun 2023 06:43:24 +0300 Subject: [PATCH 19/27] explain further i18m --- README.md | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c527c86..791afd1 100644 --- a/README.md +++ b/README.md @@ -101,9 +101,24 @@ You can contribute by forking and submitting a pull request (PR). Some conditions for a PR to be accepted: 1) Text displayed in the application shall be internationalized. - - To do that use `NSLocalizedString`. Search on the code to see examples of usage. - - Add the localized string in all the lproj files in the same position. Use ChatGPT or DeepL to translate them to other languages. + - To do that use [NSLocalizedString](https://developer.apple.com/documentation/foundation/nslocalizedstring). Search on the code to see examples of usage. + - Add the keys of the localized string to all the `lproj` files. Keep this files organized in the same way (~ same line). + - Use [ChatGPT](https://chat.openai.com) or [DeepL](https://www.deepl.com/translator) to translate them to other languages. For example, for ChatGPT you can use a prompt similar to: + ``` + You are a language translator that is in the process of translating an mobile application for getting GPX traces in an iOS device. + + Please provide the translation to the following languages: + German (de), Spanish (es), Chinese Simplified (zh-Hans), Ukranian (uk), Finnish (fi-FI), Russian (ru),French (fr), Dutch (nl), Portuguese Brazil (pt-BR), Italian (it) + + of the following strings: + + "TEXT_KEY" = "This is the text"; + "TEXT_KEY" = "This is the text"; + ``` + + 2) You need to install [swiftlint](https://github.com/realm/SwiftLint) and ensure you're not introducing additional lint warnings. + 3) You need to document the classes and methods that you create explaining what do they do from a blackbox perspective. We use [jazzy](https://github.com/realm/jazzy) for the documentation. To install jazzy run: ```shell gem install jazzy @@ -115,10 +130,10 @@ Some conditions for a PR to be accepted: **Note that it will generate the documents in the `../gh-pages/docs`.** **PR License** -Please note that though the source code is licensed under GPL 3.0 by submitting a pull request you are also providing me (Juan M. Merlos) the rights to distribute those changes also on the binary app published on the App Store (which is released under Apple's Standard License Agreement) +Note that though the source code is licensed under GPL 3.0 by submitting a pull request you are also providing me (Juan M. Merlos) the rights to distribute those changes on the binary app published on the App Store (which is released under Apple's Standard License Agreement) -## License -Open GPX Tracker app for iOS. Copyright (C) 2014 Juan M. Merlos (@merlos) & Contributors +## GPL License +Open GPX Tracker app for iOS. Copyright (C) 2014-2023 Juan M. Merlos (@merlos) & Contributors This program is free software: you can redistribute it and/or modify it under the terms of the **GNU General Public License** as published by From d87eb52915a8d98de452bb45d7e42e52898a2676 Mon Sep 17 00:00:00 2001 From: merlos Date: Thu, 1 Jun 2023 06:48:55 +0300 Subject: [PATCH 20/27] update syntax of UIColor constants --- OpenGpxTracker/Toast.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/OpenGpxTracker/Toast.swift b/OpenGpxTracker/Toast.swift index 97fca76..dbe7ca6 100644 --- a/OpenGpxTracker/Toast.swift +++ b/OpenGpxTracker/Toast.swift @@ -60,27 +60,27 @@ class Toast { static let kFontSize = 16 /// Toast.regular text color - static let kRegularTextColor: UIColor = UIColor(ciColor: .white) + static let kRegularTextColor: UIColor = UIColor.white /// Toast.regular background color - static let kRegularBackgroundColor: UIColor = UIColor(ciColor: .black) + static let kRegularBackgroundColor: UIColor = UIColor.black /// Toast.info text color - static let kInfoTextColor: UIColor = UIColor(ciColor: .white) + static let kInfoTextColor: UIColor = UIColor.white /// Toast.info background color static let kInfoBackgroundColor: UIColor = UIColor(red: 0/255, green: 100/255, blue: 225/255, alpha: kBackgroundOpacity) /// Toast.success text color - static let kSuccessTextColor: UIColor = UIColor(ciColor: .white) + static let kSuccessTextColor: UIColor = UIColor.white /// Toast.success background color static let kSuccessBackgroundColor: UIColor = UIColor(red: 0/255, green: 150/255, blue: 0/255, alpha: kBackgroundOpacity) /// Toast.warning text color - static let kWarningTextColor: UIColor = UIColor(ciColor: .black) + static let kWarningTextColor: UIColor = UIColor.black static let kWarningBackgroundColor: UIColor = UIColor(red: 255/255, green: 175/255, blue: 0/255, alpha: kBackgroundOpacity) /// Toast.error text color - static let kErrorTextColor: UIColor = UIColor(ciColor: .white) + static let kErrorTextColor: UIColor = UIColor.white /// Toast.error background color static let kErrorBackgroundColor: UIColor = UIColor(red: 175/255, green: 0/255, blue: 0/255, alpha: kBackgroundOpacity) From 559f2e07c515f74fdc5e01bb7fa48775dd2f70e6 Mon Sep 17 00:00:00 2001 From: merlos Date: Thu, 1 Jun 2023 08:06:48 +0300 Subject: [PATCH 21/27] Remove most of lint issues in ViewController --- OpenGpxTracker/ViewController.swift | 146 ++++++++++++---------------- 1 file changed, 63 insertions(+), 83 deletions(-) diff --git a/OpenGpxTracker/ViewController.swift b/OpenGpxTracker/ViewController.swift index 52bbd78..98eff8a 100644 --- a/OpenGpxTracker/ViewController.swift +++ b/OpenGpxTracker/ViewController.swift @@ -107,8 +107,8 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { manager.activityType = CLActivityType(rawValue: Preferences.shared.locationActivityTypeInt)! print("Chosen CLActivityType: \(manager.activityType.name)") manager.desiredAccuracy = kCLLocationAccuracyBest - manager.distanceFilter = 2 //meters - manager.headingFilter = 3 //degrees (1 is default) + manager.distanceFilter = 2 // meters + manager.headingFilter = 3 // degrees (1 is default) manager.pausesLocationUpdatesAutomatically = false if #available(iOS 9.0, *) { manager.allowsBackgroundLocationUpdates = true @@ -165,21 +165,21 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { switch gpxTrackingStatus { case .notStarted: print("switched to non started") - // set Tracker button to allow Start + // Set tracker button to allow Start trackerButton.setTitle(NSLocalizedString("START_TRACKING", comment: "no comment"), for: UIControl.State()) trackerButton.backgroundColor = kGreenButtonBackgroundColor - //save & reset button to transparent. + // Save & reset button to transparent. saveButton.backgroundColor = kDisabledBlueButtonBackgroundColor resetButton.backgroundColor = kDisabledRedButtonBackgroundColor - //reset clock + // Reset clock stopWatch.reset() timeLabel.text = stopWatch.elapsedTimeString - map.clearMap() //clear map - lastGpxFilename = "" //clear last filename, so when saving it appears an empty field + map.clearMap() // Clear map + lastGpxFilename = "" // Clear last filename, so when saving it appears an empty field map.coreDataHelper.clearAll() - map.coreDataHelper.coreDataDeleteAll(of: CDRoot.self)//deleteCDRootFromCoreData() + map.coreDataHelper.coreDataDeleteAll(of: CDRoot.self) // deleteCDRootFromCoreData() totalTrackedDistanceLabel.distance = (map.session.totalTrackedDistance) currentSegmentDistanceLabel.distance = (map.session.currentSegmentDistance) @@ -199,7 +199,7 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { // set tracerkButton to allow Pause trackerButton.setTitle(NSLocalizedString("PAUSE", comment: "no comment"), for: UIControl.State()) trackerButton.backgroundColor = kPurpleButtonBackgroundColor - //activate save & reset buttons + // Activate save & reset buttons saveButton.backgroundColor = kBlueButtonBackgroundColor resetButton.backgroundColor = kRedButtonBackgroundColor // start clock @@ -213,7 +213,7 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { // activate save & reset (just in case switched from .NotStarted) saveButton.backgroundColor = kBlueButtonBackgroundColor resetButton.backgroundColor = kRedButtonBackgroundColor - //pause clock + // Pause clock self.stopWatch.stop() // start new track segment self.map.startNewTrackSegment() @@ -222,9 +222,9 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { } /// Editing Waypoint Temporal Reference - var lastLocation: CLLocation? //Last point of current segment. + var lastLocation: CLLocation? // Last point of current segment. - //UI + // UI /// Label with the title of the app var appTitleLabel: UILabel @@ -375,8 +375,8 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { map.coreDataHelper.retrieveFromCoreData() - //Because of the edges, iPhone X* is slightly different on the layout. - //So, Is the current device an iPhone X? + // Because of the edges, iPhone X* is slightly different on the layout. + // So, Is the current device an iPhone X? if UIDevice.current.userInterfaceIdiom == .phone, #available(iOS 11, *) { self.isIPhoneX = UIApplication.shared.delegate?.window??.safeAreaInsets.top ?? 0 > 40 } @@ -394,15 +394,15 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { map.frame = CGRect(x: 0.0, y: (isIPhoneX ? 0.0 : 20.0), width: self.view.bounds.size.width, height: mapH) map.isZoomEnabled = true map.isRotateEnabled = true - //set the position of the compass. + // Set the position of the compass. map.compassRect = CGRect(x: map.frame.width/2 - 18, y: isIPhoneX ? 105.0 : 70.0, width: 36, height: 36) - //If user long presses the map, it will add a Pin (waypoint) at that point + // If user long presses the map, it will add a Pin (waypoint) at that point map.addGestureRecognizer( UILongPressGestureRecognizer(target: self, action: #selector(ViewController.addPinAtTappedLocation(_:))) ) - //Each time user pans, if the map is following the user, it stops doing that. + // Each time user pans, if the map is following the user, it stops doing that. let panGesture = UIPanGestureRecognizer(target: self, action: #selector(ViewController.stopFollowingUser(_:))) panGesture.delegate = self map.addGestureRecognizer(panGesture) @@ -414,11 +414,11 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { //let pinchGesture = UIPinchGestureRecognizer(target: self, action: "pinchGesture") //map.addGestureRecognizer(pinchGesture) - //Preferences + // Preferences map.tileServer = Preferences.shared.tileServer map.useCache = Preferences.shared.useCache useImperial = Preferences.shared.useImperial - //locationManager.activityType = Preferences.shared.locationActivityType + // LocationManager.activityType = Preferences.shared.locationActivityType // // Config user interface @@ -441,7 +441,7 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { let font18 = UIFont(name: "DinAlternate-Bold", size: 18.0) let font12 = UIFont(name: "DinAlternate-Bold", size: 12.0) - //add the app title Label (Branding, branding, branding! ) + // Add the app title Label (Branding, branding, branding! ) appTitleLabel.text = " Open GPX Tracker" appTitleLabel.textAlignment = .left appTitleLabel.font = UIFont.boldSystemFont(ofSize: 10) @@ -459,29 +459,25 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { // Tracked info let iPhoneXdiff: CGFloat = isIPhoneX ? 40 : 0 - //timeLabel + + // TimeLabel timeLabel.textAlignment = .right timeLabel.font = font36 timeLabel.text = "00:00" - //timeLabel.shadowColor = UIColor.whiteColor() - //timeLabel.shadowOffset = CGSize(width: 1, height: 1) - //timeLabel.backgroundColor = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.5) map.addSubview(timeLabel) - //speed Label + // Speed Label speedLabel.textAlignment = .right speedLabel.font = font18 speedLabel.text = 0.00.toSpeed(useImperial: useImperial) - //timeLabel.backgroundColor = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.5) map.addSubview(speedLabel) - //tracked distance + // Tracked distance totalTrackedDistanceLabel.textAlignment = .right totalTrackedDistanceLabel.font = font36 totalTrackedDistanceLabel.useImperial = useImperial totalTrackedDistanceLabel.distance = 0.00 totalTrackedDistanceLabel.autoresizingMask = [.flexibleWidth, .flexibleLeftMargin, .flexibleRightMargin] - //timeLabel.backgroundColor = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.5) map.addSubview(totalTrackedDistanceLabel) currentSegmentDistanceLabel.textAlignment = .right @@ -489,17 +485,14 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { currentSegmentDistanceLabel.useImperial = useImperial currentSegmentDistanceLabel.distance = 0.00 currentSegmentDistanceLabel.autoresizingMask = [.flexibleWidth, .flexibleLeftMargin, .flexibleRightMargin] - //timeLabel.backgroundColor = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.5) map.addSubview(currentSegmentDistanceLabel) - //about button + // About button aboutButton.frame = CGRect(x: 5 + 8, y: 14 + 5 + 48 + 5 + iPhoneXdiff, width: 32, height: 32) aboutButton.setImage(UIImage(named: "info"), for: UIControl.State()) aboutButton.setImage(UIImage(named: "info_high"), for: .highlighted) aboutButton.addTarget(self, action: #selector(ViewController.openAboutViewController), for: .touchUpInside) aboutButton.autoresizingMask = [.flexibleRightMargin] - //aboutButton.backgroundColor = kWhiteBackgroundColor - //aboutButton.layer.cornerRadius = 24 map.addSubview(aboutButton) // Preferences button @@ -508,8 +501,6 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { preferencesButton.setImage(UIImage(named: "prefs_high"), for: .highlighted) preferencesButton.addTarget(self, action: #selector(ViewController.openPreferencesTableViewController), for: .touchUpInside) preferencesButton.autoresizingMask = [.flexibleRightMargin] - //aboutButton.backgroundColor = kWhiteBackgroundColor - //aboutButton.layer.cornerRadius = 24 map.addSubview(preferencesButton) // Share button @@ -518,8 +509,6 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { shareButton.setImage(UIImage(named: "share_high"), for: .highlighted) shareButton.addTarget(self, action: #selector(ViewController.openShare), for: .touchUpInside) shareButton.autoresizingMask = [.flexibleRightMargin] - //aboutButton.backgroundColor = kWhiteBackgroundColor - //aboutButton.layer.cornerRadius = 24 map.addSubview(shareButton) // Folder button @@ -585,7 +574,6 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { // Follow user button followUserButton.layer.cornerRadius = kButtonSmallSize/2 followUserButton.backgroundColor = kWhiteBackgroundColor - //follow_user_high represents the user is being followed. Default status when app starts followUserButton.setImage(UIImage(named: "follow_user_high"), for: UIControl.State()) followUserButton.setImage(UIImage(named: "follow_user_high"), for: .highlighted) followUserButton.addTarget(self, action: #selector(ViewController.followButtonTroggler), for: .touchUpInside) @@ -871,15 +859,13 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { } } - /// returns a string with the format of current date dd-MMM-yyyy-HHmm' (20-Jun-2018-1133) + /// Returns a string with the format of current date dd-MMM-yyyy-HHmm' (20-Jun-2018-1133) /// func defaultFilename() -> String { let defaultDate = DefaultDateFormat() - //let dateFormatter = DateFormatter() - //dateFormatter.dateFormat = "dd-MMM-yyyy-HHmm" let dateStr = defaultDate.getDateFromPrefs() - print("fileName:" + dateStr)//dateFormatter.string(from: Date())) - return dateStr//dateFormatter.string(from: Date()) + print("fileName:" + dateStr) + return dateStr } @objc func loadRecoveredFile(_ notification: Notification) { @@ -891,15 +877,15 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { } lastGpxFilename = fileName - // adds last file name to core data as well + // Adds last file name to core data as well self.map.coreDataHelper.add(toCoreData: fileName, willContinueAfterSave: false) - //force reset timer just in case reset does not do it + // Force reset timer just in case reset does not do it self.stopWatch.reset() - //load data + // Load data self.map.continueFromGPXRoot(root) - //stop following user + // Stop following user self.followUser = false - //center map in GPX data + // Center map in GPX data self.map.regionToGPXExtent() self.gpxTrackingStatus = .paused @@ -915,8 +901,7 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { print("viewController:: applicationDidBecomeActive wasSentToBackground: \(self.wasSentToBackground) locationServices: \(CLLocationManager.locationServicesEnabled())") } - - //If the app was never sent to background do nothing + // If the app was never sent to background do nothing if !wasSentToBackground { return } @@ -994,17 +979,17 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { self.shouldShowShareActivityIndicator(true) } - //Create a temporary file + // Create a temporary file let filename = self.lastGpxFilename.isEmpty ? self.defaultFilename() : self.lastGpxFilename let gpxString: String = self.map.exportToGPXString() let tmpFile = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("\(filename).gpx") GPXFileManager.saveToURL(tmpFile, gpxContents: gpxString) - //Add it to the list of tmpFiles. - //Note: it may add more than once the same file to the list. + // Add it to the list of tmpFiles. + // Note: it may add more than once the same file to the list. // UI code DispatchQueue.main.sync { - //Call Share activity View controller + // Call Share activity View controller let activityViewController = UIActivityViewController(activityItems: [tmpFile], applicationActivities: nil) activityViewController.popoverPresentationController?.sourceView = self.shareButton activityViewController.popoverPresentationController?.sourceRect = self.shareButton.bounds @@ -1068,7 +1053,7 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { print("Adding Pin map Long Press Gesture") let point: CGPoint = gesture.location(in: self.map) map.addWaypointAtViewPoint(point) - //Allows save and reset + // Allows save and reset self.hasWaypoints = true } } @@ -1092,9 +1077,9 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { /// /// Triggered when follow Button is taped. - // + /// /// Trogles between following or not following the user, that is, automatically centering the map - // in current user´s position. + /// in current user´s position. /// @objc func followButtonTroggler() { self.followUser = !self.followUser @@ -1107,14 +1092,13 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { /// @objc func resetButtonTapped() { - let sheet = UIAlertController(title: nil, message: NSLocalizedString("SELECT_OPTION", comment: "no comment"), preferredStyle: .actionSheet) let cancelOption = UIAlertAction(title: NSLocalizedString("CANCEL", comment: "no comment"), style: .cancel) { _ in } let saveAndStartOption = UIAlertAction(title: NSLocalizedString("SAVE_START_NEW", comment: "no comment"), style: .default) { _ in - //Save + // Save self.saveButtonTapped(withReset: true) } @@ -1122,12 +1106,10 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { self.gpxTrackingStatus = .notStarted } - sheet.addAction(cancelOption) sheet.addAction(saveAndStartOption) sheet.addAction(deleteOption) - self.present(sheet, animated: true) { print("Loaded actionSheet") } @@ -1173,11 +1155,11 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { let saveAction = UIAlertAction(title: NSLocalizedString("SAVE", comment: "no comment"), style: .default) { _ in let filename = (alertController.textFields?[0].text!.utf16.count == 0) ? self.defaultFilename() : alertController.textFields?[0].text print("Save File \(String(describing: filename))") - //export to a file + // Export to a file let gpxString = self.map.exportToGPXString() GPXFileManager.save(filename!, gpxContents: gpxString) self.lastGpxFilename = filename! - self.map.coreDataHelper.coreDataDeleteAll(of: CDRoot.self)//deleteCDRootFromCoreData() + self.map.coreDataHelper.coreDataDeleteAll(of: CDRoot.self) self.map.coreDataHelper.clearAllExceptWaypoints() self.map.coreDataHelper.add(toCoreData: filename!, willContinueAfterSave: true) if withReset { @@ -1212,20 +1194,20 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { func checkLocationServicesStatus() { let authorizationStatus = CLLocationManager.authorizationStatus() - //Has the user already made a permission choice? + // Has the user already made a permission choice? guard authorizationStatus != .notDetermined else { - //We should take no action until the user has made a choice - //Note that we request location permission as part of the property `locationManager` init + // We should take no action until the user has made a choice + // Note that we request location permission as part of the property `locationManager` init return } - //Does the app have permissions to use the location servies? + // Does the app have permissions to use the location servies? guard [.authorizedAlways, .authorizedWhenInUse ].contains(authorizationStatus) else { displayLocationServicesDeniedAlert() return } - //Are location services enabled? + // Are location services enabled? guard CLLocationManager.locationServicesEnabled() else { displayLocationServicesDisabledAlert() return @@ -1243,8 +1225,7 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { if let url = URL(string: UIApplication.openSettingsURLString) { if #available(iOS 10, *) { UIApplication.shared.open(url) - } - else { + } else { UIApplication.shared.openURL(url) } } @@ -1274,8 +1255,7 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { if let url = URL(string: UIApplication.openSettingsURLString) { if #available(iOS 10, *) { UIApplication.shared.open(url) - } - else { + } else { UIApplication.shared.openURL(url) } } @@ -1360,7 +1340,7 @@ extension ViewController: PreferencesTableViewControllerDelegate { useImperial = newUseImperial totalTrackedDistanceLabel.useImperial = useImperial currentSegmentDistanceLabel.useImperial = useImperial - //Because we dont know if last speed was unknown we set it as unknown. + // Because we dont know if last speed was unknown we set it as unknown. // In regular circunstances it will go to the new units relatively fast. speedLabel.text = kUnknownSpeedText signalAccuracyLabel.text = kUnknownAccuracyText @@ -1375,19 +1355,19 @@ extension ViewController: GPXFilesTableViewControllerDelegate { /// Resets whatever estatus was before. /// func didLoadGPXFileWithName(_ gpxFilename: String, gpxRoot: GPXRoot) { - //emulate a reset button tap + // Emulate a reset button tap self.resetButtonTapped() - //println("Loaded GPX file", gpx.gpx()) + // println("Loaded GPX file", gpx.gpx()) lastGpxFilename = gpxFilename - // adds last file name to core data as well + // Adds last file name to core data as well self.map.coreDataHelper.add(toCoreData: gpxFilename, willContinueAfterSave: false) - //force reset timer just in case reset does not do it + // Force reset timer just in case reset does not do it self.stopWatch.reset() - //load data + // Load data self.map.importFromGPXRoot(gpxRoot) - //stop following user + // Stop following user self.followUser = false - //center map in GPX data + // Center map in GPX data self.map.regionToGPXExtent() self.gpxTrackingStatus = .paused @@ -1434,7 +1414,7 @@ extension ViewController: CLLocationManagerDelegate { /// /// func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { - //updates signal image accuracy + // Update signal image accuracy let newLocation = locations.first! // Update horizontal accuracy let hAcc = newLocation.horizontalAccuracy @@ -1455,16 +1435,16 @@ extension ViewController: CLLocationManagerDelegate { self.signalImageView.image = signalImage0 } - //Update coordsLabel + // Update coordsLabel let latFormat = String(format: "%.6f", newLocation.coordinate.latitude) let lonFormat = String(format: "%.6f", newLocation.coordinate.longitude) let altitude = newLocation.altitude.toAltitude(useImperial: useImperial) coordsLabel.text = String(format: NSLocalizedString("COORDS_LABEL", comment: "no comment"), latFormat, lonFormat, altitude) - //Update speed + // Update speed speedLabel.text = (newLocation.speed < 0) ? kUnknownSpeedText : newLocation.speed.toSpeed(useImperial: useImperial) - //Update Map center and track overlay if user is being followed + // Update Map center and track overlay if user is being followed if followUser { map.setCenter(newLocation.coordinate, animated: true) } From 861d270f29c59e467a93a5410adaff64a8f95299 Mon Sep 17 00:00:00 2001 From: merlos Date: Thu, 1 Jun 2023 08:48:06 +0300 Subject: [PATCH 22/27] Move some logic to ToastLabel --- OpenGpxTracker/Toast.swift | 139 ++++++++++++++++++++++++++----------- 1 file changed, 98 insertions(+), 41 deletions(-) diff --git a/OpenGpxTracker/Toast.swift b/OpenGpxTracker/Toast.swift index dbe7ca6..244d933 100644 --- a/OpenGpxTracker/Toast.swift +++ b/OpenGpxTracker/Toast.swift @@ -8,8 +8,39 @@ import Foundation import UIKit +/// Font size of the toast + /// Supporting UILabel for Toast. +/// Setups the base label. +/// The toast adds the position color class ToastLabel: UILabel { + + static let kFontSize = 16 + + override init(frame: CGRect) { + super.init(frame: frame) + commonInit() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + commonInit() + } + + convenience init(text: String) { + self.init() + self.text = text + } + + private func commonInit() { + textAlignment = .center + font = UIFont.systemFont(ofSize: CGFloat(ToastLabel.kFontSize)) + alpha = 0 + numberOfLines = 0 + layer.masksToBounds = true + layer.cornerRadius = 10 + } + var textInsets = UIEdgeInsets.zero { didSet { invalidateIntrinsicContentSize() } } @@ -56,9 +87,6 @@ class Toast { /// Offset from the closest screen edge (top or bottom). static let kToastOffset = 120 - /// Font size of the toast - static let kFontSize = 16 - /// Toast.regular text color static let kRegularTextColor: UIColor = UIColor.white /// Toast.regular background color @@ -91,7 +119,6 @@ class Toast { case top } - /// /// Generic implementation to show toast /// - Parameters: @@ -100,18 +127,18 @@ class Toast { /// - backgroundColor: Color of the text /// - position: Position within the screen (.bottom, .center, .top) /// - delay: time in seconds that the toast will be displayed - static func showToast(_ message: String, textColor: UIColor, backgroundColor: UIColor, position: Position, delay: Double) { + static func showToast(_ message: String, + textColor: UIColor = kRegularTextColor, + backgroundColor: UIColor = kRegularBackgroundColor, + position: Position = .bottom, + delay: Double = kDelayLong) { guard let window = UIApplication.shared.keyWindow else { return } - let label = ToastLabel() + let label = ToastLabel(text: message) label.textColor = textColor label.backgroundColor = backgroundColor - label.textAlignment = .center - label.font = UIFont.systemFont(ofSize: CGFloat(kFontSize)) - label.alpha = 0 - label.text = message - label.numberOfLines = 0 + var vertical: CGFloat = 0 var size = label.intrinsicContentSize var width = min(size.width, window.frame.width - 60) @@ -120,32 +147,38 @@ class Toast { label.textAlignment = .justified } label.textInsets = UIEdgeInsets(top: vertical, left: 15, bottom: vertical, right: 15) + size = label.intrinsicContentSize width = min(size.width, window.frame.width - 60) - - if position == Position.bottom { + switch position { + case .bottom: label.frame = CGRect(x: CGFloat(kToastWidth), y: window.frame.height - CGFloat(kToastOffset), width: width, height: size.height + CGFloat(kToastHeight)) - } else if position == Position.center { - label.frame = CGRect(x: CGFloat(kToastWidth), y: window.frame.height / 2, width: width, height: size.height + CGFloat(kToastHeight)) - } else if position == Position.top { - label.frame = CGRect(x: CGFloat(kToastWidth), y: CGFloat(kToastOffset), width: width, height: size.height + CGFloat(kToastHeight)) + case .center: + label.frame = CGRect(x: CGFloat(kToastWidth), + y: window.frame.height / 2, + width: width, + height: size.height + CGFloat(kToastHeight)) + case .top: + label.frame = CGRect(x: CGFloat(kToastWidth), + y: CGFloat(kToastOffset), + width: width, + height: size.height + CGFloat(kToastHeight)) } label.center.x = window.center.x - label.layer.cornerRadius = min(label.frame.height / 2, 32) - label.layer.masksToBounds = true + window.addSubview(label) - UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseIn, animations: { - label.alpha = 1 - }, completion: { _ in - UIView.animate(withDuration: 0.5, delay: delay, options: .curveEaseOut, animations: { - label.alpha = 0 - }, completion: {_ in - label.removeFromSuperview() - }) - }) + UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseIn, + animations: { label.alpha = 1 }, + completion: { _ in + UIView.animate(withDuration: 0.5, delay: delay, + options: .curveEaseOut, + animations: {label.alpha = 0 }, + completion: {_ in label.removeFromSuperview() + }) + }) } /// @@ -160,35 +193,59 @@ class Toast { /// Information toast (blue) /// /// - SeeAlso showToast - class func info(_ message: String, position: Position = Position.bottom, delay: Double = kDelayLong) { - showToast(String("\u{24D8}")+" "+message, textColor: kInfoTextColor, backgroundColor: kInfoBackgroundColor, - position: position, delay: delay) + class func info(_ message: String, + position: Position = Position.bottom, + delay: Double = kDelayLong) { + + showToast(String("\u{24D8}")+" "+message, + textColor: kInfoTextColor, + backgroundColor: kInfoBackgroundColor, + position: position, + delay: delay) } /// /// Display a warning toast (orange) /// /// - SeeAlso showToast - class func warning(_ message: String, position: Position = Position.bottom, delay: Double = kDelayLong) { - showToast(String("\u{26A0}")+" "+message, textColor: kWarningTextColor, backgroundColor: kWarningBackgroundColor, - position: position, delay: delay) + class func warning(_ message: String, + position: Position = Position.bottom, + delay: Double = kDelayLong) { + + showToast(String("\u{26A0}")+" "+message, + textColor: kWarningTextColor, + backgroundColor: kWarningBackgroundColor, + position: position, + delay: delay) } /// /// Display a Success toast /// /// - SeeAlso showToast - class func success(_ message: String, position: Position = Position.bottom, delay: Double = kDelayLong) { - showToast(String("\u{2705}")+" "+message, textColor: kSuccessTextColor, backgroundColor: kSuccessBackgroundColor, position: position, delay:delay) + class func success(_ message: String, + position: Position = Position.bottom, + delay: Double = kDelayLong) { + + showToast(String("\u{2705}")+" "+message, + textColor: kSuccessTextColor, + backgroundColor: kSuccessBackgroundColor, + position: position, + delay: delay) } /// - /// Display a error toast + /// Display a error toast. /// /// - SeeAlso showToast - class func error(_ message: String, position: Position = Position.bottom, delay: Double = kDelayLong) {//2757 - showToast(String("\u{274C}")+" "+message, textColor: kErrorTextColor, backgroundColor: kErrorBackgroundColor, position: position, delay: delay) + /// + class func error(_ message: String, + position: Position = Position.bottom, + delay: Double = kDelayLong) { + showToast(String("\u{274C}")+" "+message, + textColor: kErrorTextColor, + backgroundColor: kErrorBackgroundColor, + position: position, + delay: delay) } - } - From 8732d34cdf1911c342b0bd8debe159d3b3215d05 Mon Sep 17 00:00:00 2001 From: merlos Date: Thu, 1 Jun 2023 08:48:46 +0300 Subject: [PATCH 23/27] display session name in a different line with gpx extension --- OpenGpxTracker/CoreDataHelper.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenGpxTracker/CoreDataHelper.swift b/OpenGpxTracker/CoreDataHelper.swift index 9c9c19a..8bfa672 100644 --- a/OpenGpxTracker/CoreDataHelper.swift +++ b/OpenGpxTracker/CoreDataHelper.swift @@ -389,7 +389,7 @@ class CoreDataHelper { DispatchQueue.main.sync { NotificationCenter.default.post(name: .loadRecoveredFile, object: nil, userInfo: ["recoveredRoot": root, "fileName": self.lastFileName]) - let toastMessage = NSLocalizedString("LAST_SESSION_LOADED", comment: "the filename displayed after the text") + " " + self.lastFileName + let toastMessage = NSLocalizedString("LAST_SESSION_LOADED", comment: "the filename displayed after the text") + " \n" + self.lastFileName + ".gpx" Toast.regular(toastMessage, position: .top) } } else { From 91a72d5a23bb4b897401f64983ea604caabd74d3 Mon Sep 17 00:00:00 2001 From: merlos Date: Thu, 1 Jun 2023 08:49:14 +0300 Subject: [PATCH 24/27] increase min function body length to 50 in linting --- .swiftlint.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.swiftlint.yml b/.swiftlint.yml index 8dffe8a..276cae1 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -14,5 +14,5 @@ type_body_length: - 300 # warning - 800 # error function_body_length: - - 40 - - 246 + - 50 + - 250 From 130b28ce62c606d4efa4e97a93606e6518e5e54a Mon Sep 17 00:00:00 2001 From: merlos Date: Thu, 1 Jun 2023 14:24:26 +0300 Subject: [PATCH 25/27] User app title for displaying current filename --- OpenGpxTracker/ViewController.swift | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/OpenGpxTracker/ViewController.swift b/OpenGpxTracker/ViewController.swift index 98eff8a..98d8728 100644 --- a/OpenGpxTracker/ViewController.swift +++ b/OpenGpxTracker/ViewController.swift @@ -14,6 +14,9 @@ import CoreGPX // swiftlint:disable line_length +/// App title + +let kAppTitle: String = " Open GPX Tracker" /// Purple color for button background let kPurpleButtonBackgroundColor: UIColor = UIColor(red: 146.0/255.0, green: 166.0/255.0, blue: 218.0/255.0, alpha: 0.90) @@ -126,7 +129,20 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { var stopWatch = StopWatch() /// Name of the last file that was saved (without extension) - var lastGpxFilename: String = "" + var lastGpxFilename: String = "" { + didSet { + if lastGpxFilename == "" { + appTitleLabel.text = kAppTitle + } else { + // if name is too long arbitrary cut + var displayedName = lastGpxFilename + if lastGpxFilename.count > 20 { + displayedName = lastGpxFilename.prefix(10) + "..." + lastGpxFilename.suffix(3) + } + appTitleLabel.text = " " + displayedName + ".gpx" + } + } + } /// Status variable that indicates if the app was sent to background. var wasSentToBackground: Bool = false @@ -411,9 +427,6 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { locationManager.startUpdatingLocation() locationManager.startUpdatingHeading() - //let pinchGesture = UIPinchGestureRecognizer(target: self, action: "pinchGesture") - //map.addGestureRecognizer(pinchGesture) - // Preferences map.tileServer = Preferences.shared.tileServer map.useCache = Preferences.shared.useCache @@ -442,10 +455,9 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { let font12 = UIFont(name: "DinAlternate-Bold", size: 12.0) // Add the app title Label (Branding, branding, branding! ) - appTitleLabel.text = " Open GPX Tracker" + appTitleLabel.text = kAppTitle appTitleLabel.textAlignment = .left appTitleLabel.font = UIFont.boldSystemFont(ofSize: 10) - //appTitleLabel.textColor = UIColor(red: 0.0/255.0, green: 0.0/255.0, blue: 0.0/255.0, alpha: 1.0) appTitleLabel.textColor = UIColor.yellow appTitleLabel.backgroundColor = UIColor(red: 58.0/255.0, green: 57.0/255.0, blue: 54.0/255.0, alpha: 0.80) self.view.addSubview(appTitleLabel) From 214e15f290d380183e06cd025b8399741a83547a Mon Sep 17 00:00:00 2001 From: merlos Date: Thu, 1 Jun 2023 14:31:31 +0300 Subject: [PATCH 26/27] remove lint warnings in GPXMapView --- OpenGpxTracker/GPXMapView.swift | 41 +++++++++++++++------------------ 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/OpenGpxTracker/GPXMapView.swift b/OpenGpxTracker/GPXMapView.swift index d5582eb..e493ae8 100644 --- a/OpenGpxTracker/GPXMapView.swift +++ b/OpenGpxTracker/GPXMapView.swift @@ -42,20 +42,21 @@ class GPXMapView: MKMapView { var currentSegmentOverlay: MKPolyline /// - var extent: GPXExtentCoordinates = GPXExtentCoordinates() //extent of the GPX points and tracks + var extent: GPXExtentCoordinates = GPXExtentCoordinates() // Extent of the GPX points and tracks - ///position of the compass in the map - ///Example: + /// Position of the compass in the map + /// Example: /// map.compassRect = CGRect(x: map.frame.width/2 - 18, y: 70, width: 36, height: 36) var compassRect: CGRect /// Is the map using local image cache?? - var useCache: Bool = true { //use tile overlay cache ( + var useCache: Bool = true { // Use tile overlay cache ( didSet { if tileServerOverlay is CachedTileOverlay { print("GPXMapView:: setting useCache \(useCache)") // swiftlint:disable force_cast (tileServerOverlay as! CachedTileOverlay).useCache = useCache + // swiftlint:enable force_cast } } } @@ -72,13 +73,13 @@ class GPXMapView: MKMapView { updateMapInformation(newValue) // remove current overlay if tileServer != .apple { - //to see apple maps we need to remove the overlay added by map cache. + // To see apple maps we need to remove the overlay added by map cache. removeOverlay(tileServerOverlay) } - //add new overlay to map if not using Apple Maps + // Add new overlay to map if not using Apple Maps if newValue != .apple && newValue != .appleSatellite { - //Update cacheConfig + // Update cacheConfig var config = MapCacheConfig(withUrlTemplate: newValue.templateUrl) config.subdomains = newValue.subdomains config.tileSize = CGSize(width: newValue.tileSize, height: newValue.tileSize) @@ -93,8 +94,7 @@ class GPXMapView: MKMapView { // we need to keep a reference to remove it, in case we return back to Apple Maps. // tileServerOverlay = useCache(cache, canReplaceMapContent: newValue.canReplaceMapContent) - } - else { + } else { self.mapType = (newValue == .apple) ? .standard : .satellite } } @@ -130,7 +130,7 @@ class GPXMapView: MKMapView { /// Initializes the map with an empty currentSegmentOverlay. /// required init?(coder aDecoder: NSCoder) { - var tmpCoords: [CLLocationCoordinate2D] = [] //init with empty + var tmpCoords: [CLLocationCoordinate2D] = [] // Init with empty currentSegmentOverlay = MKPolyline(coordinates: &tmpCoords, count: 0) compassRect = CGRect.init(x: 0, y: 0, width: 36, height: 36) super.init(coder: aDecoder) @@ -257,8 +257,8 @@ class GPXMapView: MKMapView { let pt = GPXTrackPoint(location: location) coreDataHelper.add(toCoreData: pt, withTrackSegmentID: session.trackSegments.count) session.addPointToCurrentTrackSegmentAtLocation(location) - //redrawCurrent track segment overlay - //First remove last overlay, then re-add the overlay updated with the new point + // RedrawCurrent track segment overlay + // First remove last overlay, then re-add the overlay updated with the new point removeOverlay(currentSegmentOverlay) currentSegmentOverlay = session.currentSegment.overlay @@ -283,7 +283,7 @@ class GPXMapView: MKMapView { /// Finishes current segment. /// func finishCurrentSegment() { - startNewTrackSegment() //basically, we need to append the segment to the list of segments + startNewTrackSegment() // Basically, we need to append the segment to the list of segments } /// @@ -295,8 +295,8 @@ class GPXMapView: MKMapView { removeAnnotations(annotations) extent = GPXExtentCoordinates() - //add tile server overlay - //by removing all overlays, tile server overlay is also removed. We need to add it back + // Add tile server overlay + // by removing all overlays, tile server overlay is also removed. We need to add it back if tileServer != .apple { addOverlayOnBottom(tileServerOverlay) } @@ -344,10 +344,9 @@ class GPXMapView: MKMapView { session.totalTrackedDistance += oneTrack.length for segment in oneTrack.segments { let overlay = segment.overlay - //addOverlay(overlay) addOverlayOnTop(overlay) let segmentTrackpoints = segment.points - //add point to map extent + // Add point to map extent for waypoint in segmentTrackpoints { extent.extendAreaToIncludeLocation(waypoint.coordinate) } @@ -366,26 +365,24 @@ class GPXMapView: MKMapView { session.totalTrackedDistance += oneTrack.length for segment in oneTrack.segments { let overlay = segment.overlay - //addOverlay(overlay) addOverlayOnTop(overlay) let segmentTrackpoints = segment.points - //add point to map extent + // Add point to map extent for waypoint in segmentTrackpoints { extent.extendAreaToIncludeLocation(waypoint.coordinate) } } } - // for last session track segment + // For last session track segment for trackSegment in session.trackSegments { let overlay = trackSegment.overlay - //addOverlay(overlay) addOverlayOnTop(overlay) let segmentTrackpoints = trackSegment.points - //add point to map extent + // Add point to map extent for waypoint in segmentTrackpoints { extent.extendAreaToIncludeLocation(waypoint.coordinate) } From ad594e3b60ae70ebfe49813f17f00fccf7b54a5b Mon Sep 17 00:00:00 2001 From: merlos Date: Thu, 1 Jun 2023 15:10:55 +0300 Subject: [PATCH 27/27] fixed the large majority of the swiftlint warnings --- .../GPXFileTableInterfaceController.swift | 6 +- .../InterfaceController.swift | 57 +++++++------------ OpenGpxTracker/AboutViewController.swift | 7 +-- OpenGpxTracker/AppDelegate.swift | 5 +- .../CoreDataHelper+FetchRequests.swift | 4 +- OpenGpxTracker/CoreDataHelper.swift | 21 +++---- OpenGpxTracker/DefaultDateFormat.swift | 1 - .../DefaultNameSetupViewController.swift | 44 +++++++------- OpenGpxTracker/DistanceLabel.swift | 4 +- OpenGpxTracker/GPXExtentCoordinates.swift | 13 ++--- OpenGpxTracker/GPXFileInfo.swift | 4 +- OpenGpxTracker/GPXFileManager.swift | 10 ++-- .../GPXFilesTableViewController.swift | 9 +-- OpenGpxTracker/GPXMapView.swift | 3 +- OpenGpxTracker/GPXSession.swift | 20 +++---- OpenGpxTracker/GPXTileServer.swift | 4 +- OpenGpxTracker/GPXTrackSegment+MapKit.swift | 8 +-- OpenGpxTracker/GPXWaypoint+MKAnnotation.swift | 26 ++++----- OpenGpxTracker/Int+asFilesize.swift | 2 +- OpenGpxTracker/MailerManager.swift | 4 +- OpenGpxTracker/MapViewDelegate.swift | 17 ++---- OpenGpxTracker/Preferences.swift | 6 +- .../PreferencesTableViewController.swift | 28 ++++----- OpenGpxTracker/StopWatch.swift | 16 +++--- 24 files changed, 137 insertions(+), 182 deletions(-) diff --git a/OpenGpxTracker-Watch Extension/GPXFileTableInterfaceController.swift b/OpenGpxTracker-Watch Extension/GPXFileTableInterfaceController.swift index 94fe1cf..e4eb497 100644 --- a/OpenGpxTracker-Watch Extension/GPXFileTableInterfaceController.swift +++ b/OpenGpxTracker-Watch Extension/GPXFileTableInterfaceController.swift @@ -176,7 +176,7 @@ class GPXFileTableInterfaceController: WKInterfaceController { if gpxFilesFound { for index in 0.. Void in - self.trackerButton.hidden = true - self.pauseButton.hidden = false - }, completion: {(f: Bool) -> Void in - println("finished animation start tracking") - }) - */ - + case .tracking: print("switched to tracking mode") // set trackerButton to allow Pause trackerButton.setTitle(NSLocalizedString("PAUSE", comment: "no comment")) trackerButton.setBackgroundColor(kPurpleButtonBackgroundColor) - //activate save & reset buttons + // Activate save & reset buttons saveButton.setBackgroundColor(kBlueButtonBackgroundColor) resetButton.setBackgroundColor(kRedButtonBackgroundColor) // start clock @@ -173,7 +161,7 @@ class InterfaceController: WKInterfaceController { // activate save & reset (just in case switched from .NotStarted) saveButton.setBackgroundColor(kBlueButtonBackgroundColor) resetButton.setBackgroundColor(kRedButtonBackgroundColor) - //pause clock + // Pause clock self.stopWatch.stop() // start new track segment self.map.startNewTrackSegment() @@ -182,7 +170,7 @@ class InterfaceController: WKInterfaceController { } /// Editing Waypoint Temporal Reference - var lastLocation: CLLocation? //Last point of current segment. + var lastLocation: CLLocation? // Last point of current segment. override func awake(withContext context: Any?) { print("InterfaceController:: awake") @@ -242,7 +230,7 @@ class InterfaceController: WKInterfaceController { case .tracking: gpxTrackingStatus = .paused case .paused: - //set to tracking + // Set to tracking gpxTrackingStatus = .tracking } @@ -279,7 +267,7 @@ class InterfaceController: WKInterfaceController { let gpxString = self.map.exportToGPXString() GPXFileManager.save(filename, gpxContents: gpxString) self.lastGpxFilename = filename - //print(gpxString) + // print(gpxString) /// Just a 'done' button, without let action = WKAlertAction(title: "Done", style: .default) {} @@ -330,19 +318,19 @@ class InterfaceController: WKInterfaceController { func checkLocationServicesStatus() { let authorizationStatus = CLLocationManager.authorizationStatus() - //Has the user already made a permission choice? + // Has the user already made a permission choice? guard authorizationStatus != .notDetermined else { - //We should take no action until the user has made a choice + // We should take no action until the user has made a choice return } - //Does the app have permissions to use the location servies? + // Does the app have permissions to use the location servies? guard [.authorizedAlways, .authorizedWhenInUse ].contains(authorizationStatus) else { displayLocationServicesDeniedAlert() return } - //Are location services enabled? + // Are location services enabled? guard CLLocationManager.locationServicesEnabled() else { displayLocationServicesDisabledAlert() return @@ -408,8 +396,6 @@ extension InterfaceController: CLLocationManagerDelegate { altitudeLabel.setText(kUnknownAltitudeText) signalImageView.setImage(signalImage0) speedLabel.setText(kUnknownSpeedText) - //signalAccuracyLabel.text = kUnknownAccuracyText - //signalImageView.image = signalImage0 let locationError = error as? CLError switch locationError?.code { case CLError.locationUnknown: @@ -430,7 +416,7 @@ extension InterfaceController: CLLocationManagerDelegate { /// /// func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { - //updates signal image accuracy + // Updates signal image accuracy let newLocation = locations.first! let hAcc = newLocation.horizontalAccuracy @@ -461,14 +447,13 @@ extension InterfaceController: CLLocationManagerDelegate { coordinatesLabel.setText("\(latFormat),\(lonFormat)") altitudeLabel.setText(newLocation.altitude.toAltitude(useImperial: preferences.useImperial)) - //Update speed (provided in m/s, but displayed in km/h) + // Update speed (provided in m/s, but displayed in km/h) speedLabel.setText(newLocation.speed.toSpeed(useImperial: preferences.useImperial)) if gpxTrackingStatus == .tracking { print("didUpdateLocation: adding point to track (\(newLocation.coordinate.latitude),\(newLocation.coordinate.longitude))") map.addPointToCurrentTrackSegmentAtLocation(newLocation) totalTrackedDistanceLabel.setText(map.totalTrackedDistance.toDistance(useImperial: preferences.useImperial)) - //currentSegmentDistanceLabel.distance = map.currentSegmentDistance } } } diff --git a/OpenGpxTracker/AboutViewController.swift b/OpenGpxTracker/AboutViewController.swift index e2f89ff..e72bb6f 100644 --- a/OpenGpxTracker/AboutViewController.swift +++ b/OpenGpxTracker/AboutViewController.swift @@ -42,13 +42,13 @@ class AboutViewController: UIViewController { self.title = NSLocalizedString("ABOUT", comment: "no comment") - //Add the done button + // Add the done button let shareItem = UIBarButtonItem(title: NSLocalizedString("DONE", comment: "no comment"), style: UIBarButtonItem.Style.plain, target: self, action: #selector(AboutViewController.closeViewController)) self.navigationItem.rightBarButtonItems = [shareItem] - //Add the Webview + // Add the Webview self.webView = WKWebView(frame: self.view.frame, configuration: WKWebViewConfiguration()) self.webView?.navigationDelegate = self @@ -82,8 +82,7 @@ extension AboutViewController: WKNavigationDelegate { if navigationAction.navigationType == .linkActivated { if #available(iOS 10, *) { UIApplication.shared.open(navigationAction.request.url!) - } - else { + } else { UIApplication.shared.openURL(navigationAction.request.url!) } print("AboutViewController: external link sent to Safari") diff --git a/OpenGpxTracker/AppDelegate.swift b/OpenGpxTracker/AppDelegate.swift index 3385ec2..39aa9fa 100644 --- a/OpenGpxTracker/AppDelegate.swift +++ b/OpenGpxTracker/AppDelegate.swift @@ -67,7 +67,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func applicationWillTerminate(_ application: UIApplication) { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. // Saves changes in the application's managed object context before the application terminates. - //self.saveContext() + // self.saveContext() } /// Default pandle load GPX file @@ -211,9 +211,8 @@ extension AppDelegate: WCSessionDelegate { /// Called when a file is received from Apple Watch. /// Displays a popup informing about the reception of the file. func session(_ session: WCSession, didReceive file: WCSessionFile) { - // swiftlint:disable force_cast + // swiftlint:disable:next force_cast let fileName = file.metadata!["fileName"] as! String? - DispatchQueue.global().sync { GPXFileManager.moveFrom(file.fileURL, fileName: fileName) print("ViewController:: Received file from WatchConnectivity Session") diff --git a/OpenGpxTracker/CoreDataHelper+FetchRequests.swift b/OpenGpxTracker/CoreDataHelper+FetchRequests.swift index a575c0a..d48d6be 100644 --- a/OpenGpxTracker/CoreDataHelper+FetchRequests.swift +++ b/OpenGpxTracker/CoreDataHelper+FetchRequests.swift @@ -22,7 +22,8 @@ extension CoreDataHelper { self.lastFileName = safePoint.lastFileName ?? "" self.lastTracksegmentId = safePoint.lastTrackSegmentId self.isContinued = safePoint.continuedAfterSave - print("Core Data Helper: fetched CDRoot lastFileName:\(self.lastFileName) lastTracksegmentId: \(self.lastTracksegmentId) isContinued: \(self.isContinued)") + // swiftlint:disable:next line_length + print("Core Data Helper: fetched CDRoot lastFileName:\(self.lastFileName) lastTracksegmentId: \(self.lastTracksegmentId) isContinued: \(self.isContinued)") } } return asyncRootFetchRequest @@ -70,6 +71,7 @@ extension CoreDataHelper { } self.trackpointId = trackPointResults.last?.trackpointId ?? Int64() self.tracksegments.append(self.currentSegment) + // siftlint:disable:next line_length print("Core Data Helper: fetched CDTrackpoints. # of tracksegments: \(self.tracksegments.count). trackPointId: \(self.trackpointId) trackSegmentId: \(self.tracksegmentId)") } } diff --git a/OpenGpxTracker/CoreDataHelper.swift b/OpenGpxTracker/CoreDataHelper.swift index 8bfa672..e85e92a 100644 --- a/OpenGpxTracker/CoreDataHelper.swift +++ b/OpenGpxTracker/CoreDataHelper.swift @@ -34,9 +34,8 @@ class CoreDataHelper { // MARK: Other Declarations /// app delegate. - // swiftlint:disable force_cast let appDelegate = UIApplication.shared.delegate as! AppDelegate - + // swiftlint:disable:previous force_cast // arrays for handling retrieval of data when needed. // recovered tracksegments @@ -65,8 +64,8 @@ class CoreDataHelper { childManagedObjectContext.parent = appDelegate.managedObjectContext childManagedObjectContext.perform { + // swiftlint:disable:next force_cast let root = NSEntityDescription.insertNewObject(forEntityName: "CDRoot", into: childManagedObjectContext) as! CDRoot - root.lastFileName = lastFileName root.continuedAfterSave = willContinue root.lastTrackSegmentId = self.tracksegmentId @@ -101,7 +100,7 @@ class CoreDataHelper { childManagedObjectContext.perform { print("Core Data Helper: Add trackpoint with id: \(self.trackpointId)") - // swiftlint:disable force_cast + // swiftlint:disable:next force_cast let pt = NSEntityDescription.insertNewObject(forEntityName: "CDTrackpoint", into: childManagedObjectContext) as! CDTrackpoint guard let elevation = trackpoint.elevation else { return } @@ -153,9 +152,8 @@ class CoreDataHelper { waypointChildManagedObjectContext.perform { print("Core Data Helper: Add waypoint with id: \(self.waypointId)") - // swiftlint:disable force_cast + // swiftlint:disable:next force_cast let pt = NSEntityDescription.insertNewObject(forEntityName: "CDWaypoint", into: waypointChildManagedObjectContext) as! CDWaypoint - guard let latitude = waypoint.latitude else { return } guard let longitude = waypoint.longitude else { return } @@ -252,7 +250,6 @@ class CoreDataHelper { print("Failure to update and save waypoint to context at child context: \(error)") } } - } do { @@ -332,7 +329,6 @@ class CoreDataHelper { /// Delete all objects of entity given as parameter in Core Data. func coreDataDeleteAll(of type: T.Type) { - print("Core Data Helper: Batch Delete \(T.self) from Core Data") if #available(iOS 10.0, *) { @@ -372,7 +368,7 @@ class CoreDataHelper { // generates a GPXRoot from recovered data if self.isContinued && self.tracksegments.count >= (self.lastTracksegmentId + 1) { - //Check if there was a tracksegment + // Check if there was a tracksegment if root.tracks.last?.segments.count == 0 { root.tracks.last?.add(trackSegment: GPXTrackSegment()) } @@ -389,7 +385,8 @@ class CoreDataHelper { DispatchQueue.main.sync { NotificationCenter.default.post(name: .loadRecoveredFile, object: nil, userInfo: ["recoveredRoot": root, "fileName": self.lastFileName]) - let toastMessage = NSLocalizedString("LAST_SESSION_LOADED", comment: "the filename displayed after the text") + " \n" + self.lastFileName + ".gpx" + let toastMessage = NSLocalizedString("LAST_SESSION_LOADED", + comment: "the filename displayed after the text") + " \n" + self.lastFileName + ".gpx" Toast.regular(toastMessage, position: .top) } } else { @@ -425,7 +422,6 @@ class CoreDataHelper { // clear aft save. self.clearAll() self.coreDataDeleteAll(of: CDRoot.self) - //self.deleteCDRootFromCoreData() } // MARK: Reset & Clear @@ -438,7 +434,6 @@ class CoreDataHelper { self.trackpointId = 0 self.waypointId = 0 self.tracksegmentId = 0 - } /// Clear all arrays and current segment after recovery. @@ -477,7 +472,5 @@ class CoreDataHelper { // reset order sorting ids self.resetIds() - } - } diff --git a/OpenGpxTracker/DefaultDateFormat.swift b/OpenGpxTracker/DefaultDateFormat.swift index e354aea..44f2f90 100644 --- a/OpenGpxTracker/DefaultDateFormat.swift +++ b/OpenGpxTracker/DefaultDateFormat.swift @@ -46,7 +46,6 @@ class DefaultDateFormat { /// Returns sample date time based on user input. func getDate(processedFormat dateFormat: String, useUTC: Bool = false, useENLocale: Bool = false) -> String { - //processedDateFormat = DefaultDateFormat.getDateFormat(unprocessed: self.cellTextField.text!) dateFormatter.dateFormat = dateFormat dateFormatter.timeZone = useUTC ? TimeZone(secondsFromGMT: 0) : TimeZone.current dateFormatter.locale = useENLocale ? Locale(identifier: "en_US_POSIX") : Locale.current diff --git a/OpenGpxTracker/DefaultNameSetupViewController.swift b/OpenGpxTracker/DefaultNameSetupViewController.swift index fa7a3a2..f619a80 100644 --- a/OpenGpxTracker/DefaultNameSetupViewController.swift +++ b/OpenGpxTracker/DefaultNameSetupViewController.swift @@ -66,7 +66,7 @@ class DefaultNameSetupViewController: UITableViewController, UITextFieldDelegate @objc func dateButtonTapped(_ sender: Notification) { if cellTextField.text != nil { guard let notificationValues = sender.userInfo else { return } - // swiftlint:disable force_cast + // swiftlint:disable:next force_cast let patternDict = notificationValues as! [String: String] guard let pattern = patternDict["sender"] else { return } @@ -126,7 +126,6 @@ class DefaultNameSetupViewController: UITableViewController, UITextFieldDelegate let processed = defaultDateFormat.getDateFormat(unprocessed: self.cellTextField.text!) processedDateFormat = processed.0 dateFormatIsInvalid = processed.1 - //dateFormatter.dateFormat = processedDateFormat cellSampleLabel.text = defaultDateFormat.getDate(processedFormat: processedDateFormat, useUTC: useUTC, useENLocale: useEN) } @@ -141,7 +140,7 @@ class DefaultNameSetupViewController: UITableViewController, UITextFieldDelegate /// handling of textfield when editing commence. func textFieldDidBeginEditing(_ textField: UITextField) { - //remove checkmark from selected date format preset, as textfield edited == not preset anymore + // Remove checkmark from selected date format preset, as textfield edited == not preset anymore let selectedIndexPath = IndexPath(row: preferences.dateFormatPreset, section: Sections.presets.rawValue) tableView.cellForRow(at: selectedIndexPath)?.accessoryType = .none useUTC = false // clear UTC value, unlock UTC cell, as format may now be custom. @@ -152,9 +151,9 @@ class DefaultNameSetupViewController: UITableViewController, UITextFieldDelegate func textFieldDidEndEditing(_ textField: UITextField) { if cellTextField.text != preferences.dateFormatInput { saveDateFormat(processedDateFormat, input: cellTextField.text) - // save if user input is custom / derivative of preset. + // Save if user input is custom / derivative of preset. } else { - // to get back preset set, and its rules (such as UTC for ISO8601 preset) + // To get back preset set, and its rules (such as UTC for ISO8601 preset) let selectedIndexPath = IndexPath(row: preferences.dateFormatPreset, section: Sections.presets.rawValue) tableView.cellForRow(at: selectedIndexPath)?.accessoryType = .checkmark @@ -196,12 +195,12 @@ class DefaultNameSetupViewController: UITableViewController, UITextFieldDelegate updateSampleTextField() } - /// return number of sections based on `Sections` + /// Returns number of sections based on `Sections` override func numberOfSections(in tableView: UITableView) -> Int { return Sections.allCases.count } - /// implement title of each section + /// Implement title of each section override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { switch section { case Sections.input.rawValue: return NSLocalizedString("DEFAULT_NAME_DATE_FORMAT", comment: "no comment") @@ -211,14 +210,14 @@ class DefaultNameSetupViewController: UITableViewController, UITextFieldDelegate } } - /// implement footer for input section only + /// Implements footer for input section only override func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? { if section == Sections.input.rawValue { return NSLocalizedString("DEFAULT_NAME_INPUT_FOOTER", comment: "no comment") } else { return nil } } - /// return number of rows in each section + /// Returns number of rows in each section override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { switch section { case Sections.input.rawValue: return 2 @@ -231,14 +230,14 @@ class DefaultNameSetupViewController: UITableViewController, UITextFieldDelegate } } - /// setup each cell, according its requirements. - override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + /// Setups each cell, according its requirements. + override func tableView(_ tableView: UITableView, + cellForRowAt indexPath: IndexPath) -> UITableViewCell { var cell = UITableViewCell(style: .default, reuseIdentifier: "inputCell") if indexPath.section == Sections.input.rawValue { if indexPath.row == 0 { - cellSampleLabel = UILabel(frame: CGRect(x: 87, y: 0, width: view.frame.width - 99, height: cell.frame.height)) cellSampleLabel.font = .boldSystemFont(ofSize: 17) cell.addSubview(cellSampleLabel) @@ -247,9 +246,7 @@ class DefaultNameSetupViewController: UITableViewController, UITextFieldDelegate cellSampleLabel.adjustsFontSizeToFitWidth = true cell.textLabel!.text = NSLocalizedString("DEFAULT_NAME_SAMPLE_OUTPUT_TITLE", comment: "no comment") cell.textLabel?.font = .systemFont(ofSize: 17) - } else if indexPath.row == 1 { - cellTextField = UITextField(frame: CGRect(x: 22, y: 0, width: view.frame.width - 48, height: cell.frame.height)) cellTextField.text = preferences.dateFormatInput updateSampleTextField() @@ -264,21 +261,21 @@ class DefaultNameSetupViewController: UITableViewController, UITextFieldDelegate cellTextField.inputAccessoryView = createSimpleDateSelectionBar() } cellTextField.addTarget(self, action: #selector(updateSampleTextField), for: UIControl.Event.editingChanged) - cell.contentView.addSubview(cellTextField) } cell.selectionStyle = .none cellTextField.autocorrectionType = .no } else if indexPath.section == Sections.settings.rawValue { if indexPath.row == 0 { - cell.textLabel!.text = NSLocalizedString("DEFAULT_NAME_USE_UTC", comment: "no comment")//"Use UTC?" + cell.textLabel!.text = NSLocalizedString("DEFAULT_NAME_USE_UTC", + comment: "no comment")// "Use UTC?" cell.accessoryType = preferences.dateFormatUseUTC ? .checkmark : .none if preferences.dateFormatPreset == 1 { cell.isUserInteractionEnabled = !useUTC cell.textLabel?.isEnabled = !useUTC } } else if indexPath.row == 1 { - cell.textLabel!.text = NSLocalizedString("DEFAULT_NAME_ENGLISH_LOCALE", comment: "no comment")//"Force English Locale?" + cell.textLabel!.text = NSLocalizedString("DEFAULT_NAME_ENGLISH_LOCALE", comment: "no comment")// "Force English Locale?" cell.accessoryType = preferences.dateFormatUseEN ? .checkmark : .none } updateSampleTextField() @@ -291,7 +288,6 @@ class DefaultNameSetupViewController: UITableViewController, UITextFieldDelegate cell.accessoryType = preferences.dateFormatPreset == indexPath.row ? .checkmark : .none } } - return cell } @@ -299,13 +295,13 @@ class DefaultNameSetupViewController: UITableViewController, UITextFieldDelegate override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { if indexPath.section == Sections.settings.rawValue { if indexPath.row == 0 { - //remove checkmark from selected utc setting + // Remove checkmark from selected utc setting let newUseUTC = !preferences.dateFormatUseUTC preferences.dateFormatUseUTC = newUseUTC useUTC = newUseUTC tableView.cellForRow(at: indexPath)?.accessoryType = newUseUTC ? .checkmark : .none } else if indexPath.row == 1 { - //remove checkmark from selected en locale setting + // Remove checkmark from selected en locale setting let newUseEN = !preferences.dateFormatUseEN preferences.dateFormatUseEN = newUseEN useEN = newUseEN @@ -314,15 +310,13 @@ class DefaultNameSetupViewController: UITableViewController, UITextFieldDelegate updateSampleTextField() } if indexPath.section == Sections.presets.rawValue { - //cellSampleLabel.text = "{\(presets[indexPath.row].1)}" cellTextField.text = presets[indexPath.row].2 - - //update cell UI - //remove checkmark from selected date format preset + // Update cell UI + // Remove checkmark from selected date format preset let selectedIndexPath = IndexPath(row: preferences.dateFormatPreset, section: indexPath.section) tableView.cellForRow(at: selectedIndexPath)?.accessoryType = .none - //add checkmark to new selected date format preset + // Add checkmark to new selected date format preset tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark preferences.dateFormatPreset = indexPath.row preferences.dateFormatInput = presets[indexPath.row].2 diff --git a/OpenGpxTracker/DistanceLabel.swift b/OpenGpxTracker/DistanceLabel.swift index 9586734..c96ede5 100644 --- a/OpenGpxTracker/DistanceLabel.swift +++ b/OpenGpxTracker/DistanceLabel.swift @@ -24,7 +24,7 @@ open class DistanceLabel: UILabel { /// Internal variable that keeps the actual distance private var _distance = 0.0 - ///Internal variable to keep the use of imperial units + /// Internal variable to keep the use of imperial units private var _useImperial = false /// Use imperial units (miles)? False by default. @@ -35,7 +35,7 @@ open class DistanceLabel: UILabel { } set { _useImperial = newValue - distance = _distance //updates text displayed to reflect the new units + distance = _distance // Updates text displayed to reflect the new units } } diff --git a/OpenGpxTracker/GPXExtentCoordinates.swift b/OpenGpxTracker/GPXExtentCoordinates.swift index e9c149f..8ae400b 100644 --- a/OpenGpxTracker/GPXExtentCoordinates.swift +++ b/OpenGpxTracker/GPXExtentCoordinates.swift @@ -38,13 +38,6 @@ class GPXExtentCoordinates: NSObject { /// This is the extent coordinates as a MKCoordinateRegion var region: MKCoordinateRegion { - set { - topLeftCoordinate.latitude = newValue.center.latitude - newValue.span.latitudeDelta/2 - topLeftCoordinate.longitude = newValue.center.longitude + newValue.span.longitudeDelta/2 - bottomRightCoordinate.latitude = newValue.center.latitude + newValue.span.latitudeDelta/2 - bottomRightCoordinate.longitude = newValue.center.longitude - newValue.span.longitudeDelta/2 - } - get { let centerLat = (bottomRightCoordinate.latitude + topLeftCoordinate.latitude) / 2 let centerLon = (bottomRightCoordinate.longitude + topLeftCoordinate.longitude) / 2 @@ -55,5 +48,11 @@ class GPXExtentCoordinates: NSObject { return MKCoordinateRegion.init(center: center, span: span) } + set { + topLeftCoordinate.latitude = newValue.center.latitude - newValue.span.latitudeDelta/2 + topLeftCoordinate.longitude = newValue.center.longitude + newValue.span.longitudeDelta/2 + bottomRightCoordinate.latitude = newValue.center.latitude + newValue.span.latitudeDelta/2 + bottomRightCoordinate.longitude = newValue.center.longitude - newValue.span.longitudeDelta/2 + } } } diff --git a/OpenGpxTracker/GPXFileInfo.swift b/OpenGpxTracker/GPXFileInfo.swift index 586b484..f80e6a1 100644 --- a/OpenGpxTracker/GPXFileInfo.swift +++ b/OpenGpxTracker/GPXFileInfo.swift @@ -19,7 +19,7 @@ class GPXFileInfo: NSObject { /// Last time the file was modified var modifiedDate: Date { - // swiftlint:disable force_try + // swiftlint:disable:next force_try return try! fileURL.resourceValues(forKeys: [.contentModificationDateKey]).contentModificationDate ?? Date.distantPast } @@ -30,7 +30,7 @@ class GPXFileInfo: NSObject { /// File size in bytes var fileSize: Int { - // swiftlint:disable force_try + // swiftlint:disable:next force_try return try! fileURL.resourceValues(forKeys: [.fileSizeKey]).fileSize ?? 0 } diff --git a/OpenGpxTracker/GPXFileManager.swift b/OpenGpxTracker/GPXFileManager.swift index f0d7266..30630cf 100644 --- a/OpenGpxTracker/GPXFileManager.swift +++ b/OpenGpxTracker/GPXFileManager.swift @@ -54,7 +54,7 @@ class GPXFileManager: NSObject { class func URLForFilename(_ filename: String) -> URL { var fullURL = self.GPXFilesFolderURL.appendingPathComponent(filename) print("URLForFilename(\(filename): pathForFilename: \(fullURL)") - //check if filename has extension + // Check if filename has extension if !(kFileExt.contains(fullURL.pathExtension)) { fullURL = fullURL.appendingPathExtension(kFileExt[0]) } @@ -79,7 +79,7 @@ class GPXFileManager: NSObject { /// - gpxContents: String with the contents to be saved. The XML contents of the GPX file /// class func saveToURL(_ fileURL: URL, gpxContents: String) { - //save file + // Save file print("Saving file at path: \(fileURL)") // write gpx to file var writeError: NSError? @@ -106,7 +106,7 @@ class GPXFileManager: NSObject { /// - gpxContents: String with the contents to be saved. The XML contents of the GPX file /// class func save(_ filename: String, gpxContents: String) { - //check if name exists + // Check if name exists let fileURL: URL = self.URLForFilename(filename) GPXFileManager.saveToURL(fileURL, gpxContents: gpxContents) } @@ -195,7 +195,7 @@ class GPXFileManager: NSObject { if let directoryURLs = try? fileManager.contentsOfDirectory(at: rootURL, includingPropertiesForKeys: [.attributeModificationDateKey, .fileSizeKey], options: .skipsSubdirectoryDescendants) { - //Order files based on the date + // Order files based on the date // This map creates a tuple (url: URL, modificationDate: String, filesize: Int) // and then orders it by modificationDate let sortedURLs = directoryURLs.map { url in @@ -205,7 +205,7 @@ class GPXFileManager: NSObject { } .sorted(by: { $0.1 > $1.1 }) // sort descending modification dates print(sortedURLs) - //Now we filter GPX Files + // Now we filter GPX Files for (url, modificationDate, fileSize) in sortedURLs { if kFileExt.contains(url.pathExtension) { GPXFiles.append(GPXFileInfo(fileURL: url)) diff --git a/OpenGpxTracker/GPXFilesTableViewController.swift b/OpenGpxTracker/GPXFilesTableViewController.swift index 2860c56..fafa6e5 100644 --- a/OpenGpxTracker/GPXFilesTableViewController.swift +++ b/OpenGpxTracker/GPXFilesTableViewController.swift @@ -131,12 +131,9 @@ class GPXFilesTableViewController: UITableViewController, UINavigationBarDelegat /// Displays the name of the cell. override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - //let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as UITableViewCell if gpxFilesFound { let cell: UITableViewCell = UITableViewCell(style: UITableViewCell.CellStyle.subtitle, reuseIdentifier: "Cell") - //cell.accessoryType = UITableViewCellAccessoryType.DetailDisclosureButton - //cell.accessoryView = [[ UIImageView alloc ] initWithImage:[UIImage imageNamed:@"Something" ]]; - // swiftlint:disable force_cast + // swiftlint:disable:next force_cast let gpxFileInfo = fileList.object(at: (indexPath as NSIndexPath).row) as! GPXFileInfo let lastSaved = NSLocalizedString("LAST_SAVED", comment: "no comment") cell.textLabel?.text = gpxFileInfo.fileName @@ -199,7 +196,7 @@ class GPXFilesTableViewController: UITableViewController, UINavigationBarDelegat /// Returns the name of the file in the `rowIndex` passed as parameter. internal func fileListObjectTitle(_ rowIndex: Int) -> String { - // swiftlint:disable force_cast + // swiftlint:disable:next force_cast return (fileList.object(at: rowIndex) as! GPXFileInfo).fileName } @@ -223,7 +220,7 @@ class GPXFilesTableViewController: UITableViewController, UINavigationBarDelegat } GPXFileManager.removeFileFromURL(fileURL) - //Delete from list and Table + // Delete from list and Table fileList.removeObject(at: rowIndex) let indexPath = IndexPath(row: rowIndex, section: 0) tableView.deleteRows(at: [indexPath], with: UITableView.RowAnimation.fade) diff --git a/OpenGpxTracker/GPXMapView.swift b/OpenGpxTracker/GPXMapView.swift index e493ae8..b21fc7c 100644 --- a/OpenGpxTracker/GPXMapView.swift +++ b/OpenGpxTracker/GPXMapView.swift @@ -54,9 +54,8 @@ class GPXMapView: MKMapView { didSet { if tileServerOverlay is CachedTileOverlay { print("GPXMapView:: setting useCache \(useCache)") - // swiftlint:disable force_cast + // swiftlint:disable:next force_cast (tileServerOverlay as! CachedTileOverlay).useCache = useCache - // swiftlint:enable force_cast } } } diff --git a/OpenGpxTracker/GPXSession.swift b/OpenGpxTracker/GPXSession.swift index ddb86c3..50fdfd2 100644 --- a/OpenGpxTracker/GPXSession.swift +++ b/OpenGpxTracker/GPXSession.swift @@ -85,12 +85,12 @@ class GPXSession { let pt = GPXTrackPoint(location: location) self.currentSegment.add(trackpoint: pt) - //add the distance to previous tracked point - if self.currentSegment.points.count >= 2 { //at elast there are two points in the segment - let prevPt = self.currentSegment.points[self.currentSegment.points.count-2] //get previous point + // Add the distance to previous tracked point + if self.currentSegment.points.count >= 2 { // At elast there are two points in the segment + let prevPt = self.currentSegment.points[self.currentSegment.points.count-2] // Get previous point guard let latitude = prevPt.latitude, let longitude = prevPt.longitude else { return } let prevPtLoc = CLLocation(latitude: latitude, longitude: longitude) - //now get the distance + // Now get the distance let distance = prevPtLoc.distance(from: location) self.currentTrackDistance += distance self.totalTrackedDistance += distance @@ -131,18 +131,18 @@ class GPXSession { /// func exportToGPXString() -> String { print("Exporting session data into GPX String") - //Create the gpx structure + // Create the gpx structure let gpx = GPXRoot(creator: kGPXCreatorString) gpx.add(waypoints: self.waypoints) let track = GPXTrack() track.add(trackSegments: self.trackSegments) - //add current segment if not empty + // Add current segment if not empty if self.currentSegment.points.count > 0 { track.add(trackSegment: self.currentSegment) } - //add existing tracks + // Add existing tracks gpx.add(tracks: self.tracks) - //add current track + // Add current track gpx.add(track: track) return gpx.gpx() } @@ -152,11 +152,11 @@ class GPXSession { let lastTrack = gpx.tracks.last ?? GPXTrack() totalTrackedDistance += lastTrack.length - //add track segments + // Add track segments self.tracks = gpx.tracks self.trackSegments = lastTrack.segments - // remove last track as that track is packaged by Core Data, but should its tracksegments should be seperated, into self.tracksegments. + // Remove last track as that track is packaged by Core Data, but should its tracksegments should be seperated, into self.tracksegments. if self.tracks.count > 0 { self.tracks.removeLast() } diff --git a/OpenGpxTracker/GPXTileServer.swift b/OpenGpxTracker/GPXTileServer.swift index b97138e..1579c8a 100644 --- a/OpenGpxTracker/GPXTileServer.swift +++ b/OpenGpxTracker/GPXTileServer.swift @@ -27,7 +27,7 @@ enum GPXTileServer: Int { /// Open Street Map tile server case openStreetMap - //case AnotherMap + // case AnotherMap /// CartoDB tile server case cartoDB @@ -41,7 +41,7 @@ enum GPXTileServer: Int { /// OpenSeaMap tile server case openSeaMap - ///String that describes the selected tile server. + /// String that describes the selected tile server. var name: String { switch self { case .apple: return "Apple Mapkit (no offline cache)" diff --git a/OpenGpxTracker/GPXTrackSegment+MapKit.swift b/OpenGpxTracker/GPXTrackSegment+MapKit.swift index d4e9d78..113f85a 100644 --- a/OpenGpxTracker/GPXTrackSegment+MapKit.swift +++ b/OpenGpxTracker/GPXTrackSegment+MapKit.swift @@ -42,20 +42,20 @@ extension GPXTrackSegment { func length() -> CLLocationDistance { var length: CLLocationDistance = 0.0 var distanceTwoPoints: CLLocationDistance - //we need at least two points + // We need at least two points if self.points.count < 2 { return length } - var prev: CLLocation? //previous + var prev: CLLocation? // Previous for point in self.points { let pt: CLLocation = CLLocation(latitude: Double(point.latitude!), longitude: Double(point.longitude!) ) - if prev == nil { //if first point => set it as previous and go for next + if prev == nil { // If first point => set it as previous and go for next prev = pt continue } distanceTwoPoints = pt.distance(from: prev!) length += distanceTwoPoints - //set current point as previous point + // Set current point as previous point prev = pt } return length diff --git a/OpenGpxTracker/GPXWaypoint+MKAnnotation.swift b/OpenGpxTracker/GPXWaypoint+MKAnnotation.swift index 3fcafb9..20003a7 100644 --- a/OpenGpxTracker/GPXWaypoint+MKAnnotation.swift +++ b/OpenGpxTracker/GPXWaypoint+MKAnnotation.swift @@ -20,16 +20,14 @@ extension GPXWaypoint: MKAnnotation { /// convenience init (coordinate: CLLocationCoordinate2D) { self.init(latitude: coordinate.latitude, longitude: coordinate.longitude) - //set default title and subtitle + // Set default title and subtitle // Default title now let timeFormat = DateFormatter() timeFormat.dateStyle = DateFormatter.Style.none timeFormat.timeStyle = DateFormatter.Style.medium - //timeFormat.setLocalizedDateFormatFromTemplate("HH:mm:ss") let subtitleFormat = DateFormatter() - //dateFormat.setLocalizedDateFormatFromTemplate("MMM dd, yyyy") subtitleFormat.dateStyle = DateFormatter.Style.medium subtitleFormat.timeStyle = DateFormatter.Style.medium @@ -47,33 +45,35 @@ extension GPXWaypoint: MKAnnotation { /// Title displayed on the annotation bubble. /// Is the attribute name of the waypoint. public var title: String? { - set { - self.name = newValue - } get { return self.name } + set { + self.name = newValue + } + } /// Subtitle displayed on the annotation bubble /// Description of the GPXWaypoint. public var subtitle: String? { - set { - self.desc = newValue - } get { return self.desc } + set { + self.desc = newValue + } + } - ///Annotation coordinates. Returns/Sets the waypoint latitude and longitudes. + /// Annotation coordinates. Returns/Sets the waypoint latitude and longitudes. public var coordinate: CLLocationCoordinate2D { + get { + return CLLocationCoordinate2D(latitude: self.latitude!, longitude: CLLocationDegrees(self.longitude!)) + } set { self.latitude = newValue.latitude self.longitude = newValue.longitude } - get { - return CLLocationCoordinate2D(latitude: self.latitude!, longitude: CLLocationDegrees(self.longitude!)) - } } } diff --git a/OpenGpxTracker/Int+asFilesize.swift b/OpenGpxTracker/Int+asFilesize.swift index a6e581e..5ea311d 100644 --- a/OpenGpxTracker/Int+asFilesize.swift +++ b/OpenGpxTracker/Int+asFilesize.swift @@ -17,7 +17,7 @@ extension Int { bcf.allowedUnits = [.useAll] bcf.countStyle = .file let string = bcf.string(fromByteCount: Int64(self)) - //print("formatted result: \(string)") + // print("formatted result: \(string)") return string } } diff --git a/OpenGpxTracker/MailerManager.swift b/OpenGpxTracker/MailerManager.swift index 550dd74..5c2027e 100644 --- a/OpenGpxTracker/MailerManager.swift +++ b/OpenGpxTracker/MailerManager.swift @@ -27,13 +27,13 @@ class MailerManager: NSObject, MFMailComposeViewControllerDelegate { // set the subject composer.setSubject("[Open GPX tracker] Gpx File") - //Add some text to the message body + // Add some text to the message body var body = "Open GPX Tracker \n is an open source app for Apple devices. Create GPS tracks and export them to GPX files." composer.setMessageBody(body, isHTML: true) let fileData: NSData = NSData.dataWithContentsOfFile(filepath, options: .DataReadingMappedIfSafe, error: nil) composer.addAttachmentData(fileData, mimeType: "application/gpx+xml", fileName: filepath.lastPathComponent) - //Display the comopser view controller + // Display the comopser view controller controller.presentViewController(composer, animated: true, completion: nil) } diff --git a/OpenGpxTracker/MapViewDelegate.swift b/OpenGpxTracker/MapViewDelegate.swift index 436c848..01c1026 100644 --- a/OpenGpxTracker/MapViewDelegate.swift +++ b/OpenGpxTracker/MapViewDelegate.swift @@ -20,7 +20,6 @@ class MapViewDelegate: NSObject, MKMapViewDelegate, UIAlertViewDelegate { let annotationView: MKPinAnnotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "PinView") annotationView.canShowCallout = true annotationView.isDraggable = true - //let detailButton: UIButton = UIButton.buttonWithType(UIButtonType.DetailDisclosure) as UIButton let deleteButton: UIButton = UIButton(frame: CGRect(x: 0, y: 0, width: 40, height: 40)) deleteButton.setImage(UIImage(named: "delete"), for: UIControl.State()) @@ -52,8 +51,7 @@ class MapViewDelegate: NSObject, MKMapViewDelegate, UIAlertViewDelegate { if #available(iOS 13, *) { if #available(iOS 14, *) { pr.shouldRasterize = false - } - else { + } else { pr.shouldRasterize = true } if mapView.traitCollection.userInterfaceStyle == .dark { @@ -123,7 +121,7 @@ class MapViewDelegate: NSObject, MKMapViewDelegate, UIAlertViewDelegate { annotationView view: MKAnnotationView, didChange newState: MKAnnotationView.DragState, fromOldState oldState: MKAnnotationView.DragState) { - // swiftlint:disable force_cast + // swiftlint:disable:next force_cast let gpxMapView = mapView as! GPXMapView if newState == MKAnnotationView.DragState.ending { @@ -143,14 +141,14 @@ class MapViewDelegate: NSObject, MKMapViewDelegate, UIAlertViewDelegate { /// Adds the pin to the map with an animation (comes from the top of the screen) func mapView(_ mapView: MKMapView, didAdd views: [MKAnnotationView]) { var i = 0 - // swiftlint:disable force_cast + // swiftlint:disable:next force_cast let gpxMapView = mapView as! GPXMapView var hasImpacted = false - //adds the pins with an animation + // Adds the pins with an animation for object in views { i += 1 let annotationView = object as MKAnnotationView - //The only exception is the user location, we add to this the heading icon. + // The only exception is the user location, we add to this the heading icon. if annotationView.annotation!.isKind(of: MKUserLocation.self) { if gpxMapView.headingImageView == nil { let image = UIImage(named: "heading")! @@ -176,7 +174,6 @@ class MapViewDelegate: NSObject, MKMapViewDelegate, UIAlertViewDelegate { }, completion: { (finished) -> Void in if finished { UIView.animate(withDuration: 0.05, animations: { () -> Void in - //aV.transform = CGAffineTransformMakeScale(1.0, 0.8) annotationView.transform = CGAffineTransform(a: 1.0, b: 0, c: 0, d: 0.8, tx: 0, ty: annotationView.frame.size.height*0.1) }, completion: { _ -> Void in @@ -205,11 +202,7 @@ class MapViewDelegate: NSObject, MKMapViewDelegate, UIAlertViewDelegate { guard let map = mapView as? GPXMapView else { return } - //print("MapView: User interaction has ended") - map.updateHeading() - - //Is } } diff --git a/OpenGpxTracker/Preferences.swift b/OpenGpxTracker/Preferences.swift index 4c5ffc3..8870695 100644 --- a/OpenGpxTracker/Preferences.swift +++ b/OpenGpxTracker/Preferences.swift @@ -84,14 +84,14 @@ class Preferences: NSObject { private var _dateFormatUseEN: Bool = false /// - private var _gpxFilesFolderBookmark: Data? = nil + private var _gpxFilesFolderBookmark: Data? /// UserDefaults.standard shortcut private let defaults = UserDefaults.standard /// Loads preferences from UserDefaults. private override init() { - //loads preferences into private vars + // Loads preferences into private vars // Use Imperial units if let useImperialDefaults = defaults.object(forKey: kDefaultsKeyUseImperial) as? Bool { @@ -181,7 +181,7 @@ class Preferences: NSObject { } set { _useCache = newValue - //Set defaults + // Set defaults defaults.set(newValue, forKey: kDefaultsKeyUseCache) } } diff --git a/OpenGpxTracker/PreferencesTableViewController.swift b/OpenGpxTracker/PreferencesTableViewController.swift index f040684..ca6c1cd 100644 --- a/OpenGpxTracker/PreferencesTableViewController.swift +++ b/OpenGpxTracker/PreferencesTableViewController.swift @@ -69,7 +69,6 @@ class PreferencesTableViewController: UITableViewController, UINavigationBarDele override func viewDidLoad() { super.viewDidLoad() let navBarFrame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: 64) - //let navigationBar : UINavigationBar = UINavigationBar(frame: navBarFrame) self.tableView.frame = CGRect(x: navBarFrame.width + 1, y: 0, width: self.view.frame.width, height: self.view.frame.height - navBarFrame.height) @@ -188,8 +187,6 @@ class PreferencesTableViewController: UITableViewController, UINavigationBarDele // Map Section if indexPath.section == kMapSourceSection { - //cell.accessoryType = UITableViewCellAccessoryType.DetailDisclosureButton - //cell.accessoryView = [[ UIImageView alloc ] initWithImage:[UIImage imageNamed:@"Something" ]]; let tileServer = GPXTileServer(rawValue: indexPath.row) cell.textLabel?.text = tileServer!.name if indexPath.row == preferences.tileServerInt { @@ -223,7 +220,6 @@ class PreferencesTableViewController: UITableViewController, UINavigationBarDele if indexPath.section == kGPXFilesLocationSection { cell = UITableViewCell(style: .value1, reuseIdentifier: "GPXFilesLocation") if let url = preferences.gpxFilesFolderURL { - //cell.textLabel?.lineBreakMode = .byTruncatingHead cell.textLabel?.text = url.lastPathComponent } else { cell.textLabel?.text = NSLocalizedString("USING_DEFAULT_FOLDER", comment: "no comment") @@ -259,9 +255,9 @@ class PreferencesTableViewController: UITableViewController, UINavigationBarDele let newUseImperial = !preferences.useImperial preferences.useImperial = newUseImperial print("PreferencesTableViewController: toggle imperial units to \(newUseImperial)") - //update cell UI + // Update cell UI tableView.cellForRow(at: indexPath)?.accessoryType = newUseImperial ? .checkmark : .none - //notify the map + // Notify the map self.delegate?.didUpdateUseImperial(newUseImperial) default: fatalError("didSelectRowAt: Unknown cell") @@ -272,21 +268,21 @@ class PreferencesTableViewController: UITableViewController, UINavigationBarDele switch indexPath.row { case kUseOfflineCacheCell: print("toggle cache") - let newUseCache = !preferences.useCache //toggle value + let newUseCache = !preferences.useCache // Toggle value preferences.useCache = newUseCache - //update cell + // Update cell tableView.cellForRow(at: indexPath)?.accessoryType = newUseCache ? .checkmark : .none - //notify the map + // Notify the map self.delegate?.didUpdateUseCache(newUseCache) case kClearCacheCell: print("clear cache") - //Create a cache + // Create a cache cache.clear { print("Cache cleaned") let cell = tableView.cellForRow(at: indexPath)! cell.textLabel?.text = NSLocalizedString("CACHE_IS_EMPTY", comment: "no comment") cell.textLabel?.textColor = UIColor.gray - //Clear the size text + // Clear the size text let cell2 = tableView.cellForRow(at: IndexPath(row: kUseOfflineCacheCell, section: kCacheSection)) self.cachedSize = 0.asFileSize() cell2?.detailTextLabel?.text = self.cachedSize @@ -299,15 +295,15 @@ class PreferencesTableViewController: UITableViewController, UINavigationBarDele if indexPath.section == kMapSourceSection { // section 1 (sets tileServerInt in defaults print("PreferenccesTableView Map Tile Server section Row at index: \(indexPath.row)") - //remove checkmark from selected tile server + // Remove checkmark from selected tile server let selectedTileServerIndexPath = IndexPath(row: preferences.tileServerInt, section: indexPath.section) tableView.cellForRow(at: selectedTileServerIndexPath)?.accessoryType = .none - //add checkmark to new tile server + // Add checkmark to new tile server tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark preferences.tileServerInt = indexPath.row - //update map + // Update map self.delegate?.didUpdateTileServer((indexPath as NSIndexPath).row) } @@ -317,7 +313,7 @@ class PreferencesTableViewController: UITableViewController, UINavigationBarDele tableView.cellForRow(at: selected)?.accessoryType = .none - //add checkmark to new tile server + // Add checkmark to new tile server tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark preferences.locationActivityTypeInt = indexPath.row + 1 // +1 as activityType raw value starts at index 1 @@ -337,7 +333,7 @@ class PreferencesTableViewController: UITableViewController, UINavigationBarDele self.present(documentVC, animated: true) } - //unselect row + // Unselect row tableView.deselectRow(at: indexPath, animated: true) } diff --git a/OpenGpxTracker/StopWatch.swift b/OpenGpxTracker/StopWatch.swift index d19a220..72b66ee 100644 --- a/OpenGpxTracker/StopWatch.swift +++ b/OpenGpxTracker/StopWatch.swift @@ -34,7 +34,7 @@ class StopWatch: NSObject { var status: StopWatchStatus /// Defines the interval in which the delegate is called - var timeInterval: TimeInterval = 1.00 //seconds + var timeInterval: TimeInterval = 1.00 // seconds /// Timer that handles the synchronous notifications calls to `updateElapsedTime` var timer = Timer() @@ -44,7 +44,7 @@ class StopWatch: NSObject { /// Initializes the stopWatch with elapsed time 0.00 and `stopped` stop watch status. override init() { - self.tmpElapsedTime = 0.0 //seconds + self.tmpElapsedTime = 0.0 // seconds self.status = StopWatchStatus.stopped super.init() } @@ -63,7 +63,7 @@ class StopWatch: NSObject { func stop() { print("StopWatch: stopped") self.status = .stopped - //add difference between start and stop to elapsed time + // Add difference between start and stop to elapsed time let currentTime = Date.timeIntervalSinceReferenceDate let diff = currentTime - startedTime tmpElapsedTime += diff @@ -97,7 +97,7 @@ class StopWatch: NSObject { /// var elapsedTimeString: String { var tmpTime: TimeInterval = self.elapsedTime - //calculate the minutes and hours in elapsed time. + // Calculate the minutes and hours in elapsed time. let hours = UInt32(tmpTime / 3600.0) tmpTime -= (TimeInterval(hours) * 3600) @@ -105,18 +105,18 @@ class StopWatch: NSObject { let minutes = UInt32(tmpTime / 60.0) tmpTime -= (TimeInterval(minutes) * 60) - //calculate the seconds in elapsed time. + // Calculate the seconds in elapsed time. let seconds = UInt32(tmpTime) tmpTime -= TimeInterval(seconds) - //display hours only if >0 + // Display hours only if >0 let strHours = hours > 0 ? String(hours) + "h" : "" - //add the leading zero for minutes, seconds and millseconds and store them as string constants + // Add the leading zero for minutes, seconds and millseconds and store them as string constants let strMinutes = minutes > 9 ? String(minutes):"0" + String(minutes) let strSeconds = seconds > 9 ? String(seconds):"0" + String(seconds) - //concatenate hours, minutes and seconds + // Concatenate hours, minutes and seconds return "\(strHours)\(strMinutes):\(strSeconds)" }