Skip to content

Commit

Permalink
[ios] Red for over speed; Speed limit for Carplay (#3047)
Browse files Browse the repository at this point in the history
* [ios] Red for over speed; Speed limit for Carplay

iPhone:
- Red speed digits for overspeed.

CarPlay:
- Show speed limit.
- Red speed digits for overspeed.
- Blinking for speed cam.

Continuation of refactoring to unify
all speed conversions and related localizations.
Use MeterPerSecond everywhere.
Use numeric speed instead of string.
Rename of SpeedLimit to SpeedCamLimit
to not confuse with usual limits (not speed cam).

Signed-off-by: Anton Makouski <anton.makouski@gmail.com>

* Changes for review

Signed-off-by: Anton Makouski <anton.makouski@gmail.com>
  • Loading branch information
AntonM030481 authored Aug 9, 2022
1 parent 7a05ecb commit 0e0aed4
Show file tree
Hide file tree
Showing 34 changed files with 403 additions and 316 deletions.
4 changes: 2 additions & 2 deletions android/jni/com/mapswithme/maps/Framework.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1202,15 +1202,15 @@ Java_com_mapswithme_maps_Framework_nativeGetRouteFollowingInfo(JNIEnv * env, jcl
}

auto const & rm = frm()->GetRoutingManager();
auto const isSpeedLimitExceeded = rm.IsRoutingActive() ? rm.IsSpeedLimitExceeded() : false;
auto const isSpeedCamLimitExceeded = rm.IsRoutingActive() ? rm.IsSpeedCamLimitExceeded() : false;
auto const shouldPlaySignal = frm()->GetRoutingManager().GetSpeedCamManager().ShouldPlayBeepSignal();
jobject const result = env->NewObject(
klass, ctorRouteInfoID, jni::ToJavaString(env, info.m_distToTarget),
jni::ToJavaString(env, info.m_targetUnitsSuffix), jni::ToJavaString(env, info.m_distToTurn),
jni::ToJavaString(env, info.m_turnUnitsSuffix), jni::ToJavaString(env, info.m_sourceName),
jni::ToJavaString(env, info.m_displayedStreetName), info.m_completionPercent, info.m_turn,
info.m_nextTurn, info.m_pedestrianTurn, info.m_exitNum, info.m_time, jLanes,
static_cast<jboolean>(isSpeedLimitExceeded), static_cast<jboolean>(shouldPlaySignal));
static_cast<jboolean>(isSpeedCamLimitExceeded), static_cast<jboolean>(shouldPlaySignal));
ASSERT(result, (jni::DescribeException()));
return result;
}
Expand Down
11 changes: 11 additions & 0 deletions iphone/CoreApi/CoreApi/Common/MWMGeoUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@

NS_ASSUME_NONNULL_BEGIN

@interface Measure : NSObject

@property(nonatomic, readonly) double value;
@property(nonatomic, readonly) NSString* valueAsString;

@property(nonatomic, readonly) NSString* unit;

- (instancetype) initAsSpeed:(double) mps;

@end

NS_SWIFT_NAME(GeoUtil)
@interface MWMGeoUtil : NSObject

Expand Down
48 changes: 48 additions & 0 deletions iphone/CoreApi/CoreApi/Common/MWMGeoUtil.mm
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,54 @@
#include "geometry/mercator.hpp"
#include "geometry/angles.hpp"

#include "platform/localization.hpp"
#include "platform/settings.hpp"
#include "platform/measurement_utils.hpp"

@implementation Measure

// Alternative native implementation.
// It has the issue: some localized unit are too long even in .short style. E.g. speed for RU.
/*
let imperial = Settings.measurementUnits() == .imperial
var speedMeasurement = Measurement(value: speed, unit: UnitSpeed.metersPerSecond)
speedMeasurement.convert(to: imperial ? UnitSpeed.milesPerHour : UnitSpeed.kilometersPerHour)
let formatter = MeasurementFormatter()
formatter.unitOptions = .providedUnit
formatter.numberFormatter.maximumFractionDigits = 0
formatter.unitStyle = .short
if speedMeasurement.value < 10
{
formatter.numberFormatter.minimumFractionDigits = 1
formatter.numberFormatter.maximumFractionDigits = 1
}
let speedString = formatter.string(from: speedMeasurement)
*/

