Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
c717196
Fix Attach to roads flows after Plan Route refactor
aleksandr-tata Sep 7, 2026
7b33713
Fix Attach to roads during active navigation
aleksandr-tata Sep 7, 2026
3b5cd01
Preserve source track identity in Attach to roads flow
aleksandr-tata Sep 8, 2026
610fefd
Preserve source GPX path during active Follow Track
aleksandr-tata Sep 8, 2026
bd48146
Preserve source GPX path when entering Route Planning
aleksandr-tata Sep 9, 2026
7a81ff1
Separate Attach apply from Plan Route navigation
aleksandr-tata Sep 9, 2026
ab662ff
Handle Attach apply failures without closing Plan Route
aleksandr-tata Sep 9, 2026
2e7fb0d
Fix generic Plan Route navigation for unchanged tracks
aleksandr-tata Sep 9, 2026
505a322
Fix adding POIs to pathless Attach tracks
aleksandr-tata Sep 9, 2026
4cafd0c
Preserve source folder for pathless Attach tracks
aleksandr-tata Sep 9, 2026
3c396bf
Remove obsolete route planning controller
aleksandr-tata Sep 9, 2026
faabbc2
Remove duplicate reorder segment command
aleksandr-tata Sep 9, 2026
b2fefbe
Fix single-point Plan Route navigation
aleksandr-tata Sep 9, 2026
ae2ddbf
Restore approximation before Plan Route navigation
aleksandr-tata Sep 9, 2026
b1d76da
Restore default profile fallback in Plan Route navigation
aleksandr-tata Sep 10, 2026
90fcb4a
Fix navigation from empty Plan Route
aleksandr-tata Sep 10, 2026
25affcb
Fix Follow Track Plan Route presentation race
aleksandr-tata Sep 10, 2026
dc34c40
Fix Edit Track and Attach intent handling
aleksandr-tata Sep 10, 2026
c22709f
Move approximation callback dispatch to data provider
aleksandr-tata Sep 10, 2026
4a5530d
Deduplicate GPX test directory path
aleksandr-tata Sep 10, 2026
9f1fb73
Fix navigation between unrouted Plan Route points
aleksandr-tata Sep 10, 2026
0fd23e5
Fix Follow Track mode in Plan Route
aleksandr-tata Sep 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
312 changes: 312 additions & 0 deletions OsmAnd MapsTests/PlanRoute/OAPlanRouteEditingBridgeTest.mm

Large diffs are not rendered by default.

71 changes: 71 additions & 0 deletions OsmAnd MapsTests/PlanRoute/PlanRouteTrackSourceTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import XCTest

final class PlanRoutePresentationContextTests: XCTestCase {

func testFollowTrackEditPreservesFollowModeWithoutAttachBehavior() {
let context = PlanRoutePresentationContext.followTrack(attachToRoads: false)

XCTAssertTrue(context.followTrackMode)
XCTAssertFalse(context.showSnapWarning)
XCTAssertFalse(context.appliesApproximationToNavigation)
}

func testFollowTrackAttachEnablesWarningAndNavigationApply() {
let context = PlanRoutePresentationContext.followTrack(attachToRoads: true)

XCTAssertTrue(context.followTrackMode)
XCTAssertTrue(context.showSnapWarning)
XCTAssertTrue(context.appliesApproximationToNavigation)
}
}

