Repo created

This commit is contained in:
Fr4nz D13trich 2025-11-22 13:58:55 +01:00
parent 4af19165ec
commit 68073add76
12458 changed files with 12350765 additions and 2 deletions

View file

@ -0,0 +1,20 @@
#import "MWMFrameworkObserver.h"
NS_ASSUME_NONNULL_BEGIN
@interface MWMFrameworkListener : NSObject
+ (MWMFrameworkListener *)listener;
+ (void)addObserver:(id<MWMFrameworkObserver>)observer;
+ (void)removeObserver:(id<MWMFrameworkObserver>)observer;
- (instancetype)init __attribute__((unavailable("call +listener instead")));
- (instancetype)copy __attribute__((unavailable("call +listener instead")));
- (instancetype)copyWithZone:(NSZone *)zone __attribute__((unavailable("call +listener instead")));
+ (instancetype)allocWithZone:(struct _NSZone *)zone
__attribute__((unavailable("call +listener instead")));
+ (instancetype) new __attribute__((unavailable("call +listener instead")));
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,156 @@
#import "MWMFrameworkListener.h"
#import "MWMFrameworkObservers.h"
#include <CoreApi/Framework.h>
#include "platform/downloader_defines.hpp"
namespace
{
using Observer = id<MWMFrameworkObserver>;
using TRouteBuildingObserver = id<MWMFrameworkRouteBuilderObserver>;
using TDrapeObserver = id<MWMFrameworkDrapeObserver>;
using Observers = NSHashTable<Observer>;
Protocol * pRouteBuildingObserver = @protocol(MWMFrameworkRouteBuilderObserver);
Protocol * pDrapeObserver = @protocol(MWMFrameworkDrapeObserver);
using TLoopBlock = void (^)(__kindof Observer observer);
void loopWrappers(Observers * observers, TLoopBlock block)
{
dispatch_async(dispatch_get_main_queue(), ^{
for (Observer observer in observers)
{
if (observer)
block(observer);
}
});
}
} // namespace
@interface MWMFrameworkListener ()
@property(nonatomic) Observers * routeBuildingObservers;
@property(nonatomic) Observers * drapeObservers;
@end
@implementation MWMFrameworkListener
+ (MWMFrameworkListener *)listener
{
static MWMFrameworkListener * listener;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
listener = [[super alloc] initListener];
});
return listener;
}
+ (void)addObserver:(Observer)observer
{
dispatch_async(dispatch_get_main_queue(), ^{
MWMFrameworkListener * listener = [MWMFrameworkListener listener];
if ([observer conformsToProtocol:pRouteBuildingObserver])
[listener.routeBuildingObservers addObject:observer];
if ([observer conformsToProtocol:pDrapeObserver])
[listener.drapeObservers addObject:observer];
});
}
+ (void)removeObserver:(Observer)observer
{
dispatch_async(dispatch_get_main_queue(), ^{
MWMFrameworkListener * listener = [MWMFrameworkListener listener];
[listener.routeBuildingObservers removeObject:observer];
[listener.drapeObservers removeObject:observer];
});
}
- (instancetype)initListener
{
self = [super init];
if (self)
{
_routeBuildingObservers = [Observers weakObjectsHashTable];
_drapeObservers = [Observers weakObjectsHashTable];
[self registerRouteBuilderListener];
[self registerDrapeObserver];
}
return self;
}
#pragma mark - MWMFrameworkRouteBuilderObserver
- (void)registerRouteBuilderListener
{
using namespace routing;
using namespace storage;
Observers * observers = self.routeBuildingObservers;
auto & rm = GetFramework().GetRoutingManager();
rm.SetRouteBuildingListener(
[observers](RouterResultCode code, CountriesSet const & absentCountries) {
loopWrappers(observers, [code, absentCountries](TRouteBuildingObserver observer) {
[observer processRouteBuilderEvent:code countries:absentCountries];
});
});
rm.SetRouteProgressListener([observers](float progress) {
loopWrappers(observers, [progress](TRouteBuildingObserver observer) {
if ([observer respondsToSelector:@selector(processRouteBuilderProgress:)])
[observer processRouteBuilderProgress:progress];
});
});
rm.SetRouteRecommendationListener([observers](RoutingManager::Recommendation recommendation) {
MWMRouterRecommendation rec;
switch (recommendation)
{
case RoutingManager::Recommendation::RebuildAfterPointsLoading:
rec = MWMRouterRecommendationRebuildAfterPointsLoading;
break;
}
loopWrappers(observers, [rec](TRouteBuildingObserver observer) {
if ([observer respondsToSelector:@selector(processRouteRecommendation:)])
[observer processRouteRecommendation:rec];
});
});
rm.SetRouteSpeedCamShowListener([observers](m2::PointD const & point, double cameraSpeedKmPH) {
loopWrappers(observers, [cameraSpeedKmPH](TRouteBuildingObserver observer) {
if ([observer respondsToSelector:@selector(speedCameraShowedUpOnRoute:)])
[observer speedCameraShowedUpOnRoute:cameraSpeedKmPH];
});
});
rm.SetRouteSpeedCamsClearListener([observers]() {
loopWrappers(observers, ^(TRouteBuildingObserver observer) {
if ([observer respondsToSelector:@selector(speedCameraLeftVisibleArea)])
[observer speedCameraLeftVisibleArea];
});
});
}
#pragma mark - MWMFrameworkDrapeObserver
- (void)registerDrapeObserver
{
Observers * observers = self.drapeObservers;
auto & f = GetFramework();
f.SetCurrentCountryChangedListener([observers](CountryId const & countryId) {
for (TDrapeObserver observer in observers)
{
if ([observer respondsToSelector:@selector(processViewportCountryEvent:)])
[observer processViewportCountryEvent:countryId];
}
});
f.SetViewportListener([observers](ScreenBase const & screen) {
for (TDrapeObserver observer in observers)
{
if ([observer respondsToSelector:@selector(processViewportChangedEvent)])
[observer processViewportChangedEvent];
}
});
}
@end

