Skip to content

Commit

Permalink
Image expression options (#2369)
Browse files Browse the repository at this point in the history
  • Loading branch information
evil159 authored Nov 25, 2024
1 parent c2bb275 commit 34313b2
Show file tree
Hide file tree
Showing 8 changed files with 119 additions and 9 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ In order to continue use them use the following import `@_spi(Experimental) impo
That initializer doesn't require to wrap arguments in `Argument` cases. For example, `Exp(.eq, Exp(.get, "extrude"), "true")`.
* Expose a `TileStore/clearAmbientCache()` method to clear ambient cache.
* Add new experimental `radius` parameter to `TapInteraction`, `LongPressInteraction` and interaction managers to control the radius of a tappable area.
* Add a way to specify image expression options.
* Bump core maps version to 11.9.0-beta.1 and common sdk to 24.9.0-beta.1

## 11.8.0 - 11 November, 2024

Expand Down
2 changes: 1 addition & 1 deletion LICENSE.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions MapboxMaps.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ Pod::Spec.new do |m|
m.source_files = 'Sources/MapboxMaps/**/*.{swift,h}'
m.resource_bundles = { 'MapboxMapsResources' => ['Sources/**/*.{xcassets,strings}', 'Sources/MapboxMaps/MapboxMaps.json', 'Sources/MapboxMaps/PrivacyInfo.xcprivacy'] }

m.dependency 'MapboxCoreMaps', '11.9.0-SNAPSHOT.1122T1014Z.b9d442a'
m.dependency 'MapboxCommon', '24.9.0-SNAPSHOT.1112T0225Z.a361369'
m.dependency 'MapboxCoreMaps', '11.9.0-beta.1'
m.dependency 'MapboxCommon', '24.9.0-beta.1'
m.dependency 'Turf', '4.0.0-beta.1'

end
5 changes: 3 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
import PackageDescription
import Foundation

let coreMaps = MapsDependency.coreMaps(version: "11.9.0-SNAPSHOT.1122T1014Z.b9d442a", checksum: "ec2407a32601b0fca1c36fffb10707214473091e8bab2992f74fd2185a480f83")
let common = MapsDependency.common(version: "24.9.0-SNAPSHOT.1112T0225Z.a361369", checksum: "e828f210cc591daf087206066d5117c0d4c10e8ec07c233ab1cd8d800a834a63")
let coreMaps = MapsDependency.coreMaps(version: "11.9.0-beta.1")

let common = MapsDependency.common(version: "24.9.0-beta.1")

let mapboxMapsPath: String? = nil

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@
- ``FormatOptions``
- ``NumberFormatOptions``
- ``CollatorOptions``
- ``ImageOptions``
- ``ExpressionArgumentConvertible``
- ``ExpressionArgumentBuilder``
60 changes: 58 additions & 2 deletions Sources/MapboxMaps/Style/Types/ExpressionOptions.swift
Original file line number Diff line number Diff line change
@@ -1,21 +1,28 @@
import Foundation

private enum ExpDecodingError: Error {
case noKeysFound
}
extension Exp {

public enum Option: Codable, Equatable, Sendable {
case format(FormatOptions)
case numberFormat(NumberFormatOptions)
case collator(CollatorOptions)
case image(ImageOptions)

public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()

if let validFormatOptions = try? container.decode(FormatOptions.self) {
self = .format(validFormatOptions)
if let validImageOptions = try? container.decode(ImageOptions.self) {
self = .image(validImageOptions)

} else if let validNumberFormatOptions = try? container.decode(NumberFormatOptions.self) {
self = .numberFormat(validNumberFormatOptions)

} else if let validFormatOptions = try? container.decode(FormatOptions.self) {
self = .format(validFormatOptions)

} else if let validCollatorOptions = try? container.decode(CollatorOptions.self) {
self = .collator(validCollatorOptions)

Expand All @@ -36,6 +43,8 @@ extension Exp {
try container.encode(option)
case .numberFormat(let option):
try container.encode(option)
case .image(let option):
try container.encode(option)
}
}

Expand Down Expand Up @@ -104,6 +113,19 @@ public struct NumberFormatOptions: Codable, Equatable, ExpressionArgumentConvert
self.minFractionDigits = minFractionDigits
self.maxFractionDigits = maxFractionDigits
}

public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)

guard container.containsAnyKey() else {
throw ExpDecodingError.noKeysFound
}

locale = try container.decodeIfPresent(String.self, forKey: .locale)
currency = try container.decodeIfPresent(String.self, forKey: .currency)
minFractionDigits = try container.decodeIfPresent(Int.self, forKey: .minFractionDigits)
maxFractionDigits = try container.decodeIfPresent(Int.self, forKey: .maxFractionDigits)
}
}

public struct CollatorOptions: Codable, Equatable, ExpressionArgumentConvertible, Sendable {
Expand Down Expand Up @@ -133,5 +155,39 @@ public struct CollatorOptions: Codable, Equatable, ExpressionArgumentConvertible
self.diacriticSensitive = diacriticSensitive
self.locale = locale
}
}

/// Image options container.
public struct ImageOptions: Codable, Equatable, ExpressionArgumentConvertible, Sendable {
public typealias ColorLike = Value<StyleColor>

/// Vector image parameters.
public var options: [String: ColorLike]

public var expressionArguments: [Exp.Argument] {
return [.option(.image(self))]
}

public init(_ options: [String: ColorLike]) {
self.options = options
}

enum CodingKeys: String, CodingKey {
case options = "params"
}

public init(from decoder: any Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)

guard container.containsAnyKey() else {
throw ExpDecodingError.noKeysFound
}

options = try container.decode([String: ColorLike].self, forKey: .options)
}
}

extension KeyedDecodingContainer {
func containsAnyKey() -> Bool { allKeys.contains(where: contains) }

}
50 changes: 50 additions & 0 deletions Tests/MapboxMapsTests/Style/ExpressionTests/ExpressionTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -326,4 +326,54 @@ final class ExpressionTests: XCTestCase {

XCTAssertNotEqual(shortFormExpression, longFormExpression)
}

func testEncodeImageOptions() throws {
let color = StyleColor(UIColor.black)
let empty = ImageOptions([:])
let constantValues = ImageOptions([
"key": .constant(StyleColor("red")),
"key2": .constant(color)

])
let expression = Expression(.toRgba, Exp(.get, "color"))
let expression2 = Exp(.switchCase) {
Exp(.gte) {
Exp(.toNumber) {
Exp(.get) { "point_count" }
}
4
}
"#ffffff"
"#000000"
}
let expressionValues = ImageOptions([
"key": .expression(expression),
"key2": .expression(expression2)
])

let emptyEncoded = try DictionaryEncoder().encode(empty)
let constantValuesEncoded = try DictionaryEncoder().encode(constantValues)
let expressionValuesParamsEncoded = try DictionaryEncoder().encode(expressionValues)["params"] as? [String: Any]

XCTAssertEqual(emptyEncoded["params"] as? [String: String], [:])
XCTAssertEqual(constantValuesEncoded["params"] as? [String: String], ["key": "red", "key2": color.rawValue])
XCTAssertEqual(
String(data: try JSONSerialization.data(withJSONObject: expressionValuesParamsEncoded?["key"] as Any), encoding: .utf8),
##"["to-rgba",["get","color"]]"##
)
XCTAssertEqual(
String(data: try JSONSerialization.data(withJSONObject: expressionValuesParamsEncoded?["key2"] as Any), encoding: .utf8),
##"["case",[">=",["to-number",["get","point_count"]],4],"#ffffff","#000000"]"##
)
}

func testDecodeImageOptions() throws {
let jsonString = #"{"params": {"expression": ["get", "color"], "constant": "red", "rgb": "rgba(0, 0, 0, 1)"}}"#

let imageOptions = try JSONDecoder().decode(ImageOptions.self, from: try XCTUnwrap(jsonString.data(using: .utf8)))

XCTAssertEqual(imageOptions.options["expression"], Value.expression(Exp(.get) { "color" }))
XCTAssertEqual(imageOptions.options["constant"], Value.constant(StyleColor(rawValue: "red")))
XCTAssertEqual(imageOptions.options["rgb"], Value.constant(StyleColor("rgba(0, 0, 0, 1)")))
}
}
4 changes: 2 additions & 2 deletions scripts/release/packager/versions.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"MapboxCoreMaps": "11.9.0-SNAPSHOT.1122T1014Z.b9d442a",
"MapboxCommon": "24.9.0-SNAPSHOT.1112T0225Z.a361369",
"MapboxCoreMaps": "11.9.0-beta.1",
"MapboxCommon": "24.9.0-beta.1",
"Turf": "4.0.0-beta.1"
}

0 comments on commit 34313b2

Please sign in to comment.