Skip to content

Commit

Permalink
Add Speed menu item + Bug fixes
Browse files Browse the repository at this point in the history
This fixes some long standing bugs e.g. the wrong menubar items are activated on app launch and if a navigation is reset. Coordinate selection crashes the app if the textfield is cleared. CLLocationSpeed is used in more places to indicate the unit of the speed in m/s. An CLLocationSpeed extension helps with converting between km/h and m/s.

Merge

Add missing files
  • Loading branch information
Schlaubischlump committed Jan 31, 2023
1 parent 936629c commit 9112536
Show file tree
Hide file tree
Showing 25 changed files with 534 additions and 56 deletions.
19 changes: 19 additions & 0 deletions LocationSimulator-Bridging-Header.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// LocationSimulator-Bridging-Header.h
// LocationSimulator
//
// Created by David Klopp on 30.01.23.
// Copyright © 2023 David Klopp. All rights reserved.
//

#ifndef LocationSimulator_Bridging_Header_h
#define LocationSimulator_Bridging_Header_h

#import <AppKit/AppKit.h>

@interface NSMenuItem(Private)
- (void)_corePerformAction;
- (BOOL)_viewHandlesEvents;
@end

#endif /* LocationSimulator_Bridging_Header_h */
59 changes: 52 additions & 7 deletions LocationSimulator.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@
6361BA332302272B002986BF /* CLLocationCoordinate2D+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6361BA322302272B002986BF /* CLLocationCoordinate2D+Extension.swift */; };
6361BA3523022C3A002986BF /* MKMultiPoint+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6361BA3423022C3A002986BF /* MKMultiPoint+Extension.swift */; };
6367802E27FA37BC00233CC7 /* PreferenceViewControllerBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6367802D27FA37BC00233CC7 /* PreferenceViewControllerBase.swift */; };
636FD9DF2989A8F7004FBFFF /* SpeedSelectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 636FD9DB2989A8F7004FBFFF /* SpeedSelectionView.swift */; };
636FD9E02989A8F7004FBFFF /* SpeedFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 636FD9DC2989A8F7004FBFFF /* SpeedFormatter.swift */; };
636FD9E12989A8F7004FBFFF /* SpeedStepper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 636FD9DD2989A8F7004FBFFF /* SpeedStepper.swift */; };
636FD9E22989A8F7004FBFFF /* SpeedSelectionView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 636FD9DE2989A8F7004FBFFF /* SpeedSelectionView.xib */; };
636FD9E42989ADF3004FBFFF /* SpeedSelectionAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 636FD9E32989ADF2004FBFFF /* SpeedSelectionAlert.swift */; };
636FD9E62989B717004FBFFF /* SpeedValueTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 636FD9E52989B717004FBFFF /* SpeedValueTransformer.swift */; };
636FD9E82989B840004FBFFF /* CoordinateValueTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 636FD9E72989B840004FBFFF /* CoordinateValueTransformer.swift */; };
636FD9EA2989BBAB004FBFFF /* CLLocationSpeed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 636FD9E92989BBAB004FBFFF /* CLLocationSpeed.swift */; };
637169D627FD880200386021 /* LocationSpoofer+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 637169D527FD880200386021 /* LocationSpoofer+Extension.swift */; };
637169D827FD8D0A00386021 /* Device+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 637169D727FD8D0A00386021 /* Device+Extension.swift */; };
637169DA27FF1C2400386021 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 637169D927FF1C2400386021 /* main.swift */; };
Expand Down Expand Up @@ -220,6 +228,15 @@
6361BA322302272B002986BF /* CLLocationCoordinate2D+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CLLocationCoordinate2D+Extension.swift"; sourceTree = "<group>"; };
6361BA3423022C3A002986BF /* MKMultiPoint+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MKMultiPoint+Extension.swift"; sourceTree = "<group>"; };
6367802D27FA37BC00233CC7 /* PreferenceViewControllerBase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferenceViewControllerBase.swift; sourceTree = "<group>"; };
636FD9CE29887EBA004FBFFF /* LocationSimulator-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "LocationSimulator-Bridging-Header.h"; sourceTree = "<group>"; };
636FD9DB2989A8F7004FBFFF /* SpeedSelectionView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SpeedSelectionView.swift; sourceTree = "<group>"; };
636FD9DC2989A8F7004FBFFF /* SpeedFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SpeedFormatter.swift; sourceTree = "<group>"; };
636FD9DD2989A8F7004FBFFF /* SpeedStepper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SpeedStepper.swift; sourceTree = "<group>"; };
636FD9DE2989A8F7004FBFFF /* SpeedSelectionView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SpeedSelectionView.xib; sourceTree = "<group>"; };
636FD9E32989ADF2004FBFFF /* SpeedSelectionAlert.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SpeedSelectionAlert.swift; sourceTree = "<group>"; };
636FD9E52989B717004FBFFF /* SpeedValueTransformer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpeedValueTransformer.swift; sourceTree = "<group>"; };
636FD9E72989B840004FBFFF /* CoordinateValueTransformer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoordinateValueTransformer.swift; sourceTree = "<group>"; };
636FD9E92989BBAB004FBFFF /* CLLocationSpeed.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CLLocationSpeed.swift; sourceTree = "<group>"; };
637169D527FD880200386021 /* LocationSpoofer+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LocationSpoofer+Extension.swift"; sourceTree = "<group>"; };
637169D727FD8D0A00386021 /* Device+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Device+Extension.swift"; sourceTree = "<group>"; };
637169D927FF1C2400386021 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -342,6 +359,7 @@
13BA350D20A433ED00A0431C = {
isa = PBXGroup;
children = (
636FD9CE29887EBA004FBFFF /* LocationSimulator-Bridging-Header.h */,
6347E1F5281ACACA00A7F9C9 /* Help */,
635722FE28EDD27A00E20D58 /* Localization */,
13BA351820A433EE00A0431C /* LocationSimulator */,
Expand Down Expand Up @@ -475,6 +493,7 @@
isa = PBXGroup;
children = (
633C74C225AA293300161DB4 /* CoordinateSelectionView.xib */,
636FD9E72989B840004FBFFF /* CoordinateValueTransformer.swift */,
632C466023F4CC6A004E5092 /* CoordinateFormatter.swift */,
632C466223F4D9C8004E5092 /* CoordinateStepper.swift */,
632C465823F4B611004E5092 /* CoordinateSelectionView.swift */,
Expand Down Expand Up @@ -576,6 +595,7 @@
isa = PBXGroup;
children = (
6361BA322302272B002986BF /* CLLocationCoordinate2D+Extension.swift */,
636FD9E92989BBAB004FBFFF /* CLLocationSpeed.swift */,
);
path = CoreLocation;
sourceTree = "<group>";
Expand All @@ -584,12 +604,13 @@
isa = PBXGroup;
children = (
63525957258E8FC80031F289 /* Common */,
63D5DF3627D8F0F400F2DCD3 /* AddDeveloperDiskImageView */,
632C466623F76881004E5092 /* CoordinateSelectionView */,
63FDE21B258F9D2400917412 /* GPXSelectionView */,
630C0C9B27DE6DF400C3D5A9 /* HUD */,
63720622259121C600293EA8 /* MapView */,
637206262591418F00293EA8 /* ProgressListView */,
63D5DF3627D8F0F400F2DCD3 /* AddDeveloperDiskImageView */,
636FD9D22989A8CC004FBFFF /* SpeedSelectionView */,
632C466623F76881004E5092 /* CoordinateSelectionView */,
63FDE21B258F9D2400917412 /* GPXSelectionView */,
);
path = Views;
sourceTree = "<group>";
Expand Down Expand Up @@ -649,6 +670,18 @@
path = Downloader;
sourceTree = "<group>";
};
636FD9D22989A8CC004FBFFF /* SpeedSelectionView */ = {
isa = PBXGroup;
children = (
636FD9DE2989A8F7004FBFFF /* SpeedSelectionView.xib */,
636FD9E52989B717004FBFFF /* SpeedValueTransformer.swift */,
636FD9DC2989A8F7004FBFFF /* SpeedFormatter.swift */,
636FD9DD2989A8F7004FBFFF /* SpeedStepper.swift */,
636FD9DB2989A8F7004FBFFF /* SpeedSelectionView.swift */,
);
path = SpeedSelectionView;
sourceTree = "<group>";
};
63720622259121C600293EA8 /* MapView */ = {
isa = PBXGroup;
children = (
Expand All @@ -675,6 +708,7 @@
635F9BA8297D4EB300F0B2E1 /* DownloadProgress */,
6372063E25916BEE00293EA8 /* GPXSelectionAlert.swift */,
6372063B25915F0900293EA8 /* CoordinateSelectionAlert.swift */,
636FD9E32989ADF2004FBFFF /* SpeedSelectionAlert.swift */,
63D5DF3B27D8F29200F2DCD3 /* AddDeveloperDiskImageAlert.swift */,
);
path = Alerts;
Expand Down Expand Up @@ -949,7 +983,7 @@
TargetAttributes = {
13BA351520A433EE00A0431C = {
CreatedOnToolsVersion = 9.3;
LastSwiftMigration = 1020;
LastSwiftMigration = 1420;
SystemCapabilities = {
com.apple.ApplicationGroups.Mac = {
enabled = 0;
Expand Down Expand Up @@ -1013,6 +1047,7 @@
6357231028EDD27A00E20D58 /* MainMenuTranslations.plist in Resources */,
6357231128EDD27A00E20D58 /* MainMenuTranslate.py in Resources */,
6357230E28EDD27A00E20D58 /* LICENSE in Resources */,
636FD9E22989A8F7004FBFFF /* SpeedSelectionView.xib in Resources */,
633C750D25AA8C6800161DB4 /* Main.storyboard in Resources */,
63D5DF3A27D8F14B00F2DCD3 /* AddDeveloperDiskImageView.xib in Resources */,
635F9BBE298075DE00F0B2E1 /* DeveloperDiskImages.json in Resources */,
Expand Down Expand Up @@ -1107,6 +1142,8 @@
635CF723280EC3D30092A99B /* HelpMenubarItem.swift in Sources */,
63D7350027EB74F10044918C /* Constants.swift in Sources */,
6311B799230C150D00AABF3E /* FileManager+DeveloperDiskImages.swift in Sources */,
636FD9E02989A8F7004FBFFF /* SpeedFormatter.swift in Sources */,
636FD9DF2989A8F7004FBFFF /* SpeedSelectionView.swift in Sources */,
63C799FD259659740099B794 /* InfoViewController.swift in Sources */,
633A460322F996E1005B3BE0 /* NSView+Extension.swift in Sources */,
63525922258B74290031F289 /* NavigationMenuabrItem.swift in Sources */,
Expand All @@ -1120,6 +1157,7 @@
63888DD42592B23D00B1DFC9 /* SidebarDataSource.swift in Sources */,
63767569258EADC0000DCEF3 /* NSBezierPath+Extension.swift in Sources */,
635F9B9B2978A7A700F0B2E1 /* ProgressListView.swift in Sources */,
636FD9E42989ADF3004FBFFF /* SpeedSelectionAlert.swift in Sources */,
638B909F254B514C00A520E0 /* PreferenceWindowController.swift in Sources */,
63D5DF4027D969E800F2DCD3 /* DragAndDropBox.swift in Sources */,
6372E3762824772F00188416 /* Application.swift in Sources */,
Expand All @@ -1132,6 +1170,7 @@
630C0C9A27DE4CC500C3D5A9 /* Float+Extension.swift in Sources */,
6372063C25915F0900293EA8 /* CoordinateSelectionAlert.swift in Sources */,
6372063F25916BEE00293EA8 /* GPXSelectionAlert.swift in Sources */,
636FD9E12989A8F7004FBFFF /* SpeedStepper.swift in Sources */,
630C4A152593ECD100442713 /* NoDeviceView.swift in Sources */,
630C0C9E27DE72A600C3D5A9 /* FileManager+License.swift in Sources */,
633A460122F996DE005B3BE0 /* MapViewController.swift in Sources */,
Expand All @@ -1155,8 +1194,10 @@
631EBFE9259415250066D5BB /* DeviceStatus.swift in Sources */,
634069D829343F580045673A /* NSTextField+Extension.swift in Sources */,
63C799F9259656F20099B794 /* NSTouchbarItem+Extension.swift in Sources */,
636FD9E82989B840004FBFFF /* CoordinateValueTransformer.swift in Sources */,
6372061D25911CED00293EA8 /* MapView.swift in Sources */,
633A45FF22F996DA005B3BE0 /* WindowController.swift in Sources */,
636FD9EA2989BBAB004FBFFF /* CLLocationSpeed.swift in Sources */,
63525927258B74750031F289 /* RecentLocationMenubarItem.swift in Sources */,
6382B57F2939686F0061D484 /* ProgressBar.swift in Sources */,
635CF71B280E03AB0092A99B /* DonateDetailViewController.swift in Sources */,
Expand All @@ -1176,6 +1217,7 @@
63D5DF3827D8F12E00F2DCD3 /* AddDeveloperDiskImageView.swift in Sources */,
631EBFE3259409190066D5BB /* Notification+Extension.swift in Sources */,
6376756B258EC809000DCEF3 /* SeparatorLine.swift in Sources */,
636FD9E62989B717004FBFFF /* SpeedValueTransformer.swift in Sources */,
631EC00B2594C1D60066D5BB /* NSViewController+Extension.swift in Sources */,
637169D627FD880200386021 /* LocationSpoofer+Extension.swift in Sources */,
638B90A7254B5A4400A520E0 /* NetworkViewController.swift in Sources */,
Expand Down Expand Up @@ -1297,6 +1339,7 @@
OTHER_CODE_SIGN_FLAGS = "--deep";
SDKROOT = macosx;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
Expand Down Expand Up @@ -1355,6 +1398,7 @@
OTHER_CODE_SIGN_FLAGS = "--deep";
SDKROOT = macosx;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_OPTIMIZATION_LEVEL = "-O";
};
name = Release;
Expand Down Expand Up @@ -1386,7 +1430,7 @@
PRODUCT_BUNDLE_IDENTIFIER = de.davidklopp.locationsimulator;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_OBJC_BRIDGING_HEADER = "LocationSimulator-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
};
Expand Down Expand Up @@ -1419,7 +1463,7 @@
PRODUCT_BUNDLE_IDENTIFIER = de.davidklopp.locationsimulator;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_OBJC_BRIDGING_HEADER = "LocationSimulator-Bridging-Header.h";
SWIFT_VERSION = 5.0;
};
name = Release;
Expand Down Expand Up @@ -1478,6 +1522,7 @@
OTHER_CODE_SIGN_FLAGS = "--deep";
SDKROOT = macosx;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_OPTIMIZATION_LEVEL = "-O";
};
name = Homebrew;
Expand Down Expand Up @@ -1510,7 +1555,7 @@
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "";
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_OBJC_BRIDGING_HEADER = "LocationSimulator-Bridging-Header.h";
SWIFT_VERSION = 5.0;
};
name = Homebrew;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ class DownloadListViewController: NSViewController {
/// - Return: [[DeveloperDiskImage.dmg download links], [DeveloperDiskImage.dmg.signature download links]]
private func getDeveloperDiskImageDownloadLinks(os: String, version: String) -> [String: [URL]] {
// Check if the plist file and the platform inside the file can be found.
guard let jsonPath = FileManager.default.developerDiskImageDownloadDefinitionsFile,
let manager = FileManager.default
guard let jsonPath = manager.developerDiskImageDownloadDefinitionsFile,
let jsonData = try? Data(contentsOf: jsonPath, options: .mappedIfSafe),
let jsonResult = try? JSONSerialization.jsonObject(with: jsonData) as? JSonType else {
logError("DeveloperDiskImages.json not found!")
Expand Down
60 changes: 60 additions & 0 deletions LocationSimulator/Alerts/SpeedSelectionAlert.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//
// CoordinateSelectionAlert.swift
// LocationSimulator
//
// Created by David Klopp on 21.12.20.
// Copyright © 2020 David Klopp. All rights reserved.
//

import AppKit
import CoreLocation

typealias SpeedSelectionCompletionHandler = ((NSApplication.ModalResponse, Double) -> Void)

/// Alert view which lets the user update the speed value.
class SpeedSelectionAlert: NSAlert {

public var speedSelectionView = SpeedSelectionView(frame: CGRect(x: 0, y: 0, width: 170, height: 40))

init(defaultValue: CLLocationSpeed) {
super.init()

self.messageText = "CHANGE_SPEED".localized
self.addButton(withTitle: "CANCEL".localized)
self.addButton(withTitle: "OK".localized)
self.alertStyle = .informational

var frame = self.speedSelectionView.frame
frame.size.width = 200
let contentView = NSView(frame: frame)

let offX = (frame.width - self.speedSelectionView.frame.width) / 2
self.speedSelectionView.frame.origin.x = offX
self.speedSelectionView.speed = defaultValue.inKmH

contentView.addSubview(self.speedSelectionView)
self.accessoryView = contentView
}

override func beginSheetModal(for sheetWindow: NSWindow,
completionHandler handler: ((NSApplication.ModalResponse) -> Void)? = nil) {
fatalError("Do not use this function. Use the two argument implementation instead.")
}

/// Implementation to handle the response more nicely and add a second argument.
func beginSheetModal(for sheetWindow: NSWindow,
completionHandler handler: SpeedSelectionCompletionHandler? = nil) {
// Show the actual coordinate selection.
super.beginSheetModal(for: sheetWindow) { [unowned self] response in
// Get the user entered coordinates
let speed = self.speedSelectionView.getSpeed()
switch response {
// User canceled
case .alertFirstButtonReturn: handler?(.cancel, speed)
// Navigate or teleport depending on whether navigate is available
case .alertSecondButtonReturn: handler?(.OK, speed)
default: break
}
}
}
}
7 changes: 7 additions & 0 deletions LocationSimulator/Constants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,10 @@ let kDeveloperDiskImagesInfo = "\(kGithubWebsite)/raw/info/DeveloperDiskImages.j
// The variance to add to the movement speed. The lower bound is the minimum factor, the upper bounds the maximum
// factor to apply to the current speed. See LocationSpoofer for more details.
let kDefaultMovementSpeedVariance = 0.8..<1.2

// Configure min and maximum speed
let kSpeedSliderLogBase = 16.0
let kSpeedSliderMaxExponent = 2.0

let kMinSpeed = 1.0
let kMaxSpeed = 256.0 // kSpeedSliderLogBase ^ kSpeedSliderMaxExponent
2 changes: 1 addition & 1 deletion LocationSimulator/DeviceStatus.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ enum DeviceStatus {

/// List with all MenubarItems to enable for this state.
public var enabledMenubarItems: [MenubarItem] {
var navigationItems: [NavigationMenubarItem] = [.walk, .cycle, .drive]
var navigationItems: [NavigationMenubarItem] = [.walk, .cycle, .drive, .setSpeed]
let fileMenuItems: [FileMenubarItem] = [.openGPXFile]
var viewMenuItems: [ViewMenubarItem] = [.toggleSidebar, .explore, .hybrid, .satellite]

Expand Down
19 changes: 19 additions & 0 deletions LocationSimulator/Extensions/CoreLocation/CLLocationSpeed.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// CLLocationSpeed.swift
// LocationSimulator
//
// Created by David Klopp on 31.01.23.
// Copyright © 2023 David Klopp. All rights reserved.
//

import CoreLocation

extension CLLocationSpeed {
init(inKmH speed: Double) {
self = (speed * 1000)/(60*60)
}

var inKmH: Double {
return (self * (60 * 60)) / 1000
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ extension FileManager {
}

public var developerDiskImageDownloadDefinitionsFile: URL? {
guard let supportDir = self.getSupportDirectory(create: true) else {
// Note: Do not store this file in the custom support directory
guard let supportDir = self.getAppSupportDirectory(create: true) else {
return nil
}
return supportDir.appendingPathComponent("DeveloperDiskImages.json", isDirectory: false)
Expand Down
Loading

0 comments on commit 9112536

Please sign in to comment.