@iternio/react-native-auto-play 0.3.12 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -1
- package/ReactNativeAutoPlay.podspec +0 -4
- package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/template/Parser.kt +10 -1
- package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/utils/SymbolFont.kt +29 -30
- package/ios/utils/SymbolFont.swift +44 -44
- package/ios/utils/VoiceInputManager.swift +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/types/Image.d.ts +33 -4
- package/lib/types/Maneuver.d.ts +2 -10
- package/lib/utils/NitroImage.d.ts +23 -2
- package/lib/utils/NitroImage.js +57 -3
- package/nitrogen/generated/android/c++/JGlyphImage.hpp +6 -1
- package/nitrogen/generated/android/c++/JNitroImage.hpp +1 -1
- package/nitrogen/generated/android/c++/JVariant_GlyphImage_AssetImage_RemoteImage.hpp +1 -1
- package/nitrogen/generated/android/c++/JVariant_PreferredImageLane_ImageLane.hpp +1 -1
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/GlyphImage.kt +5 -2
- package/nitrogen/generated/ios/c++/HybridCarPlayDashboardSpecSwift.hpp +1 -1
- package/nitrogen/generated/ios/swift/GlyphImage.swift +7 -2
- package/nitrogen/generated/shared/c++/GlyphImage.hpp +6 -1
- package/package.json +2 -3
- package/src/index.ts +1 -0
- package/src/types/Image.ts +53 -18
- package/src/types/Maneuver.ts +3 -10
- package/src/utils/NitroImage.ts +66 -5
- package/android/src/main/res/font/materialsymbolsoutlined_regular.ttf +0 -0
- package/ios/Assets/MaterialSymbolsOutlined-Regular.ttf +0 -0
- package/lib/types/Glyphmap.d.ts +0 -4105
- package/lib/types/Glyphmap.js +0 -4105
- package/src/types/Glyphmap.ts +0 -4107
package/README.md
CHANGED
|
@@ -304,7 +304,49 @@ When using build variants, Android Studio may not be aware of the selected varia
|
|
|
304
304
|
To work around this and allow for debugging or enhancing the Android Automotive-specific implementation, you can temporarily set the automotive flags in your `gradle.properties` file or your default `.env` file before running a Gradle sync.
|
|
305
305
|
|
|
306
306
|
## Icons
|
|
307
|
-
The library
|
|
307
|
+
The library does **not** bundle any icon font — the consuming app must provide one.
|
|
308
|
+
|
|
309
|
+
### Setup
|
|
310
|
+
|
|
311
|
+
1. Add a `.ttf` font file to your native projects:
|
|
312
|
+
- **iOS** — add `<name>.ttf` to your app bundle (no `UIAppFonts` entry needed — the library registers it via CoreText automatically).
|
|
313
|
+
- **Android** — place `<name>.ttf` in `res/font/`.
|
|
314
|
+
|
|
315
|
+
For cross-platform compatibility use **lowercase names with underscores only** (e.g. `material_symbols`).
|
|
316
|
+
|
|
317
|
+
2. Register the font and an optional glyph map at startup:
|
|
318
|
+
|
|
319
|
+
```ts
|
|
320
|
+
import { setIconFont } from '@iternio/react-native-auto-play';
|
|
321
|
+
import { glyphMap } from './assets/Glyphmap';
|
|
322
|
+
|
|
323
|
+
setIconFont('material_symbols', glyphMap);
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
3. Use glyph images by name or code point:
|
|
327
|
+
|
|
328
|
+
```ts
|
|
329
|
+
{ type: 'glyph', name: 'directions_car' }
|
|
330
|
+
{ type: 'glyph', codepoint: 0xe531 }
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
`setIconFont` must be called once before the first glyph is used (subsequent calls are ignored). If no font is registered, the library throws an error when a glyph image is rendered.
|
|
334
|
+
|
|
335
|
+
### Type-safe glyph names
|
|
336
|
+
|
|
337
|
+
To get autocompletion and type checking for glyph names, create a declaration file in your app (e.g. `autoplay-glyphs.d.ts`):
|
|
338
|
+
|
|
339
|
+
```ts
|
|
340
|
+
import type { GlyphName } from './assets/Glyphmap';
|
|
341
|
+
|
|
342
|
+
declare module '@iternio/react-native-auto-play' {
|
|
343
|
+
interface AutoPlayGlyphMap extends Record<GlyphName, number> {}
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
Without this augmentation, `name` accepts any `string`. With it, only keys from your glyph map are allowed and you get full autocompletion.
|
|
348
|
+
|
|
349
|
+
The example app uses [Material Symbols](https://fonts.google.com/icons). See `apps/example/assets/symbolFont/` for the glyph map generation script.
|
|
308
350
|
|
|
309
351
|
It is also possible to use custom bundled images (e.g. PNG, WEBP or Vector Drawables). Make sure to add them to your native projects.
|
|
310
352
|
- iOS: Add to your `Images.xcassets`
|
|
@@ -25,10 +25,6 @@ Pod::Spec.new do |s|
|
|
|
25
25
|
# react helpers like RCTConvert
|
|
26
26
|
s.public_header_files = Array(s.attributes_hash['public_header_files']) + ["ios/ReactHelpers/*.h"]
|
|
27
27
|
|
|
28
|
-
s.resource_bundles = {
|
|
29
|
-
"ReactNativeAutoPlay" => ['ios/Assets/**/*.ttf']
|
|
30
|
-
}
|
|
31
|
-
|
|
32
28
|
s.pod_target_xcconfig = {
|
|
33
29
|
# C++ compiler flags, mainly for folly.
|
|
34
30
|
"GCC_PREPROCESSOR_DEFINITIONS" => "$(inherited) FOLLY_NO_CONFIG FOLLY_CFG_NO_COROUTINES"
|
package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/template/Parser.kt
CHANGED
|
@@ -598,11 +598,20 @@ object Parser {
|
|
|
598
598
|
val image = result?.get()
|
|
599
599
|
try {
|
|
600
600
|
if (image is CloseableBitmap) {
|
|
601
|
-
|
|
601
|
+
// underlyingBitmap can be null when Fresco decodes to a CloseableBitmap
|
|
602
|
+
// whose backing bitmap has already been recycled or failed to allocate;
|
|
603
|
+
// copy() can also throw (e.g., OOM on very large remote images). Either
|
|
604
|
+
// way we return null so the caller falls back to a placeholder icon.
|
|
605
|
+
return image.underlyingBitmap?.copy(Bitmap.Config.ARGB_8888, false)
|
|
602
606
|
} else if (image is CloseableXml) {
|
|
603
607
|
val drawable = image.buildDrawable()
|
|
604
608
|
return drawable?.toBitmap(width = image.width, height = image.height, Bitmap.Config.ARGB_8888)
|
|
605
609
|
}
|
|
610
|
+
} catch (_: Exception) {
|
|
611
|
+
// Any decode/copy failure (OOM, recycled bitmap, invalid config, …) should
|
|
612
|
+
// not crash the car app — the image is optional decoration and the caller
|
|
613
|
+
// handles a null return with CarIcon.ALERT.
|
|
614
|
+
return null
|
|
606
615
|
} finally {
|
|
607
616
|
image?.close()
|
|
608
617
|
result?.close()
|
package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/utils/SymbolFont.kt
CHANGED
|
@@ -10,39 +10,36 @@ import android.graphics.Typeface
|
|
|
10
10
|
import androidx.car.app.CarContext
|
|
11
11
|
import androidx.core.content.res.ResourcesCompat
|
|
12
12
|
import androidx.core.graphics.createBitmap
|
|
13
|
-
import androidx.core.graphics.drawable.IconCompat
|
|
14
|
-
import com.margelo.nitro.swe.iternio.reactnativeautoplay.GlyphImage
|
|
15
|
-
import com.margelo.nitro.swe.iternio.reactnativeautoplay.NitroImage
|
|
16
13
|
import com.margelo.nitro.swe.iternio.reactnativeautoplay.BuildConfig
|
|
17
|
-
import com.margelo.nitro.swe.iternio.reactnativeautoplay.
|
|
18
|
-
import com.margelo.nitro.swe.iternio.reactnativeautoplay.template.Parser
|
|
14
|
+
import com.margelo.nitro.swe.iternio.reactnativeautoplay.GlyphImage
|
|
19
15
|
|
|
20
16
|
object SymbolFont {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
private var typeface: Typeface? = null
|
|
24
|
-
|
|
25
|
-
private fun loadFont(context: Context) {
|
|
26
|
-
if (typeface != null) {
|
|
27
|
-
return
|
|
28
|
-
}
|
|
17
|
+
private var cachedFontName: String? = null
|
|
18
|
+
private var cachedTypeface: Typeface? = null
|
|
29
19
|
|
|
30
|
-
|
|
20
|
+
private fun loadTypeface(context: Context, fontName: String): Typeface? {
|
|
21
|
+
if (fontName == cachedFontName) return cachedTypeface
|
|
22
|
+
val id = context.resources.getIdentifier(
|
|
23
|
+
fontName.lowercase(), "font", context.packageName
|
|
24
|
+
)
|
|
25
|
+
if (id == 0) return null
|
|
26
|
+
val tf = ResourcesCompat.getFont(context, id) ?: return null
|
|
27
|
+
cachedFontName = fontName
|
|
28
|
+
cachedTypeface = tf
|
|
29
|
+
return tf
|
|
31
30
|
}
|
|
32
31
|
|
|
33
32
|
private fun imageFromGlyph(
|
|
34
33
|
context: Context,
|
|
35
|
-
|
|
34
|
+
glyphImage: GlyphImage,
|
|
36
35
|
color: Int,
|
|
37
36
|
backgroundColor: Int,
|
|
38
37
|
cornerRadius: Float = 8f, //TODO: make accessible and add it to GlyphImage.cacheKey
|
|
39
|
-
fontScale: Float,
|
|
40
38
|
): Bitmap? {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
39
|
+
val font =
|
|
40
|
+
loadTypeface(context, glyphImage.fontName) ?: run {
|
|
41
|
+
return null
|
|
42
|
+
}
|
|
46
43
|
|
|
47
44
|
val virtualScreenDensity = context.resources.displayMetrics.density
|
|
48
45
|
val scale = BuildConfig.SCALE_FACTOR * virtualScreenDensity
|
|
@@ -59,6 +56,8 @@ object SymbolFont {
|
|
|
59
56
|
}
|
|
60
57
|
canvas.drawRoundRect(rectF, cornerRadius, cornerRadius, paint)
|
|
61
58
|
|
|
59
|
+
val fontScale = (glyphImage.fontScale ?: 1.0).toFloat()
|
|
60
|
+
|
|
62
61
|
// Setup text paint
|
|
63
62
|
paint.reset()
|
|
64
63
|
paint = Paint().apply {
|
|
@@ -70,7 +69,7 @@ object SymbolFont {
|
|
|
70
69
|
}
|
|
71
70
|
|
|
72
71
|
// Get the character from codepoint
|
|
73
|
-
val codepoint = glyph.toInt()
|
|
72
|
+
val codepoint = glyphImage.glyph.toInt()
|
|
74
73
|
val text = String(Character.toChars(codepoint))
|
|
75
74
|
|
|
76
75
|
// Measure text
|
|
@@ -94,13 +93,13 @@ object SymbolFont {
|
|
|
94
93
|
return bitmap
|
|
95
94
|
}
|
|
96
95
|
|
|
97
|
-
bitmap =
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
96
|
+
bitmap =
|
|
97
|
+
imageFromGlyph(
|
|
98
|
+
context = context,
|
|
99
|
+
glyphImage = image,
|
|
100
|
+
color = image.color.get(context),
|
|
101
|
+
backgroundColor = image.backgroundColor.get(context),
|
|
102
|
+
)
|
|
104
103
|
|
|
105
104
|
bitmap?.let {
|
|
106
105
|
BitmapCache.put(context, image, it)
|
|
@@ -108,4 +107,4 @@ object SymbolFont {
|
|
|
108
107
|
|
|
109
108
|
return bitmap
|
|
110
109
|
}
|
|
111
|
-
}
|
|
110
|
+
}
|
|
@@ -9,67 +9,65 @@ import CoreText
|
|
|
9
9
|
import UIKit
|
|
10
10
|
|
|
11
11
|
class SymbolFont {
|
|
12
|
-
private static
|
|
12
|
+
private static var cachedFontName: String?
|
|
13
|
+
private static var cachedPSName: String?
|
|
13
14
|
|
|
14
|
-
private static
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
let podBundle = Bundle(for: SymbolFont.self)
|
|
15
|
+
private static func loadFont(named fontName: String) -> String? {
|
|
16
|
+
if fontName == cachedFontName {
|
|
17
|
+
return cachedPSName
|
|
18
|
+
}
|
|
19
19
|
|
|
20
|
-
guard
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
withExtension: "bundle"
|
|
24
|
-
),
|
|
25
|
-
let resourceBundle = Bundle(url: bundleURL),
|
|
26
|
-
let fontURL = resourceBundle.url(
|
|
27
|
-
forResource: "MaterialSymbolsOutlined-Regular",
|
|
28
|
-
withExtension: "ttf"
|
|
29
|
-
)
|
|
30
|
-
else {
|
|
31
|
-
return
|
|
20
|
+
guard let url = Bundle.main.url(forResource: fontName, withExtension: "ttf") else {
|
|
21
|
+
print("[AutoPlay] \(fontName).ttf not found in the app bundle — glyph images will not render.")
|
|
22
|
+
return nil
|
|
32
23
|
}
|
|
33
24
|
|
|
34
|
-
guard let fontData = try? Data(contentsOf:
|
|
25
|
+
guard let fontData = try? Data(contentsOf: url) as CFData,
|
|
35
26
|
let provider = CGDataProvider(data: fontData),
|
|
36
27
|
let font = CGFont(provider)
|
|
37
28
|
else {
|
|
38
|
-
return
|
|
29
|
+
return nil
|
|
39
30
|
}
|
|
40
31
|
|
|
41
32
|
var error: Unmanaged<CFError>?
|
|
42
33
|
CTFontManagerRegisterGraphicsFont(font, &error)
|
|
43
|
-
|
|
44
|
-
|
|
34
|
+
// Ignore already-registered errors (e.g. hot reload)
|
|
35
|
+
|
|
36
|
+
guard let psName = font.fullName as? String else {
|
|
37
|
+
return nil
|
|
45
38
|
}
|
|
46
|
-
|
|
47
|
-
|
|
39
|
+
|
|
40
|
+
cachedFontName = fontName
|
|
41
|
+
cachedPSName = psName
|
|
42
|
+
return psName
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
private static func uiFont(for glyphImage: GlyphImage, size: CGFloat, fontScale: CGFloat) -> UIFont? {
|
|
46
|
+
let pointSize = size * fontScale
|
|
47
|
+
|
|
48
|
+
guard let psName = loadFont(named: glyphImage.fontName) else {
|
|
49
|
+
return nil
|
|
48
50
|
}
|
|
49
51
|
|
|
50
|
-
|
|
51
|
-
SymbolFont.isRegistered = true
|
|
52
|
+
return UIFont(name: psName, size: pointSize)
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
// creates a single color UIImage
|
|
55
56
|
static func imageFromGlyph(
|
|
56
|
-
|
|
57
|
+
glyphImage: GlyphImage,
|
|
57
58
|
foregroundColor: UIColor,
|
|
58
59
|
backgroundColor: UIColor,
|
|
59
60
|
size: CGFloat,
|
|
60
61
|
fontScale: CGFloat
|
|
61
62
|
) -> UIImage? {
|
|
62
|
-
|
|
63
|
-
|
|
63
|
+
guard let font = uiFont(for: glyphImage, size: size, fontScale: fontScale) else {
|
|
64
|
+
return nil
|
|
64
65
|
}
|
|
65
66
|
|
|
66
|
-
guard let
|
|
67
|
-
let font = UIFont(name: fontName, size: size * fontScale)
|
|
68
|
-
else {
|
|
67
|
+
guard let scalar = UnicodeScalar(UInt32(glyphImage.glyph)) else {
|
|
69
68
|
return nil
|
|
70
69
|
}
|
|
71
|
-
|
|
72
|
-
let codepoint = String(UnicodeScalar(UInt32(glyph))!)
|
|
70
|
+
let codepoint = String(Character(scalar))
|
|
73
71
|
let canvasSize = CGSize(width: size, height: size)
|
|
74
72
|
let rect = CGRect(origin: .zero, size: canvasSize)
|
|
75
73
|
|
|
@@ -99,14 +97,14 @@ class SymbolFont {
|
|
|
99
97
|
let y = (canvasSize.height - textSize.height) / 2
|
|
100
98
|
attrString.draw(at: CGPoint(x: x, y: y))
|
|
101
99
|
|
|
102
|
-
let
|
|
100
|
+
let uiImage = UIGraphicsGetImageFromCurrentImageContext()
|
|
103
101
|
UIGraphicsEndImageContext()
|
|
104
102
|
|
|
105
|
-
return
|
|
103
|
+
return uiImage
|
|
106
104
|
}
|
|
107
105
|
|
|
108
106
|
static func imageFromGlyph(
|
|
109
|
-
|
|
107
|
+
glyphImage: GlyphImage,
|
|
110
108
|
size: CGFloat,
|
|
111
109
|
foregroundColor: NitroColor,
|
|
112
110
|
backgroundColor: NitroColor,
|
|
@@ -115,7 +113,7 @@ class SymbolFont {
|
|
|
115
113
|
) -> UIImage? {
|
|
116
114
|
guard
|
|
117
115
|
let lightImage = imageFromGlyph(
|
|
118
|
-
|
|
116
|
+
glyphImage: glyphImage,
|
|
119
117
|
foregroundColor: Parser.doubleToColor(
|
|
120
118
|
value: foregroundColor.lightColor
|
|
121
119
|
),
|
|
@@ -126,7 +124,7 @@ class SymbolFont {
|
|
|
126
124
|
fontScale: fontScale
|
|
127
125
|
),
|
|
128
126
|
let darkImage = imageFromGlyph(
|
|
129
|
-
|
|
127
|
+
glyphImage: glyphImage,
|
|
130
128
|
foregroundColor: Parser.doubleToColor(
|
|
131
129
|
value: foregroundColor.darkColor
|
|
132
130
|
),
|
|
@@ -167,6 +165,8 @@ class SymbolFont {
|
|
|
167
165
|
) -> UIImage? {
|
|
168
166
|
guard let image else { return nil }
|
|
169
167
|
|
|
168
|
+
let fontScale = image.fontScale ?? 1.0
|
|
169
|
+
|
|
170
170
|
if noImageAsset {
|
|
171
171
|
let foregroundColor = Parser.doubleToColor(
|
|
172
172
|
value: traitCollection.userInterfaceStyle == .light
|
|
@@ -180,21 +180,21 @@ class SymbolFont {
|
|
|
180
180
|
)
|
|
181
181
|
|
|
182
182
|
return SymbolFont.imageFromGlyph(
|
|
183
|
-
|
|
183
|
+
glyphImage: image,
|
|
184
184
|
foregroundColor: foregroundColor,
|
|
185
185
|
backgroundColor: backgroundColor,
|
|
186
186
|
size: size,
|
|
187
|
-
fontScale:
|
|
187
|
+
fontScale: fontScale
|
|
188
188
|
)
|
|
189
189
|
}
|
|
190
190
|
|
|
191
191
|
return SymbolFont.imageFromGlyph(
|
|
192
|
-
|
|
192
|
+
glyphImage: image,
|
|
193
193
|
size: size,
|
|
194
194
|
foregroundColor: image.color,
|
|
195
195
|
backgroundColor: image.backgroundColor,
|
|
196
|
-
fontScale:
|
|
196
|
+
fontScale: fontScale,
|
|
197
197
|
traitCollection: traitCollection
|
|
198
|
-
)
|
|
198
|
+
)
|
|
199
199
|
}
|
|
200
200
|
}
|
|
@@ -90,7 +90,7 @@ class VoiceInputManager {
|
|
|
90
90
|
|
|
91
91
|
// Activate the session first so inputNode reports the correct hardware format
|
|
92
92
|
let session = AVAudioSession.sharedInstance()
|
|
93
|
-
try session.setCategory(.playAndRecord, mode: .measurement, options: [
|
|
93
|
+
try session.setCategory(.playAndRecord, mode: .measurement, options: [])
|
|
94
94
|
try session.setActive(true)
|
|
95
95
|
|
|
96
96
|
if let interfaceController {
|
package/lib/index.d.ts
CHANGED
|
@@ -43,3 +43,4 @@ export * from './types/Trip';
|
|
|
43
43
|
export type { AlertPriority, NavigationAlert as Alert, NavigationAlertAction as AlertAction, } from './utils/NitroAlert';
|
|
44
44
|
export type { ThemedColor } from './utils/NitroColor';
|
|
45
45
|
export type { GridButton } from './utils/NitroGrid';
|
|
46
|
+
export { setIconFont } from './utils/NitroImage';
|
package/lib/index.js
CHANGED
package/lib/types/Image.d.ts
CHANGED
|
@@ -1,8 +1,22 @@
|
|
|
1
1
|
import type { ImageSourcePropType } from 'react-native';
|
|
2
2
|
import type { ThemedColor } from '../utils/NitroColor';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Augment this interface in your app to get type-safe glyph name autocompletion.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* // autoplay-glyphs.d.ts
|
|
9
|
+
* import type { GlyphName } from './assets/symbolFont/Glyphmap';
|
|
10
|
+
* declare module '@iternio/react-native-auto-play' {
|
|
11
|
+
* interface AutoPlayGlyphMap extends Record<GlyphName, number> {}
|
|
12
|
+
* }
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export interface AutoPlayGlyphMap {
|
|
16
|
+
}
|
|
17
|
+
/** Resolves to the augmented glyph name union, or falls back to `string` when not augmented. */
|
|
18
|
+
export type GlyphMapKey = keyof AutoPlayGlyphMap extends never ? string : Extract<keyof AutoPlayGlyphMap, string>;
|
|
19
|
+
type GlyphStyleFields = {
|
|
6
20
|
/**
|
|
7
21
|
* Sets the icon dark and light mode color or a single color for both.
|
|
8
22
|
* Defaults to white for dark mode and black for light mode if not specified.
|
|
@@ -15,8 +29,22 @@ export type AutoImage = {
|
|
|
15
29
|
*/
|
|
16
30
|
backgroundColor?: ThemedColor | string;
|
|
17
31
|
fontScale?: number;
|
|
32
|
+
};
|
|
33
|
+
/** Glyph by name — looked up in the glyph map registered via {@link setIconFont}. */
|
|
34
|
+
export type AutoGlyphByName = GlyphStyleFields & {
|
|
18
35
|
type: 'glyph';
|
|
19
|
-
|
|
36
|
+
/** Key in the glyph map passed to `setIconFont`. */
|
|
37
|
+
name: GlyphMapKey;
|
|
38
|
+
/** Optional override — if set, used instead of the map lookup. */
|
|
39
|
+
codepoint?: number;
|
|
40
|
+
};
|
|
41
|
+
/** Glyph by raw Unicode code point. */
|
|
42
|
+
export type AutoGlyphByCodepoint = GlyphStyleFields & {
|
|
43
|
+
type: 'glyph';
|
|
44
|
+
codepoint: number;
|
|
45
|
+
};
|
|
46
|
+
export type AutoGlyph = AutoGlyphByName | AutoGlyphByCodepoint;
|
|
47
|
+
export type AutoImage = AutoGlyph | {
|
|
20
48
|
image: ImageSourcePropType;
|
|
21
49
|
/**
|
|
22
50
|
* if specified the image gets tinted, if not it will just use the original image
|
|
@@ -38,3 +66,4 @@ export type AutoImage = {
|
|
|
38
66
|
timeoutMs?: number;
|
|
39
67
|
type: 'remote';
|
|
40
68
|
};
|
|
69
|
+
export {};
|
package/lib/types/Maneuver.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ImageSourcePropType } from 'react-native';
|
|
2
2
|
import type { ThemedColor } from '../utils/NitroColor';
|
|
3
|
-
import type {
|
|
3
|
+
import type { AutoGlyphByCodepoint, AutoGlyphByName } from './Image';
|
|
4
4
|
import type { TravelEstimates } from './Trip';
|
|
5
5
|
export declare enum ManeuverType {
|
|
6
6
|
Depart = 0,
|
|
@@ -148,15 +148,7 @@ export interface PreferredLane extends Lane {
|
|
|
148
148
|
highlightedAngle: number;
|
|
149
149
|
isPreferred: boolean;
|
|
150
150
|
}
|
|
151
|
-
export type ManeuverImage = {
|
|
152
|
-
name: GlyphName;
|
|
153
|
-
/**
|
|
154
|
-
* make sure to specify a color with a proper contrast ratio to cardBackgroundColor otherwise it might not get applied
|
|
155
|
-
* defaults to white/black for dark/light mode
|
|
156
|
-
*/
|
|
157
|
-
color?: ThemedColor | string;
|
|
158
|
-
type: 'glyph';
|
|
159
|
-
} | {
|
|
151
|
+
export type ManeuverImage = Pick<AutoGlyphByName, 'type' | 'name' | 'codepoint' | 'color'> | Pick<AutoGlyphByCodepoint, 'type' | 'codepoint' | 'color'> | {
|
|
160
152
|
image: ImageSourcePropType;
|
|
161
153
|
/**
|
|
162
154
|
* if specified the image gets tinted, if not it will just use the original image
|
|
@@ -1,12 +1,34 @@
|
|
|
1
1
|
import { type ImageResolvedAssetSource } from 'react-native';
|
|
2
2
|
import type { AutoImage } from '../types/Image';
|
|
3
3
|
import { type NitroColor } from './NitroColor';
|
|
4
|
+
/**
|
|
5
|
+
* Register the icon font and (optionally) a glyph map for name-based lookups.
|
|
6
|
+
* Must be called **once** before creating any templates. Subsequent calls are ignored.
|
|
7
|
+
*
|
|
8
|
+
* The font name maps directly to a native font asset:
|
|
9
|
+
* - **Android** — `res/font/<name>.ttf` (must be lowercase)
|
|
10
|
+
* - **iOS** — `<name>.ttf` in the app bundle (registered via CoreText automatically)
|
|
11
|
+
*
|
|
12
|
+
* For cross-platform compatibility use lowercase with underscores only.
|
|
13
|
+
*
|
|
14
|
+
* @param name Native font asset name (without extension).
|
|
15
|
+
* @param glyphMap Optional map of glyph names to Unicode code points.
|
|
16
|
+
* When provided, glyphs can use `{ type: 'glyph', name: 'icon_name' }`.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* import { glyphMap } from './assets/Glyphmap';
|
|
21
|
+
* setIconFont('material_symbols', glyphMap);
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare function setIconFont(name: string, glyphMap?: Record<string, number>): void;
|
|
4
25
|
interface AssetImage extends ImageResolvedAssetSource {
|
|
5
26
|
color?: NitroColor;
|
|
6
27
|
packager_asset: boolean;
|
|
7
28
|
}
|
|
8
29
|
interface GlyphImage {
|
|
9
30
|
glyph: number;
|
|
31
|
+
fontName: string;
|
|
10
32
|
color: NitroColor;
|
|
11
33
|
backgroundColor: NitroColor;
|
|
12
34
|
fontScale?: number;
|
|
@@ -17,8 +39,7 @@ interface RemoteImage {
|
|
|
17
39
|
timeoutMs?: number;
|
|
18
40
|
}
|
|
19
41
|
/**
|
|
20
|
-
*
|
|
21
|
-
* the actual numeric value so we need a nitro specific type
|
|
42
|
+
* NitroModules-compatible image types passed to native.
|
|
22
43
|
*/
|
|
23
44
|
export type NitroImage = GlyphImage | AssetImage | RemoteImage;
|
|
24
45
|
declare function convert(image: AutoImage): NitroImage;
|
package/lib/utils/NitroImage.js
CHANGED
|
@@ -1,14 +1,68 @@
|
|
|
1
1
|
import { Image } from 'react-native';
|
|
2
|
-
import { glyphMap } from '../types/Glyphmap';
|
|
3
2
|
import { NitroColorUtil } from './NitroColor';
|
|
3
|
+
let _iconFont;
|
|
4
|
+
let _glyphMap;
|
|
5
|
+
/**
|
|
6
|
+
* Register the icon font and (optionally) a glyph map for name-based lookups.
|
|
7
|
+
* Must be called **once** before creating any templates. Subsequent calls are ignored.
|
|
8
|
+
*
|
|
9
|
+
* The font name maps directly to a native font asset:
|
|
10
|
+
* - **Android** — `res/font/<name>.ttf` (must be lowercase)
|
|
11
|
+
* - **iOS** — `<name>.ttf` in the app bundle (registered via CoreText automatically)
|
|
12
|
+
*
|
|
13
|
+
* For cross-platform compatibility use lowercase with underscores only.
|
|
14
|
+
*
|
|
15
|
+
* @param name Native font asset name (without extension).
|
|
16
|
+
* @param glyphMap Optional map of glyph names to Unicode code points.
|
|
17
|
+
* When provided, glyphs can use `{ type: 'glyph', name: 'icon_name' }`.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* import { glyphMap } from './assets/Glyphmap';
|
|
22
|
+
* setIconFont('material_symbols', glyphMap);
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export function setIconFont(name, glyphMap) {
|
|
26
|
+
if (_iconFont != null) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
_iconFont = name;
|
|
30
|
+
_glyphMap = glyphMap;
|
|
31
|
+
}
|
|
32
|
+
function getIconFont() {
|
|
33
|
+
if (_iconFont == null) {
|
|
34
|
+
throw new Error('No icon font configured. Call setIconFont("your_font_name") before using glyph images.');
|
|
35
|
+
}
|
|
36
|
+
return _iconFont;
|
|
37
|
+
}
|
|
38
|
+
function resolveGlyph(image) {
|
|
39
|
+
if ('name' in image && image.name !== undefined) {
|
|
40
|
+
if (image.codepoint !== undefined) {
|
|
41
|
+
return image.codepoint;
|
|
42
|
+
}
|
|
43
|
+
if (_glyphMap == null) {
|
|
44
|
+
throw new Error(`Glyph name "${image.name}" used but no glyph map was provided to setIconFont().`);
|
|
45
|
+
}
|
|
46
|
+
const cp = _glyphMap[image.name];
|
|
47
|
+
if (cp === undefined) {
|
|
48
|
+
throw new Error(`Glyph name "${image.name}" not found in the glyph map.`);
|
|
49
|
+
}
|
|
50
|
+
return cp;
|
|
51
|
+
}
|
|
52
|
+
if (image.codepoint !== undefined) {
|
|
53
|
+
return image.codepoint;
|
|
54
|
+
}
|
|
55
|
+
throw new Error('Glyph image must provide either `name` or `codepoint`.');
|
|
56
|
+
}
|
|
4
57
|
function convert(image) {
|
|
5
58
|
if (image == null) {
|
|
6
59
|
return undefined;
|
|
7
60
|
}
|
|
8
61
|
if (image.type === 'glyph') {
|
|
9
|
-
const { color = { darkColor: 'white', lightColor: 'black' }, fontScale,
|
|
62
|
+
const { color = { darkColor: 'white', lightColor: 'black' }, fontScale, backgroundColor = 'transparent', } = image;
|
|
10
63
|
return {
|
|
11
|
-
glyph:
|
|
64
|
+
glyph: resolveGlyph(image),
|
|
65
|
+
fontName: getIconFont(),
|
|
12
66
|
color: NitroColorUtil.convert(color),
|
|
13
67
|
backgroundColor: NitroColorUtil.convert(backgroundColor),
|
|
14
68
|
fontScale,
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
#include "JNitroColor.hpp"
|
|
14
14
|
#include "NitroColor.hpp"
|
|
15
15
|
#include <optional>
|
|
16
|
+
#include <string>
|
|
16
17
|
|
|
17
18
|
namespace margelo::nitro::swe::iternio::reactnativeautoplay {
|
|
18
19
|
|
|
@@ -35,6 +36,8 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay {
|
|
|
35
36
|
static const auto clazz = javaClassStatic();
|
|
36
37
|
static const auto fieldGlyph = clazz->getField<double>("glyph");
|
|
37
38
|
double glyph = this->getFieldValue(fieldGlyph);
|
|
39
|
+
static const auto fieldFontName = clazz->getField<jni::JString>("fontName");
|
|
40
|
+
jni::local_ref<jni::JString> fontName = this->getFieldValue(fieldFontName);
|
|
38
41
|
static const auto fieldColor = clazz->getField<JNitroColor>("color");
|
|
39
42
|
jni::local_ref<JNitroColor> color = this->getFieldValue(fieldColor);
|
|
40
43
|
static const auto fieldBackgroundColor = clazz->getField<JNitroColor>("backgroundColor");
|
|
@@ -43,6 +46,7 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay {
|
|
|
43
46
|
jni::local_ref<jni::JDouble> fontScale = this->getFieldValue(fieldFontScale);
|
|
44
47
|
return GlyphImage(
|
|
45
48
|
glyph,
|
|
49
|
+
fontName->toStdString(),
|
|
46
50
|
color->toCpp(),
|
|
47
51
|
backgroundColor->toCpp(),
|
|
48
52
|
fontScale != nullptr ? std::make_optional(fontScale->value()) : std::nullopt
|
|
@@ -55,12 +59,13 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay {
|
|
|
55
59
|
*/
|
|
56
60
|
[[maybe_unused]]
|
|
57
61
|
static jni::local_ref<JGlyphImage::javaobject> fromCpp(const GlyphImage& value) {
|
|
58
|
-
using JSignature = JGlyphImage(double, jni::alias_ref<JNitroColor>, jni::alias_ref<JNitroColor>, jni::alias_ref<jni::JDouble>);
|
|
62
|
+
using JSignature = JGlyphImage(double, jni::alias_ref<jni::JString>, jni::alias_ref<JNitroColor>, jni::alias_ref<JNitroColor>, jni::alias_ref<jni::JDouble>);
|
|
59
63
|
static const auto clazz = javaClassStatic();
|
|
60
64
|
static const auto create = clazz->getStaticMethod<JSignature>("fromCpp");
|
|
61
65
|
return create(
|
|
62
66
|
clazz,
|
|
63
67
|
value.glyph,
|
|
68
|
+
jni::make_jstring(value.fontName),
|
|
64
69
|
JNitroColor::fromCpp(value.color),
|
|
65
70
|
JNitroColor::fromCpp(value.backgroundColor),
|
|
66
71
|
value.fontScale.has_value() ? jni::JDouble::valueOf(value.fontScale.value()) : nullptr
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
#include "RemoteImage.hpp"
|
|
16
16
|
#include <variant>
|
|
17
17
|
#include "JGlyphImage.hpp"
|
|
18
|
+
#include <string>
|
|
18
19
|
#include "NitroColor.hpp"
|
|
19
20
|
#include "JNitroColor.hpp"
|
|
20
21
|
#include <optional>
|
|
21
22
|
#include "JAssetImage.hpp"
|
|
22
|
-
#include <string>
|
|
23
23
|
#include "JRemoteImage.hpp"
|
|
24
24
|
|
|
25
25
|
namespace margelo::nitro::swe::iternio::reactnativeautoplay {
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
#include "RemoteImage.hpp"
|
|
16
16
|
#include <variant>
|
|
17
17
|
#include "JGlyphImage.hpp"
|
|
18
|
+
#include <string>
|
|
18
19
|
#include "NitroColor.hpp"
|
|
19
20
|
#include "JNitroColor.hpp"
|
|
20
21
|
#include <optional>
|
|
21
22
|
#include "JAssetImage.hpp"
|
|
22
|
-
#include <string>
|
|
23
23
|
#include "JRemoteImage.hpp"
|
|
24
24
|
|
|
25
25
|
namespace margelo::nitro::swe::iternio::reactnativeautoplay {
|
|
@@ -19,11 +19,11 @@
|
|
|
19
19
|
#include "RemoteImage.hpp"
|
|
20
20
|
#include "JNitroImage.hpp"
|
|
21
21
|
#include "JGlyphImage.hpp"
|
|
22
|
+
#include <string>
|
|
22
23
|
#include "NitroColor.hpp"
|
|
23
24
|
#include "JNitroColor.hpp"
|
|
24
25
|
#include <optional>
|
|
25
26
|
#include "JAssetImage.hpp"
|
|
26
|
-
#include <string>
|
|
27
27
|
#include "JRemoteImage.hpp"
|
|
28
28
|
#include <vector>
|
|
29
29
|
#include "JImageLane.hpp"
|