View file

@ -0,0 +1,3 @@
@protocol MWMFrameworkObserver<NSObject>
@end

View file

@ -0,0 +1,35 @@
#import "MWMFrameworkObserver.h"
#import "MWMRouterRecommendation.h"
#include "routing/router.hpp"
#include "routing/routing_callbacks.hpp"
#include "storage/storage.hpp"
#include "storage/storage_defines.hpp"
#include "platform/downloader_defines.hpp"
using namespace storage;
@protocol MWMFrameworkRouteBuilderObserver<MWMFrameworkObserver>
- (void)processRouteBuilderEvent:(routing::RouterResultCode)code
countries:(storage::CountriesSet const &)absentCountries;
@optional
- (void)processRouteBuilderProgress:(CGFloat)progress;
- (void)processRouteRecommendation:(MWMRouterRecommendation)recommendation;
- (void)speedCameraShowedUpOnRoute:(double)speedLimitKMph;
- (void)speedCameraLeftVisibleArea;
@end
@protocol MWMFrameworkDrapeObserver<MWMFrameworkObserver>
@optional
- (void)processViewportCountryEvent:(storage::CountryId const &)countryId;
- (void)processViewportChangedEvent;
@end

View file

@ -0,0 +1,10 @@
#import "MWMMyPositionMode.h"
NS_ASSUME_NONNULL_BEGIN
NS_SWIFT_NAME(LocationModeListener)
@protocol MWMLocationModeListener <NSObject>
- (void)processMyPositionStateModeEvent:(MWMMyPositionMode)mode;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,19 @@
typedef NS_CLOSED_ENUM(NSUInteger, MWMRouterResultCode) {
MWMRouterResultCodeNoError = 0,
MWMRouterResultCodeCancelled = 1,
MWMRouterResultCodeNoCurrentPosition = 2,
MWMRouterResultCodeInconsistentMWMandRoute = 3,
MWMRouterResultCodeRouteFileNotExist = 4,
MWMRouterResultCodeStartPointNotFound = 5,
MWMRouterResultCodeEndPointNotFound = 6,
MWMRouterResultCodePointsInDifferentMWM = 7,
MWMRouterResultCodeRouteNotFound = 8,
MWMRouterResultCodeNeedMoreMaps = 9,
MWMRouterResultCodeInternalError = 10,
MWMRouterResultCodeFileTooOld = 11,
MWMRouterResultCodeIntermediatePointNotFound = 12,
MWMRouterResultCodeTransitRouteNotFoundNoNetwork = 13,
MWMRouterResultCodeTransitRouteNotFoundTooLongPedestrian = 14,
MWMRouterResultCodeRouteNotFoundRedressRouteError = 15,
MWMRouterResultCodeHasWarnings = 16
} NS_SWIFT_NAME(RouterResultCode);