final class PlanRouteTrackSourceTests: XCTestCase {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

private let gpxDirectory = "/Documents/GPX"

private let gpxDirectory = "/Documents/GPX"

func testPathlessGpxKeepsSourceFilePathSeparateFromEditableFilePath() {
let sourceFilePath = "\(gpxDirectory)/twisty-route.gpx"
let source = PlanRouteTrackSource(gpxFilePath: "", sourceFilePath: sourceFilePath)

XCTAssertNil(source.editableFilePath)
XCTAssertEqual(source.sourceFilePath, sourceFilePath)
}

func testPathlessGpxUsesSourceFilePathForWaypointEditing() {
let sourceFilePath = "\(gpxDirectory)/twisty-route.gpx"
let source = PlanRouteTrackSource(gpxFilePath: "", sourceFilePath: sourceFilePath)

XCTAssertEqual(source.waypointEditingFilePath, sourceFilePath)
}

func testPathlessGpxUsesSourceFolderForSaving() {
let sourceFilePath = "\(gpxDirectory)/import/twisty-route.gpx"
let source = PlanRouteTrackSource(gpxFilePath: "", sourceFilePath: sourceFilePath)

XCTAssertEqual(source.savingFolder(relativeTo: gpxDirectory), "import")
}

func testGpxInRootFolderHasNoSavingSubfolder() {
let sourceFilePath = "\(gpxDirectory)/twisty-route.gpx"
let source = PlanRouteTrackSource(gpxFilePath: sourceFilePath, sourceFilePath: nil)

XCTAssertNil(source.savingFolder(relativeTo: gpxDirectory))
}

func testGpxFilePathIsUsedWhenExplicitSourceFilePathIsMissing() {
let sourceFilePath = "\(gpxDirectory)/twisty-route.gpx"
let source = PlanRouteTrackSource(gpxFilePath: sourceFilePath, sourceFilePath: nil)

XCTAssertEqual(source.editableFilePath, sourceFilePath)
XCTAssertEqual(source.sourceFilePath, sourceFilePath)
}

func testPathlessGpxWithoutSourceFilePathKeepsBothPathsEmpty() {
let source = PlanRouteTrackSource(gpxFilePath: "", sourceFilePath: nil)

XCTAssertNil(source.editableFilePath)
XCTAssertNil(source.sourceFilePath)
XCTAssertNil(source.waypointEditingFilePath)
XCTAssertNil(source.savingFolder(relativeTo: gpxDirectory))
}
}
22 changes: 22 additions & 0 deletions OsmAnd.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1751,6 +1751,10 @@
D1A0B0122F50001100A0B001 /* StringExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3216E9522BA097BD0087D0EF /* StringExtensions.swift */; };
D1C571200000000000000001 /* ContextMenuPresentationCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1C571200000000000000003 /* ContextMenuPresentationCoordinator.swift */; };
D1C571200000000000000002 /* ContextMenuPresentationCoordinatorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1C571200000000000000005 /* ContextMenuPresentationCoordinatorTest.swift */; };
D1C573500000000000000001 /* OAPlanRouteEditingBridgeTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = D1C573500000000000000002 /* OAPlanRouteEditingBridgeTest.mm */; };
D1C573510000000000000001 /* PlanRouteTrackSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1C573510000000000000003 /* PlanRouteTrackSource.swift */; };
D1C573510000000000000002 /* PlanRouteTrackSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1C573510000000000000003 /* PlanRouteTrackSource.swift */; };
D1C573510000000000000004 /* PlanRouteTrackSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1C573510000000000000005 /* PlanRouteTrackSourceTests.swift */; };
D1C571200000000000000007 /* ContextMenuPresentationCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1C571200000000000000003 /* ContextMenuPresentationCoordinator.swift */; };
D1C571210000000000000001 /* ContextMenuPresentationUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1C571210000000000000002 /* ContextMenuPresentationUITests.swift */; };
D71B9A8C2FC95D8500FBB0F3 /* OrganizeTracksByViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D71B9A8B2FC95D8500FBB0F3 /* OrganizeTracksByViewController.swift */; };
Expand Down Expand Up @@ -5930,6 +5934,9 @@
D1A0B0102F50001100A0B001 /* URLExtractionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLExtractionTests.swift; sourceTree = "<group>"; };
D1C571200000000000000003 /* ContextMenuPresentationCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextMenuPresentationCoordinator.swift; sourceTree = "<group>"; };
D1C571200000000000000005 /* ContextMenuPresentationCoordinatorTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextMenuPresentationCoordinatorTest.swift; sourceTree = "<group>"; };
D1C573500000000000000002 /* OAPlanRouteEditingBridgeTest.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = OAPlanRouteEditingBridgeTest.mm; sourceTree = "<group>"; };
D1C573510000000000000003 /* PlanRouteTrackSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlanRouteTrackSource.swift; sourceTree = "<group>"; };
D1C573510000000000000005 /* PlanRouteTrackSourceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlanRouteTrackSourceTests.swift; sourceTree = "<group>"; };
D1C571210000000000000002 /* ContextMenuPresentationUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextMenuPresentationUITests.swift; sourceTree = "<group>"; };
D1C571210000000000000003 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
D1C571210000000000000004 /* OsmAnd MapsUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "OsmAnd MapsUITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -11193,6 +11200,15 @@
path = Panels;
sourceTree = "<group>";
};
D1C573500000000000000003 /* PlanRoute */ = {
isa = PBXGroup;
children = (
D1C573500000000000000002 /* OAPlanRouteEditingBridgeTest.mm */,
D1C573510000000000000005 /* PlanRouteTrackSourceTests.swift */,
);
path = PlanRoute;
sourceTree = "<group>";
};
D1C571210000000000000005 /* OsmAnd MapsUITests */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -11248,6 +11264,7 @@
D7210159301B768C003CECB8 /* PlanRouteEditingContextDataProvider.swift */,
D721015A301B768C003CECB8 /* PlanRouteEditingModels.swift */,
D721015B301B768C003CECB8 /* PlanRouteModels.swift */,
D1C573510000000000000003 /* PlanRouteTrackSource.swift */,
D721015C301B768C003CECB8 /* PlanRoutePointMenuViewController.swift */,
D721015D301B768C003CECB8 /* PlanRoutePoiState.swift */,
D721015E301B768C003CECB8 /* PlanRouteScrollableViewController.swift */,
Expand Down Expand Up @@ -14782,6 +14799,7 @@
FAB624402E0953870048965E /* OsmAnd MapsTests-Bridging-Header.h */,
FAB6243D2E0953580048965E /* Managers */,
D1C571200000000000000006 /* Panels */,
D1C573500000000000000003 /* PlanRoute */,
DA80DAA8251E0C0C008E6267 /* Router */,
8A1CF862250D145C003D3829 /* test-resources */,
DA72AB932508F44900851313 /* Search */,
Expand Down Expand Up @@ -18278,6 +18296,7 @@
D7210182301B768C003CECB8 /* PlanRouteEditingContextDataProvider.swift in Sources */,
D7210183301B768C003CECB8 /* PlanRouteEditingModels.swift in Sources */,
D7210184301B768C003CECB8 /* PlanRouteModels.swift in Sources */,
D1C573510000000000000001 /* PlanRouteTrackSource.swift in Sources */,
D7210185301B768C003CECB8 /* PlanRoutePointMenuViewController.swift in Sources */,
D7210186301B768C003CECB8 /* PlanRoutePoiState.swift in Sources */,
D7210187301B768C003CECB8 /* PlanRouteScrollableViewController.swift in Sources */,
Expand Down Expand Up @@ -19620,6 +19639,9 @@
D1A0B0122F50001100A0B001 /* StringExtensions.swift in Sources */,
DA72AB952508F44900851313 /* SearchUICoreTest.mm in Sources */,
D1C571200000000000000007 /* ContextMenuPresentationCoordinator.swift in Sources */,
D1C573500000000000000001 /* OAPlanRouteEditingBridgeTest.mm in Sources */,
D1C573510000000000000002 /* PlanRouteTrackSource.swift in Sources */,
D1C573510000000000000004 /* PlanRouteTrackSourceTests.swift in Sources */,
D1C571200000000000000002 /* ContextMenuPresentationCoordinatorTest.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,14 +259,20 @@ - (void) openPlanRoute
[self openPlanRoute:NO];
}

- (void) openPlanRoute:(BOOL)showSnapWarning
- (void) openPlanRoute:(BOOL)attachToRoads
{
if (_gpx)
{
NSString *filePath = _gpx.path;
OASGpxFile *gpx = _gpx;
NSString *fileName = gpx.path.lastPathComponent.stringByDeletingPathExtension;
[self dismissViewControllerAnimated:NO completion:^{
[[OARootViewController instance].mapPanel closeRouteInfo];
[PlanRouteScrollableViewController openExistingTrackWithFilePath:filePath];
OAMapPanelViewController *mapPanel = [OARootViewController instance].mapPanel;
[mapPanel closeRouteInfo:YES onComplete:^{
[PlanRouteScrollableViewController openExistingTrackWithGpxFile:gpx
fileName:fileName ?: @""
sourceFilePath:gpx.path
attachToRoads:attachToRoads];
}];
}];
}
}
Expand Down
23 changes: 22 additions & 1 deletion Sources/Controllers/PlanRoute/OAPlanRouteEditingBridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,22 @@ typedef NS_ENUM(NSInteger, EOAPlanRoutePointEditMode) {
EOAPlanRoutePointEditModeAddAfter
};

typedef NS_ENUM(NSInteger, EOAPlanRouteNavigationResult) {
EOAPlanRouteNavigationResultSuccess = 0,
EOAPlanRouteNavigationResultInvalidContext,
EOAPlanRouteNavigationResultNoPoints,
EOAPlanRouteNavigationResultMissingApproximationResult,
EOAPlanRouteNavigationResultExportFailed,
EOAPlanRouteNavigationResultTransitionFailed
};

@interface OAPlanRouteEditingBridge : NSObject

@property (nonatomic, copy, nullable) void (^onChange)(void);
@property (nonatomic, copy, nullable) void (^onRouteInfoChanged)(void);
@property (nonatomic, copy, nullable) void (^onNewSegmentStarted)(void);
@property (nonatomic, copy, nullable) void (^onPointEditModeRequested)(EOAPlanRoutePointEditMode mode);
@property (nonatomic, copy, nullable) void (^onApproximationApplied)(void);
@property (nonatomic, copy, nullable) void (^onApproximationPopupDismissed)(void);
@property (nonatomic, copy, nullable, getter=changeRouteTypeBeforeHandler) void (^onChangeRouteTypeBefore)(NSInteger pointIndex);
@property (nonatomic, copy, nullable, getter=changeRouteTypeAfterHandler) void (^onChangeRouteTypeAfter)(NSInteger pointIndex);
Expand All @@ -53,6 +63,7 @@ typedef NS_ENUM(NSInteger, EOAPlanRoutePointEditMode) {
@property (nonatomic, readonly, nullable) OAApplicationMode *defaultAppMode;
@property (nonatomic, readonly) BOOL isTrackReadyToCalculate;
@property (nonatomic, readonly) BOOL isApproximationNeeded;
@property (nonatomic, readonly) BOOL shouldRequestApproximationBeforeNavigation;
@property (nonatomic, readonly) BOOL shouldShowApproximationWarning;
@property (nonatomic, readonly, nullable) UIViewController *approximationWarningViewController;
@property (nonatomic, readonly) BOOL hasChanges;
Expand All @@ -79,7 +90,11 @@ typedef NS_ENUM(NSInteger, EOAPlanRoutePointEditMode) {
- (void)prepareNewRoute;
- (void)prepareNewRouteWithApplicationMode:(OAApplicationMode *)applicationMode;
- (void)addPointAtCoordinate:(CLLocationCoordinate2D)coordinate;
- (void)openTrackWithGpxFile:(OASGpxFile *)gpxFile
applicationMode:(nullable OAApplicationMode *)applicationMode
selectedSegment:(NSInteger)selectedSegment;
- (void)openTrackWithFilePath:(NSString *)filePath;
- (void)fitTrackOnMapWithBottomInset:(CGFloat)bottomInset leftInset:(CGFloat)leftInset;
- (void)addCenterPoint;
- (void)setCrosshairScreenPoint:(CGPoint)point;
+ (void)moveMapToCoordinate:(CLLocationCoordinate2D)coordinate;
Expand Down Expand Up @@ -137,7 +152,13 @@ typedef NS_ENUM(NSInteger, EOAPlanRoutePointEditMode) {
- (void)appendToTrack:(NSString *)filePath
onComplete:(void (^)(BOOL success))onComplete;

- (void)enterNavigationWithTrackName:(NSString *)trackName;
- (EOAPlanRouteNavigationResult)enterNavigationWithTrackName:(NSString *)trackName
followTrackMode:(BOOL)followTrackMode
sourceFilePath:(nullable NSString *)sourceFilePath;

- (EOAPlanRouteNavigationResult)applyAttachedTrackToNavigationWithTrackName:(NSString *)trackName
sourceFilePath:(nullable NSString *)sourceFilePath
beforeTransition:(void (NS_NOESCAPE ^)(void))beforeTransition;

@end

Expand Down
Loading