- (NSString*) valueAsString {
if (self.value > 9.999)
return [NSString stringWithFormat:@"%.0f", self.value];
else
return [NSString stringWithFormat:@"%.1f", self.value];
}

- (instancetype)initAsSpeed:(double) mps {
self = [super init];
if (self) {
auto units = measurement_utils::Units::Metric;
settings::TryGet(settings::kMeasurementUnits, units);
_value = measurement_utils::MpsToUnits(mps, units);

_unit = @(platform::GetLocalizedSpeedUnits(units).c_str());
}
return self;
}

@end

@implementation MWMGeoUtil

+ (float)angleAtPoint:(CLLocationCoordinate2D)p1 toPoint:(CLLocationCoordinate2D)p2 {
Expand Down
2 changes: 1 addition & 1 deletion iphone/Maps/Categories/UIColor+MapsMeColor.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (UIColor *)opentableBackground;
+ (UIColor *)transparentGreen;
+ (UIColor *)speedLimitRed;
+ (UIColor *)speedLimitGeen;
+ (UIColor *)speedLimitGreen;
+ (UIColor *)speedLimitWhite;
+ (UIColor *)speedLimitLightGray;
+ (UIColor *)speedLimitDarkGray;
Expand Down
2 changes: 1 addition & 1 deletion iphone/Maps/Categories/UIColor+MapsMeColor.m
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ + (UIColor *)speedLimitRed {
return [UIColor colorWithRed:scaled(224) green:scaled(31) blue:scaled(31) alpha:alpha100];
}

+ (UIColor *)speedLimitGeen {
+ (UIColor *)speedLimitGreen {
return [UIColor colorWithRed:scaled(1) green:scaled(104) blue:scaled(44) alpha:alpha100];
}

Expand Down
62 changes: 31 additions & 31 deletions iphone/Maps/Classes/CarPlay/CarPlayRouter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,37 +22,37 @@ final class CarPlayRouter: NSObject {
var speedCameraMode: SpeedCameraManagerMode {
return RoutingManager.routingManager.speedCameraMode
}

override init() {
listenerContainer = ListenerContainer<CarPlayRouterListener>()
initialSpeedCamSettings = RoutingManager.routingManager.speedCameraMode
super.init()
}

func addListener(_ listener: CarPlayRouterListener) {
listenerContainer.addListener(listener)
}

func removeListener(_ listener: CarPlayRouterListener) {
listenerContainer.removeListener(listener)
}

func subscribeToEvents() {
RoutingManager.routingManager.add(self)
}

func unsubscribeFromEvents() {
RoutingManager.routingManager.remove(self)
}

func completeRouteAndRemovePoints() {
let manager = RoutingManager.routingManager
manager.stopRoutingAndRemoveRoutePoints(true)
manager.deleteSavedRoutePoints()
manager.apply(routeType: .vehicle)
previewTrip = nil
}

func rebuildRoute() {
guard let trip = previewTrip else { return }
do {
Expand All @@ -64,7 +64,7 @@ final class CarPlayRouter: NSObject {
})
}
}

func buildRoute(trip: CPTrip) {
completeRouteAndRemovePoints()
previewTrip = trip
Expand All @@ -87,11 +87,11 @@ final class CarPlayRouter: NSObject {
})
return
}

let manager = RoutingManager.routingManager
manager.add(routePoint: startPoint)
manager.add(routePoint: endPoint)

do {
try manager.buildRoute()
} catch let error as NSError {
Expand All @@ -101,7 +101,7 @@ final class CarPlayRouter: NSObject {
})
}
}

func updateStartPointAndRebuild(trip: CPTrip) {
let manager = RoutingManager.routingManager
previewTrip = trip
Expand All @@ -128,27 +128,27 @@ final class CarPlayRouter: NSObject {
})
}
}

func startRoute() {
let manager = RoutingManager.routingManager
manager.startRoute()
}

func setupCarPlaySpeedCameraMode() {
if case .auto = initialSpeedCamSettings {
RoutingManager.routingManager.speedCameraMode = .always
}
}

func setupInitialSpeedCameraMode() {
RoutingManager.routingManager.speedCameraMode = initialSpeedCamSettings
}

func updateSpeedCameraMode(_ mode: SpeedCameraManagerMode) {
initialSpeedCamSettings = mode
RoutingManager.routingManager.speedCameraMode = mode
}