View file

@ -0,0 +1,49 @@
#import "MWMRouterType.h"
#import "MWMRoutePoint.h"
#import "MWMRouterResultCode.h"
#import "MWMSpeedCameraManagerMode.h"
@class RouteInfo;
NS_ASSUME_NONNULL_BEGIN
NS_SWIFT_NAME(RoutingManagerListener)
@protocol MWMRoutingManagerListener <NSObject>
- (void)processRouteBuilderEventWithCode:(MWMRouterResultCode)code
countries:(NSArray<NSString *> *)absentCountries;
- (void)didLocationUpdate:(NSArray<NSString *> *)notifications;
- (void)updateCameraInfo:(BOOL)isCameraOnRoute speedLimitMps:(double)limit NS_SWIFT_NAME(updateCameraInfo(isCameraOnRoute:speedLimitMps:));
@end
NS_SWIFT_NAME(RoutingManager)
@interface MWMRoutingManager : NSObject
@property(class, nonatomic, readonly) MWMRoutingManager *routingManager;
@property(nonatomic, readonly, nullable) MWMRoutePoint *startPoint;
@property(nonatomic, readonly, nullable) MWMRoutePoint *endPoint;
@property(nonatomic, readonly) BOOL isOnRoute;
@property(nonatomic, readonly) BOOL isRoutingActive;
@property(nonatomic, readonly) BOOL isRouteFinished;
@property(nonatomic, readonly, nullable) RouteInfo *routeInfo;
@property(nonatomic, readonly) MWMRouterType type;
@property(nonatomic) MWMSpeedCameraManagerMode speedCameraMode;
- (void)addListener:(id<MWMRoutingManagerListener>)listener;
- (void)removeListener:(id<MWMRoutingManagerListener>)listener;
- (void)stopRoutingAndRemoveRoutePoints:(BOOL)flag;
- (void)deleteSavedRoutePoints;
- (void)applyRouterType:(MWMRouterType)type NS_SWIFT_NAME(apply(routeType:));
- (void)addRoutePoint:(MWMRoutePoint *)point NS_SWIFT_NAME(add(routePoint:));
- (void)buildRouteWithDidFailError:(NSError **)errorPtr __attribute__((swift_error(nonnull_error))) NS_SWIFT_NAME(buildRoute());
- (void)startRoute;
- (void)setOnNewTurnCallback:(MWMVoidBlock)callback;
- (void)resetOnNewTurnCallback;
- (instancetype)init __attribute__((unavailable("call +routingManager instead")));
- (instancetype)copy __attribute__((unavailable("call +routingManager instead")));
- (instancetype)copyWithZone:(NSZone *)zone __attribute__((unavailable("call +routingManager instead")));
+ (instancetype)allocWithZone:(struct _NSZone *)zone
__attribute__((unavailable("call +routingManager instead")));
+ (instancetype) new __attribute__((unavailable("call +routingManager instead")));
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,293 @@
#import "MWMRoutingManager.h"
#import "MWMLocationManager.h"
#import "MWMLocationObserver.h"
#import "MWMFrameworkListener.h"
#import "MWMFrameworkObservers.h"
#import "MWMCoreRouterType.h"
#import "MWMRoutePoint+CPP.h"
#import "MWMCoreUnits.h"
#import "SwiftBridge.h"
#include <CoreApi/Framework.h>
@interface MWMRoutingManager()<MWMFrameworkRouteBuilderObserver, MWMLocationObserver>
@property(nonatomic, readonly) RoutingManager & rm;
@property(strong, nonatomic) NSHashTable<id<MWMRoutingManagerListener>> *listeners;
@end
@implementation MWMRoutingManager
+ (MWMRoutingManager *)routingManager {
static MWMRoutingManager * routingManager;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
routingManager = [[self alloc] initManager];
});
return routingManager;
}
- (instancetype)initManager {
self = [super init];
if (self) {
self.listeners = [NSHashTable<id<MWMRoutingManagerListener>> weakObjectsHashTable];
[MWMFrameworkListener addObserver:self];
[MWMLocationManager addObserver:self];
}
return self;
}
- (RoutingManager &)rm {
return GetFramework().GetRoutingManager();
}
- (routing::SpeedCameraManager &)scm {
return self.rm.GetSpeedCamManager();
}
- (MWMRoutePoint *)startPoint {
auto const routePoints = self.rm.GetRoutePoints();
if (routePoints.empty())
return nil;
auto const & routePoint = routePoints.front();
if (routePoint.m_pointType == RouteMarkType::Start)
return [[MWMRoutePoint alloc] initWithRouteMarkData:routePoint];
return nil;
}
- (MWMRoutePoint *)endPoint {
auto const routePoints = self.rm.GetRoutePoints();
if (routePoints.empty())
return nil;
auto const & routePoint = routePoints.back();
if (routePoint.m_pointType == RouteMarkType::Finish)
return [[MWMRoutePoint alloc] initWithRouteMarkData:routePoint];
return nil;
}
- (BOOL)isOnRoute {
return self.rm.IsRoutingFollowing();
}
- (BOOL)isRoutingActive {
return self.rm.IsRoutingActive();
}
- (BOOL)isRouteFinished {
return self.rm.IsRouteFinished();
}
- (MWMRouteInfo *)routeInfo {
if (!self.isRoutingActive)
return nil;
routing::FollowingInfo info;
self.rm.GetRouteFollowingInfo(info);
if (!info.IsValid())
return nil;
CLLocation * lastLocation = [MWMLocationManager lastLocation];
double speedMps = 0;
if (lastLocation && lastLocation.speed >= 0)
speedMps = lastLocation.speed;
NSInteger roundExitNumber = 0;
if (info.m_turn == routing::turns::CarDirection::EnterRoundAbout ||
info.m_turn == routing::turns::CarDirection::StayOnRoundAbout ||
info.m_turn == routing::turns::CarDirection::LeaveRoundAbout) {
roundExitNumber = info.m_exitNum;
}
MWMRouteInfo *objCInfo = [[MWMRouteInfo alloc] initWithTimeToTarget:info.m_time
targetDistance: info.m_distToTarget.GetDistance()
targetUnitsIndex:static_cast<UInt8>(info.m_distToTarget.GetUnits())
distanceToTurn:info.m_distToTurn.GetDistance()
turnUnitsIndex:static_cast<UInt8>(info.m_distToTurn.GetUnits())
streetName:@(info.m_nextStreetName.c_str())
turnImageName:[self turnImageName:info.m_turn isPrimary:YES]
nextTurnImageName:[self turnImageName:info.m_nextTurn isPrimary:NO]
speedMps:speedMps
speedLimitMps:info.m_speedLimitMps
roundExitNumber:roundExitNumber];
return objCInfo;
}
- (MWMRouterType)type {
return routerType(self.rm.GetRouter());
}
- (void)addListener:(id<MWMRoutingManagerListener>)listener {
[self.listeners addObject:listener];
}
- (void)removeListener:(id<MWMRoutingManagerListener>)listener {
[self.listeners removeObject:listener];
}
- (void)stopRoutingAndRemoveRoutePoints:(BOOL)flag {
self.rm.CloseRouting(flag);
}
- (void)deleteSavedRoutePoints {
self.rm.DeleteSavedRoutePoints();
}
- (void)applyRouterType:(MWMRouterType)type {
self.rm.SetRouter(coreRouterType(type));
}
- (void)addRoutePoint:(MWMRoutePoint *)point {
RouteMarkData startPt = point.routeMarkData;
self.rm.AddRoutePoint(std::move(startPt));
}
- (void)saveRoute {
self.rm.SaveRoutePoints();
}
- (void)buildRouteWithDidFailError:(NSError * __autoreleasing __nullable *)errorPtr {
auto const & points = self.rm.GetRoutePoints();
auto const pointsCount = points.size();
if (pointsCount > 1) {
self.rm.BuildRoute();
} else {
if (errorPtr) {
if (pointsCount == 0) {
*errorPtr = [NSError errorWithDomain:@"comaps.app.routing"
code:MWMRouterResultCodeStartPointNotFound
userInfo:nil];
} else {
auto const & routePoint = points.front();
MWMRouterResultCode code;
if (routePoint.m_pointType == RouteMarkType::Start) {
code = MWMRouterResultCodeEndPointNotFound;
} else {
code = MWMRouterResultCodeStartPointNotFound;
}
*errorPtr = [NSError errorWithDomain:@"comaps.app.routing"
code:code
userInfo:nil];
}
}
}
}
- (void)startRoute {
[self saveRoute];
self.rm.FollowRoute();
}
- (MWMSpeedCameraManagerMode)speedCameraMode {
auto const mode = self.scm.GetMode();
switch (mode) {
case routing::SpeedCameraManagerMode::Auto:
return MWMSpeedCameraManagerModeAuto;
case routing::SpeedCameraManagerMode::Always:
return MWMSpeedCameraManagerModeAlways;
default:
return MWMSpeedCameraManagerModeNever;
}
}
- (void)setSpeedCameraMode:(MWMSpeedCameraManagerMode)mode {
switch (mode) {
case MWMSpeedCameraManagerModeAuto:
self.scm.SetMode(routing::SpeedCameraManagerMode::Auto);
break;
case MWMSpeedCameraManagerModeAlways:
self.scm.SetMode(routing::SpeedCameraManagerMode::Always);
break;
default:
self.scm.SetMode(routing::SpeedCameraManagerMode::Never);
}
}
- (void)setOnNewTurnCallback:(MWMVoidBlock)callback {
self.rm.RoutingSession().SetOnNewTurnCallback([callback] {
callback();
});
}
- (void)resetOnNewTurnCallback {
self.rm.RoutingSession().SetOnNewTurnCallback(nullptr);
}
#pragma mark - MWMFrameworkRouteBuilderObserver implementation
- (void)processRouteBuilderEvent:(routing::RouterResultCode)code
countries:(const storage::CountriesSet &)absentCountries {
NSArray<id<MWMRoutingManagerListener>> * objects = self.listeners.allObjects;
MWMRouterResultCode objCCode = MWMRouterResultCode(code);
NSMutableArray<NSString *> *objCAbsentCountries = [NSMutableArray new];
std::for_each(absentCountries.begin(), absentCountries.end(), ^(std::string const & str) {
id nsstr = [NSString stringWithUTF8String:str.c_str()];
[objCAbsentCountries addObject:nsstr];
});
for (id<MWMRoutingManagerListener> object in objects) {
[object processRouteBuilderEventWithCode:objCCode
countries:objCAbsentCountries];
}
}
- (void)speedCameraShowedUpOnRoute:(double)speedLimit {
NSArray<id<MWMRoutingManagerListener>> * objects = self.listeners.allObjects;
for (id<MWMRoutingManagerListener> object in objects) {
if (speedLimit == routing::SpeedCameraOnRoute::kNoSpeedInfo) {
[object updateCameraInfo:YES speedLimitMps:-1];
} else {
auto const metersPerSecond = measurement_utils::KmphToMps(speedLimit);
[object updateCameraInfo:YES speedLimitMps:metersPerSecond];
}
}
}
- (void)speedCameraLeftVisibleArea {
NSArray<id<MWMRoutingManagerListener>> * objects = self.listeners.allObjects;
for (id<MWMRoutingManagerListener> object in objects) {
[object updateCameraInfo:NO speedLimitMps:-1];
}
}
#pragma mark - MWMLocationObserver implementation
- (void)onLocationUpdate:(CLLocation *)location {
NSMutableArray<NSString *> * turnNotifications = [NSMutableArray array];
std::vector<std::string> notifications;
auto announceStreets = [NSUserDefaults.standardUserDefaults boolForKey:@"UserDefaultsNeedToEnableStreetNamesTTS"];
self.rm.GenerateNotifications(notifications, announceStreets);
for (auto const & text : notifications) {
[turnNotifications addObject:@(text.c_str())];
}
NSArray<id<MWMRoutingManagerListener>> * objects = self.listeners.allObjects;
for (id<MWMRoutingManagerListener> object in objects) {
[object didLocationUpdate:turnNotifications];
}
}
- (NSString *)turnImageName:(routing::turns::CarDirection)turn isPrimary:(BOOL)isPrimary {
using namespace routing::turns;
NSString *imageName = nil;
switch (turn) {
case CarDirection::ExitHighwayToRight: imageName = @"ic_cp_exit_highway_to_right"; break;
case CarDirection::TurnSlightRight: imageName = @"ic_cp_slight_right"; break;
case CarDirection::TurnRight: imageName = @"ic_cp_simple_right"; break;
case CarDirection::TurnSharpRight: imageName = @"ic_cp_sharp_right"; break;
case CarDirection::ExitHighwayToLeft: imageName = @"ic_cp_exit_highway_to_left"; break;
case CarDirection::TurnSlightLeft: imageName = @"ic_cp_slight_left"; break;
case CarDirection::TurnLeft: imageName = @"ic_cp_simple_left"; break;
case CarDirection::TurnSharpLeft: imageName = @"ic_cp_sharp_left"; break;
case CarDirection::UTurnLeft: imageName = @"ic_cp_uturn_left"; break;
case CarDirection::UTurnRight: imageName = @"ic_cp_uturn_right"; break;
case CarDirection::ReachedYourDestination: imageName = @"ic_cp_finish_point"; break;
case CarDirection::LeaveRoundAbout:
case CarDirection::EnterRoundAbout: imageName = @"ic_cp_round"; break;
case CarDirection::GoStraight: imageName = @"ic_cp_straight"; break;
case CarDirection::StartAtEndOfStreet:
case CarDirection::StayOnRoundAbout:
case CarDirection::Count:
case CarDirection::None: imageName = isPrimary ? @"ic_cp_straight" : nil; break;
}
if (!isPrimary && imageName != nil) {
imageName = [NSString stringWithFormat:@"%@_then", imageName];
}
return imageName;
}
@end

View file

@ -0,0 +1,5 @@
typedef NS_ENUM(NSUInteger, MWMSpeedCameraManagerMode) {
MWMSpeedCameraManagerModeAuto,
MWMSpeedCameraManagerModeAlways,
MWMSpeedCameraManagerModeNever
} NS_SWIFT_NAME(SpeedCameraManagerMode);