diff --git a/iphone/Maps/Classes/CarPlay/Template Builders/SettingsTemplateBuilder.swift b/iphone/Maps/Classes/CarPlay/Template Builders/SettingsTemplateBuilder.swift
index 6b6f73589..d53c10a9e 100644
--- a/iphone/Maps/Classes/CarPlay/Template Builders/SettingsTemplateBuilder.swift
+++ b/iphone/Maps/Classes/CarPlay/Template Builders/SettingsTemplateBuilder.swift
@@ -15,6 +15,7 @@ final class SettingsTemplateBuilder {
return [createUnpavedButton(options: options),
createTollButton(options: options),
createFerryButton(options: options),
+ createPavedButton(options: options),
createStepsButton(options: options),
createSpeedcamButton()]
}
@@ -40,7 +41,7 @@ final class SettingsTemplateBuilder {
private class func createUnpavedButton(options: RoutingOptions) -> CPGridButton {
var unpavedIconName = "options.unpaved"
- if options.avoidDirty { unpavedIconName += ".slash" }
+ if options.avoidDirty && !options.avoidPaved { unpavedIconName += ".slash" }
let configuration = UIImage.SymbolConfiguration(textStyle: .title1)
var image = UIImage(named: unpavedIconName, in: nil, with: configuration)!
if #unavailable(iOS 26) {
@@ -49,12 +50,38 @@ final class SettingsTemplateBuilder {
}
let unpavedButton = CPGridButton(titleVariants: [L("avoid_unpaved")], image: image) { _ in
options.avoidDirty = !options.avoidDirty
+ if options.avoidDirty {
+ options.avoidPaved = false
+ }
options.save()
CarPlayService.shared.updateRouteAfterChangingSettings()
CarPlayService.shared.popTemplate(animated: true)
}
+ unpavedButton.isEnabled = !options.avoidPaved
return unpavedButton
}
+
+ private class func createPavedButton(options: RoutingOptions) -> CPGridButton {
+ var pavedIconName = "options.paved"
+ if options.avoidPaved && !options.avoidDirty { pavedIconName += ".slash" }
+ let configuration = UIImage.SymbolConfiguration(textStyle: .title1)
+ var image = UIImage(named: pavedIconName, in: nil, with: configuration)!
+ if #unavailable(iOS 26) {
+ image = image.withTintColor(.white, renderingMode: .alwaysTemplate)
+ image = UIImage(data: image.pngData()!)!.withRenderingMode(.alwaysTemplate)
+ }
+ let pavedButton = CPGridButton(titleVariants: [L("avoid_paved")], image: image) { _ in
+ options.avoidPaved = !options.avoidPaved
+ if options.avoidPaved {
+ options.avoidDirty = false
+ }
+ options.save()
+ CarPlayService.shared.updateRouteAfterChangingSettings()
+ CarPlayService.shared.popTemplate(animated: true)
+ }
+ pavedButton.isEnabled = !options.avoidDirty
+ return pavedButton
+ }
private class func createFerryButton(options: RoutingOptions) -> CPGridButton {
var ferryIconName = "options.ferries"
diff --git a/iphone/Maps/Core/Routing/MWMRouter.h b/iphone/Maps/Core/Routing/MWMRouter.h
index 86d8f5798..2901437b6 100644
--- a/iphone/Maps/Core/Routing/MWMRouter.h
+++ b/iphone/Maps/Core/Routing/MWMRouter.h
@@ -6,7 +6,8 @@ typedef NS_ENUM(NSInteger, MWMRoadType) {
MWMRoadTypeDirty,
MWMRoadTypeFerry,
MWMRoadTypeMotorway,
- MWMRoadTypeSteps
+ MWMRoadTypeSteps,
+ MWMRoadTypePaved
};
typedef void (^MWMImageHeightBlock)(UIImage *, NSString *, NSString *);
diff --git a/iphone/Maps/Core/Routing/MWMRouter.mm b/iphone/Maps/Core/Routing/MWMRouter.mm
index 9d2bdaceb..82385be43 100644
--- a/iphone/Maps/Core/Routing/MWMRouter.mm
+++ b/iphone/Maps/Core/Routing/MWMRouter.mm
@@ -592,6 +592,9 @@ char const *kRenderAltitudeImagesQueueLabel = "mapsme.mwmrouter.renderAltitudeIm
case MWMRoadTypeDirty:
options.avoidDirty = YES;
break;
+ case MWMRoadTypePaved:
+ options.avoidPaved = YES;
+ break;
case MWMRoadTypeFerry:
options.avoidFerry = YES;
break;
diff --git a/iphone/Maps/Core/Settings/MWMRoutingOptions.h b/iphone/Maps/Core/Settings/MWMRoutingOptions.h
index b45daf049..6d96e973d 100644
--- a/iphone/Maps/Core/Settings/MWMRoutingOptions.h
+++ b/iphone/Maps/Core/Settings/MWMRoutingOptions.h
@@ -7,6 +7,7 @@ NS_SWIFT_NAME(RoutingOptions)
@property(nonatomic) BOOL avoidToll;
@property(nonatomic) BOOL avoidDirty;
+@property(nonatomic) BOOL avoidPaved;
@property(nonatomic) BOOL avoidFerry;
@property(nonatomic) BOOL avoidMotorway;
@property(nonatomic) BOOL avoidSteps;
diff --git a/iphone/Maps/Core/Settings/MWMRoutingOptions.mm b/iphone/Maps/Core/Settings/MWMRoutingOptions.mm
index c05892a7f..d6b80a8c8 100644
--- a/iphone/Maps/Core/Settings/MWMRoutingOptions.mm
+++ b/iphone/Maps/Core/Settings/MWMRoutingOptions.mm
@@ -35,6 +35,14 @@
[self setOption:(routing::RoutingOptions::Road::Dirty) enabled:avoid];
}
+- (BOOL)avoidPaved {
+ return _options.Has(routing::RoutingOptions::Road::Paved);
+}
+
+- (void)setAvoidPaved:(BOOL)avoid {
+ [self setOption:(routing::RoutingOptions::Road::Paved) enabled:avoid];
+}
+
- (BOOL)avoidFerry {
return _options.Has(routing::RoutingOptions::Road::Ferry);
}
@@ -60,7 +68,7 @@
}
- (BOOL)hasOptions {
- return self.avoidToll || self.avoidDirty || self.avoidFerry || self.avoidMotorway || self.avoidSteps;
+ return self.avoidToll || self.avoidDirty || self.avoidPaved|| self.avoidFerry || self.avoidMotorway || self.avoidSteps;
}
- (void)save {
@@ -80,8 +88,7 @@
return NO;
}
MWMRoutingOptions *another = (MWMRoutingOptions *)object;
- return another.avoidToll == self.avoidToll && another.avoidDirty == self.avoidDirty &&
- another.avoidFerry == self.avoidFerry && another.avoidMotorway == self.avoidMotorway && another.avoidSteps == self.avoidSteps;
+ return another.avoidToll == self.avoidToll && another.avoidDirty == self.avoidDirty && another.avoidPaved == self.avoidPaved && another.avoidFerry == self.avoidFerry && another.avoidMotorway == self.avoidMotorway && another.avoidSteps == self.avoidSteps;
}
@end
diff --git a/iphone/Maps/Images.xcassets/Interface/Symbols/options.paved.slash.symbolset/Contents.json b/iphone/Maps/Images.xcassets/Interface/Symbols/options.paved.slash.symbolset/Contents.json
new file mode 100644
index 000000000..cee240622
--- /dev/null
+++ b/iphone/Maps/Images.xcassets/Interface/Symbols/options.paved.slash.symbolset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ },
+ "symbols" : [
+ {
+ "filename" : "options.paved.slash.svg",
+ "idiom" : "universal"
+ }
+ ]
+}
diff --git a/iphone/Maps/Images.xcassets/Interface/Symbols/options.paved.slash.symbolset/options.paved.slash.svg b/iphone/Maps/Images.xcassets/Interface/Symbols/options.paved.slash.symbolset/options.paved.slash.svg
new file mode 100644
index 000000000..627459117
--- /dev/null
+++ b/iphone/Maps/Images.xcassets/Interface/Symbols/options.paved.slash.symbolset/options.paved.slash.svg
@@ -0,0 +1,122 @@
+
+
+
+
diff --git a/iphone/Maps/Images.xcassets/Interface/Symbols/options.paved.symbolset/Contents.json b/iphone/Maps/Images.xcassets/Interface/Symbols/options.paved.symbolset/Contents.json
new file mode 100644
index 000000000..7f607e64f
--- /dev/null
+++ b/iphone/Maps/Images.xcassets/Interface/Symbols/options.paved.symbolset/Contents.json
@@ -0,0 +1,12 @@
+{
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ },
+ "symbols" : [
+ {
+ "filename" : "options.paved.svg",
+ "idiom" : "universal"
+ }
+ ]
+}
diff --git a/iphone/Maps/Images.xcassets/Interface/Symbols/options.paved.symbolset/options.paved.svg b/iphone/Maps/Images.xcassets/Interface/Symbols/options.paved.symbolset/options.paved.svg
new file mode 100644
index 000000000..175f01cc9
--- /dev/null
+++ b/iphone/Maps/Images.xcassets/Interface/Symbols/options.paved.symbolset/options.paved.svg
@@ -0,0 +1,109 @@
+
+
+
+
diff --git a/iphone/Maps/Images.xcassets/Interface/Symbols/options.unpaved.slash.symbolset/options.unpaved.slash.svg b/iphone/Maps/Images.xcassets/Interface/Symbols/options.unpaved.slash.symbolset/options.unpaved.slash.svg
index 05766c3ca..c9c21e6e1 100644
--- a/iphone/Maps/Images.xcassets/Interface/Symbols/options.unpaved.slash.symbolset/options.unpaved.slash.svg
+++ b/iphone/Maps/Images.xcassets/Interface/Symbols/options.unpaved.slash.symbolset/options.unpaved.slash.svg
@@ -4,23 +4,26 @@
PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
diff --git a/iphone/Maps/Images.xcassets/Interface/Symbols/options.unpaved.symbolset/options.unpaved.svg b/iphone/Maps/Images.xcassets/Interface/Symbols/options.unpaved.symbolset/options.unpaved.svg
index 1bd826730..58db41dfb 100644
--- a/iphone/Maps/Images.xcassets/Interface/Symbols/options.unpaved.symbolset/options.unpaved.svg
+++ b/iphone/Maps/Images.xcassets/Interface/Symbols/options.unpaved.symbolset/options.unpaved.svg
@@ -4,17 +4,19 @@
PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
diff --git a/iphone/Maps/LocalizedStrings/de.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/de.lproj/Localizable.strings
index 04a49aaf4..fcf4a6c5d 100644
--- a/iphone/Maps/LocalizedStrings/de.lproj/Localizable.strings
+++ b/iphone/Maps/LocalizedStrings/de.lproj/Localizable.strings
@@ -823,6 +823,7 @@
/* Recommended length for CarPlay and Android Auto is around 25-27 characters */
"avoid_unpaved" = "Unbefest. Straßen vermeiden";
+"avoid_paved" = "Befst. Straßen vermeiden";
/* Recommended length for CarPlay and Android Auto is around 25-27 characters */
"avoid_steps" = "Treppen vermeiden";
diff --git a/iphone/Maps/LocalizedStrings/en-GB.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/en-GB.lproj/Localizable.strings
index 44efcdb01..0bba18f8f 100644
--- a/iphone/Maps/LocalizedStrings/en-GB.lproj/Localizable.strings
+++ b/iphone/Maps/LocalizedStrings/en-GB.lproj/Localizable.strings
@@ -850,6 +850,7 @@
/* Recommended length for CarPlay and Android Auto is around 25-27 characters */
"avoid_unpaved" = "Avoid unpaved roads";
+"avoid_paved" = "Avoid paved roads";
/* Recommended length for CarPlay and Android Auto is around 25-27 characters */
"avoid_steps" = "Avoid stairs";
diff --git a/iphone/Maps/LocalizedStrings/en.lproj/Localizable.strings b/iphone/Maps/LocalizedStrings/en.lproj/Localizable.strings
index b007593b5..426e9dfef 100644
--- a/iphone/Maps/LocalizedStrings/en.lproj/Localizable.strings
+++ b/iphone/Maps/LocalizedStrings/en.lproj/Localizable.strings
@@ -871,6 +871,7 @@
/* Recommended length for CarPlay and Android Auto is around 25-27 characters */
"avoid_unpaved" = "Avoid unpaved roads";
+"avoid_paved" = "Avoid paved roads";
/* Recommended length for CarPlay and Android Auto is around 25-27 characters */
"avoid_steps" = "Avoid stairs";
diff --git a/iphone/Maps/Model/Settings.swift b/iphone/Maps/Model/Settings.swift
index df3ebdb31..c5de941ac 100644
--- a/iphone/Maps/Model/Settings.swift
+++ b/iphone/Maps/Model/Settings.swift
@@ -388,6 +388,21 @@ import AVFoundation
}
+ /// If paved roads should be avoided during routing
+ @objc static var shouldAvoidPavedRoadsWhileRouting: Bool {
+ get {
+ return RoutingOptions().avoidPaved
+ }
+ set {
+ let routingOptions = RoutingOptions()
+ routingOptions.avoidPaved = newValue
+ routingOptions.save()
+
+ NotificationCenter.default.post(name: routingOptionsChangedNotificationName, object: nil)
+ }
+ }
+
+
/// If ferries should be avoided during routing
@objc static var shouldAvoidFerriesWhileRouting: Bool {
get {
diff --git a/iphone/Maps/UI/Routing/RoutingOptionsView.swift b/iphone/Maps/UI/Routing/RoutingOptionsView.swift
index 8559e8010..2270f3a93 100644
--- a/iphone/Maps/UI/Routing/RoutingOptionsView.swift
+++ b/iphone/Maps/UI/Routing/RoutingOptionsView.swift
@@ -16,6 +16,10 @@ struct RoutingOptionsView: View {
@State var shouldAvoidUnpavedRoadsWhileRouting: Bool = false
+ /// If paved roads should be avoided during routing
+ @State var shouldAvoidPavedRoadsWhileRouting: Bool = false
+
+
/// If ferries should be avoided during routing
@State var shouldAvoidFerriesWhileRouting: Bool = false
@@ -38,6 +42,7 @@ struct RoutingOptionsView: View {
Toggle("avoid_unpaved", isOn: $shouldAvoidUnpavedRoadsWhileRouting)
.tint(.accent)
+ .disabled(shouldAvoidPavedRoadsWhileRouting)
Toggle("avoid_ferry", isOn: $shouldAvoidFerriesWhileRouting)
.tint(.accent)
@@ -47,6 +52,10 @@ struct RoutingOptionsView: View {
Toggle("avoid_steps", isOn: $shouldAvoidStepsWhileRouting)
.tint(.accent)
+
+ Toggle("avoid_paved", isOn: $shouldAvoidPavedRoadsWhileRouting)
+ .tint(.accent)
+ .disabled(shouldAvoidUnpavedRoadsWhileRouting)
}
}
.navigationTitle(String(localized: "driving_options_title"))
@@ -65,6 +74,7 @@ struct RoutingOptionsView: View {
.onAppear {
shouldAvoidTollRoadsWhileRouting = Settings.shouldAvoidTollRoadsWhileRouting
shouldAvoidUnpavedRoadsWhileRouting = Settings.shouldAvoidUnpavedRoadsWhileRouting
+ shouldAvoidPavedRoadsWhileRouting = Settings.shouldAvoidPavedRoadsWhileRouting
shouldAvoidFerriesWhileRouting = Settings.shouldAvoidFerriesWhileRouting
shouldAvoidMotorwaysWhileRouting = Settings.shouldAvoidMotorwaysWhileRouting
shouldAvoidStepsWhileRouting = Settings.shouldAvoidStepsWhileRouting
@@ -74,9 +84,15 @@ struct RoutingOptionsView: View {
}
.onChange(of: shouldAvoidUnpavedRoadsWhileRouting) { changedShouldAvoidUnpavedRoadsWhileRouting in
Settings.shouldAvoidUnpavedRoadsWhileRouting = changedShouldAvoidUnpavedRoadsWhileRouting
+ if changedShouldAvoidUnpavedRoadsWhileRouting {
+ shouldAvoidPavedRoadsWhileRouting = false
+ }
}
- .onChange(of: shouldAvoidUnpavedRoadsWhileRouting) { changedShouldAvoidUnpavedRoadsWhileRouting in
- Settings.shouldAvoidUnpavedRoadsWhileRouting = changedShouldAvoidUnpavedRoadsWhileRouting
+ .onChange(of: shouldAvoidPavedRoadsWhileRouting) { changedShouldAvoidPavedRoadsWhileRouting in
+ Settings.shouldAvoidPavedRoadsWhileRouting = changedShouldAvoidPavedRoadsWhileRouting
+ if changedShouldAvoidPavedRoadsWhileRouting {
+ shouldAvoidUnpavedRoadsWhileRouting = false
+ }
}
.onChange(of: shouldAvoidFerriesWhileRouting) { changedShouldAvoidFerriesWhileRouting in
Settings.shouldAvoidFerriesWhileRouting = changedShouldAvoidFerriesWhileRouting
diff --git a/iphone/Maps/UI/Settings/SettingsNavigationView.swift b/iphone/Maps/UI/Settings/SettingsNavigationView.swift
index e88a57c13..98fe54f18 100644
--- a/iphone/Maps/UI/Settings/SettingsNavigationView.swift
+++ b/iphone/Maps/UI/Settings/SettingsNavigationView.swift
@@ -40,6 +40,10 @@ struct SettingsNavigationView: View {
@State var shouldAvoidUnpavedRoadsWhileRouting: Bool = false
+ /// If paved roads should be avoided during routing
+ @State var shouldAvoidPavedRoadsWhileRouting: Bool = false
+
+
/// If ferries should be avoided during routing
@State var shouldAvoidFerriesWhileRouting: Bool = false
@@ -149,6 +153,7 @@ struct SettingsNavigationView: View {
Toggle("avoid_unpaved", isOn: $shouldAvoidUnpavedRoadsWhileRouting)
.tint(.accent)
+ .disabled(shouldAvoidPavedRoadsWhileRouting)
Toggle("avoid_ferry", isOn: $shouldAvoidFerriesWhileRouting)
.tint(.accent)
@@ -158,6 +163,10 @@ struct SettingsNavigationView: View {
Toggle("avoid_steps", isOn: $shouldAvoidStepsWhileRouting)
.tint(.accent)
+
+ Toggle("avoid_paved", isOn: $shouldAvoidPavedRoadsWhileRouting)
+ .tint(.accent)
+ .disabled(shouldAvoidUnpavedRoadsWhileRouting)
} header: {
Text("driving_options_title")
}
@@ -174,6 +183,7 @@ struct SettingsNavigationView: View {
selectedAnnouncingSpeedTrapsWhileVoiceRouting = Settings.announcingSpeedTrapsWhileVoiceRouting
shouldAvoidTollRoadsWhileRouting = Settings.shouldAvoidTollRoadsWhileRouting
shouldAvoidUnpavedRoadsWhileRouting = Settings.shouldAvoidUnpavedRoadsWhileRouting
+ shouldAvoidPavedRoadsWhileRouting = Settings.shouldAvoidPavedRoadsWhileRouting
shouldAvoidFerriesWhileRouting = Settings.shouldAvoidFerriesWhileRouting
shouldAvoidMotorwaysWhileRouting = Settings.shouldAvoidMotorwaysWhileRouting
shouldAvoidStepsWhileRouting = Settings.shouldAvoidStepsWhileRouting
@@ -206,9 +216,15 @@ struct SettingsNavigationView: View {
}
.onChange(of: shouldAvoidUnpavedRoadsWhileRouting) { changedShouldAvoidUnpavedRoadsWhileRouting in
Settings.shouldAvoidUnpavedRoadsWhileRouting = changedShouldAvoidUnpavedRoadsWhileRouting
+ if changedShouldAvoidUnpavedRoadsWhileRouting {
+ shouldAvoidPavedRoadsWhileRouting = false
+ }
}
- .onChange(of: shouldAvoidUnpavedRoadsWhileRouting) { changedShouldAvoidUnpavedRoadsWhileRouting in
- Settings.shouldAvoidUnpavedRoadsWhileRouting = changedShouldAvoidUnpavedRoadsWhileRouting
+ .onChange(of: shouldAvoidPavedRoadsWhileRouting) { changedShouldAvoidPavedRoadsWhileRouting in
+ Settings.shouldAvoidPavedRoadsWhileRouting = changedShouldAvoidPavedRoadsWhileRouting
+ if changedShouldAvoidPavedRoadsWhileRouting {
+ shouldAvoidUnpavedRoadsWhileRouting = false
+ }
}
.onChange(of: shouldAvoidFerriesWhileRouting) { changedShouldAvoidFerriesWhileRouting in
Settings.shouldAvoidFerriesWhileRouting = changedShouldAvoidFerriesWhileRouting