func restoreTripPreviewOnCarplay(beforeRootTemplateDidAppear: Bool) {
guard MWMRouter.isRestoreProcessCompleted() else {
DispatchQueue.main.async { [weak self] in
Expand Down Expand Up @@ -182,7 +182,7 @@ final class CarPlayRouter: NSObject {
CarPlayService.shared.preparePreview(trips: [trip])
}
}

func restoredNavigationSession() -> (CPTrip, RouteInfo)? {
let manager = RoutingManager.routingManager
if manager.isOnRoute,
Expand Down Expand Up @@ -211,21 +211,21 @@ extension CarPlayRouter {
self?.updateUpcomingManeuvers()
}
}

func cancelTrip() {
routeSession?.cancelTrip()
routeSession = nil
completeRouteAndRemovePoints()
RoutingManager.routingManager.resetOnNewTurnCallback()
}

func finishTrip() {
routeSession?.finishTrip()
routeSession = nil
completeRouteAndRemovePoints()
RoutingManager.routingManager.resetOnNewTurnCallback()
}

func updateUpcomingManeuvers() {
let maneuvers = createUpcomingManeuvers()
routeSession?.upcomingManeuvers = maneuvers
Expand All @@ -249,7 +249,7 @@ extension CarPlayRouter {
let measurement = Measurement(value: distance, unit: routeInfo.turnUnits)
return CPTravelEstimates(distanceRemaining: measurement, timeRemaining: 0.0)
}

private func createUpcomingManeuvers() -> [CPManeuver] {
guard let routeInfo = RoutingManager.routingManager.routeInfo else {
return []
Expand Down Expand Up @@ -286,7 +286,7 @@ extension CarPlayRouter {
}
return maneuvers
}

func createTrip(startPoint: MWMRoutePoint, endPoint: MWMRoutePoint, routeInfo: RouteInfo? = nil) -> CPTrip {
let startPlacemark = MKPlacemark(coordinate: CLLocationCoordinate2D(latitude: startPoint.latitude,
longitude: startPoint.longitude))
Expand All @@ -296,10 +296,10 @@ extension CarPlayRouter {
let startItem = MKMapItem(placemark: startPlacemark)
let endItem = MKMapItem(placemark: endPlacemark)
endItem.name = endPoint.title

let routeChoice = CPRouteChoice(summaryVariants: [" "], additionalInformationVariants: [], selectionSummaryVariants: [])
routeChoice.userInfo = routeInfo

let trip = CPTrip(origin: startItem, destination: endItem, routeChoices: [routeChoice])
trip.userInfo = [CPConstants.Trip.start: startPoint, CPConstants.Trip.end: endPoint]
return trip
Expand All @@ -308,10 +308,10 @@ extension CarPlayRouter {

// MARK: - RoutingManagerListener implementation
extension CarPlayRouter: RoutingManagerListener {
func updateCameraInfo(isCameraOnRoute: Bool, speedLimit limit: String?) {
CarPlayService.shared.updateCameraUI(isCameraOnRoute: isCameraOnRoute, speedLimit: limit)
func updateCameraInfo(isCameraOnRoute: Bool, speedLimitMps limit: Double) {
CarPlayService.shared.updateCameraUI(isCameraOnRoute: isCameraOnRoute, speedLimitMps: limit < 0 ? nil : limit)
}

func processRouteBuilderEvent(with code: RouterResultCode, countries: [String]) {
guard let trip = previewTrip else {
return
Expand Down Expand Up @@ -345,24 +345,24 @@ extension CarPlayRouter: RoutingManagerListener {
})
}
}

func didLocationUpdate(_ notifications: [String]) {
guard let trip = previewTrip else { return }

let manager = RoutingManager.routingManager
if manager.isRouteFinished {
listenerContainer.forEach({
$0.routeDidFinish(trip)
})
return
}

guard let routeInfo = manager.routeInfo,
manager.isRoutingActive else { return }
listenerContainer.forEach({
$0.didUpdateRouteInfo(routeInfo, forTrip: trip)
})

let tts = MWMTextToSpeech.tts()!
if manager.isOnRoute && tts.active {
tts.playTurnNotifications(notifications)
Expand Down
Loading

0 comments on commit 0e0aed4

Please sign in to comment.