@iternio/react-native-auto-play 0.6.0 → 0.6.1
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 +56 -7
- package/android/src/main/java/com/margelo/nitro/swe/iternio/reactnativeautoplay/template/Parser.kt +49 -14
- package/jest.js +2 -0
- package/lib/index.web.d.ts +73 -0
- package/lib/index.web.js +72 -1
- package/lib/types/Image.d.ts +6 -1
- package/lib/utils/NitroColor.d.ts +1 -0
- package/lib/utils/NitroColor.js +8 -0
- package/lib/utils/NitroImage.js +1 -1
- package/lib/utils/NitroManeuver.js +1 -3
- package/lib-cjs/AutoPlayHeadlessJsTask.js +16 -0
- package/lib-cjs/Constants.js +9 -0
- package/lib-cjs/components/MapTemplateContext.js +10 -0
- package/lib-cjs/components/SafeAreaInsetsContext.js +21 -0
- package/lib-cjs/components/SafeAreaView.js +22 -0
- package/lib-cjs/components/WindowInformationWrapper.js +20 -0
- package/lib-cjs/hooks/useAndroidAutoTelemetry.js +115 -0
- package/lib-cjs/hooks/useFocusedEffect.js +35 -0
- package/lib-cjs/hooks/useMapTemplate.js +13 -0
- package/lib-cjs/hooks/useSafeAreaInsets.js +9 -0
- package/lib-cjs/hooks/useVoiceInput.js +42 -0
- package/lib-cjs/hybrid/HybridAndroidAutoTelemetry.js +4 -0
- package/lib-cjs/hybrid/HybridAndroidWindowInformation.js +4 -0
- package/lib-cjs/hybrid/HybridAutoPlay.js +5 -0
- package/lib-cjs/hybrid/HybridVoice.js +61 -0
- package/lib-cjs/index.js +76 -0
- package/lib-cjs/index.web.js +98 -0
- package/lib-cjs/scenes/AutoPlayCluster.js +140 -0
- package/lib-cjs/scenes/CarPlayDashboardScene.js +100 -0
- package/lib-cjs/specs/AndroidAutoTelemetry.nitro.js +2 -0
- package/lib-cjs/specs/AndroidAutomotive.nitro.js +16 -0
- package/lib-cjs/specs/AndroidWindowInformation.nitro.js +2 -0
- package/lib-cjs/specs/AutoPlay.nitro.js +2 -0
- package/lib-cjs/specs/CarPlayDashboard.nitro.js +2 -0
- package/lib-cjs/specs/Cluster.nitro.js +2 -0
- package/lib-cjs/specs/GridTemplate.nitro.js +2 -0
- package/lib-cjs/specs/InformationTemplate.nitro.js +2 -0
- package/lib-cjs/specs/ListTemplate.nitro.js +2 -0
- package/lib-cjs/specs/MapTemplate.nitro.js +2 -0
- package/lib-cjs/specs/MessageTemplate.nitro.js +2 -0
- package/lib-cjs/specs/SearchTemplate.nitro.js +2 -0
- package/lib-cjs/specs/SignInTemplate.nitro.js +2 -0
- package/lib-cjs/specs/Voice.nitro.js +2 -0
- package/lib-cjs/templates/GridTemplate.js +41 -0
- package/lib-cjs/templates/InformationTemplate.js +49 -0
- package/lib-cjs/templates/ListTemplate.js +33 -0
- package/lib-cjs/templates/MapTemplate.js +168 -0
- package/lib-cjs/templates/MessageTemplate.js +50 -0
- package/lib-cjs/templates/SearchTemplate.js +32 -0
- package/lib-cjs/templates/SignInTemplate.js +55 -0
- package/lib-cjs/templates/Template.js +40 -0
- package/lib-cjs/types/Button.js +12 -0
- package/lib-cjs/types/Event.js +2 -0
- package/lib-cjs/types/Image.js +2 -0
- package/lib-cjs/types/Maneuver.js +77 -0
- package/lib-cjs/types/RootComponent.js +2 -0
- package/lib-cjs/types/SignInMethod.js +22 -0
- package/lib-cjs/types/Telemetry.js +24 -0
- package/lib-cjs/types/Text.js +8 -0
- package/lib-cjs/types/Trip.js +2 -0
- package/lib-cjs/types/Voice.js +2 -0
- package/lib-cjs/utils/ErrorUtil.js +34 -0
- package/lib-cjs/utils/NitroAction.js +129 -0
- package/lib-cjs/utils/NitroAlert.js +19 -0
- package/lib-cjs/utils/NitroAttributedString.js +14 -0
- package/lib-cjs/utils/NitroColor.js +32 -0
- package/lib-cjs/utils/NitroGrid.js +12 -0
- package/lib-cjs/utils/NitroImage.js +97 -0
- package/lib-cjs/utils/NitroManeuver.js +79 -0
- package/lib-cjs/utils/NitroMapButton.js +33 -0
- package/lib-cjs/utils/NitroOptionsPanel.js +66 -0
- package/lib-cjs/utils/NitroSection.js +112 -0
- package/nitrogen/generated/android/c++/JNitroColor.hpp +8 -4
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/swe/iternio/reactnativeautoplay/NitroColor.kt +9 -4
- package/nitrogen/generated/ios/swift/NitroColor.swift +20 -2
- package/nitrogen/generated/shared/c++/NitroColor.hpp +7 -3
- package/package.json +7 -3
- package/src/index.web.ts +166 -0
- package/src/types/Image.ts +6 -1
- package/src/utils/NitroColor.ts +10 -1
- package/src/utils/NitroImage.ts +1 -5
- package/src/utils/NitroManeuver.ts +1 -4
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NitroOptionsPanelUtil = void 0;
|
|
4
|
+
const NitroAction_1 = require("./NitroAction");
|
|
5
|
+
const NitroGrid_1 = require("./NitroGrid");
|
|
6
|
+
const NitroImage_1 = require("./NitroImage");
|
|
7
|
+
const NitroSection_1 = require("./NitroSection");
|
|
8
|
+
const isRadioSection = (items) => {
|
|
9
|
+
return items.length > 0 && items.every((item) => item.type === 'radio');
|
|
10
|
+
};
|
|
11
|
+
const convertSection = (template, section) => {
|
|
12
|
+
if (section.type === 'grid') {
|
|
13
|
+
return {
|
|
14
|
+
title: section.title,
|
|
15
|
+
buttons: NitroGrid_1.NitroGridUtil.convert(template, section.buttons),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
if (section.type === 'charger') {
|
|
19
|
+
const { location } = section;
|
|
20
|
+
return {
|
|
21
|
+
title: section.title,
|
|
22
|
+
outlets: section.outlets.map((outlet) => ({
|
|
23
|
+
connector: outlet.connector,
|
|
24
|
+
voltage: outlet.voltage,
|
|
25
|
+
powerKw: outlet.powerKw,
|
|
26
|
+
onPress: outlet.onPress ? () => outlet.onPress?.(template) : undefined,
|
|
27
|
+
})),
|
|
28
|
+
location: location
|
|
29
|
+
? {
|
|
30
|
+
name: location.name,
|
|
31
|
+
address: location.address,
|
|
32
|
+
coordinate: location.coordinate,
|
|
33
|
+
distance: location.travelEstimates.distance,
|
|
34
|
+
duration: location.travelEstimates.duration,
|
|
35
|
+
visible: location.travelEstimates.visible,
|
|
36
|
+
image: NitroImage_1.NitroImageUtil.convert(location.image),
|
|
37
|
+
onPress: location.onPress ? () => location.onPress?.(template) : undefined,
|
|
38
|
+
}
|
|
39
|
+
: undefined,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
const { items, title = '' } = section;
|
|
43
|
+
const multiSection = isRadioSection(items)
|
|
44
|
+
? { type: 'radio', title, items }
|
|
45
|
+
: {
|
|
46
|
+
type: 'default',
|
|
47
|
+
title,
|
|
48
|
+
items,
|
|
49
|
+
};
|
|
50
|
+
const [nitroSection] = NitroSection_1.NitroSectionUtil.convert(template, [multiSection]) ?? [];
|
|
51
|
+
if (nitroSection == null) {
|
|
52
|
+
throw new Error('converting sections failed');
|
|
53
|
+
}
|
|
54
|
+
return nitroSection;
|
|
55
|
+
};
|
|
56
|
+
const convert = (template, config) => {
|
|
57
|
+
if (config == null) {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
title: config.title,
|
|
62
|
+
sections: config.sections.map((section) => convertSection(template, section)),
|
|
63
|
+
actions: NitroAction_1.NitroActionUtil.convert(template, config.actions),
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
exports.NitroOptionsPanelUtil = { convert };
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NitroSectionUtil = void 0;
|
|
4
|
+
const Text_1 = require("../types/Text");
|
|
5
|
+
const NitroImage_1 = require("./NitroImage");
|
|
6
|
+
const validateRadioItems = (type, items) => {
|
|
7
|
+
if (__DEV__ &&
|
|
8
|
+
type === 'radio' &&
|
|
9
|
+
(items.filter((item) => item.selected).length > 1 || items.every((item) => !item.selected))) {
|
|
10
|
+
throw new Error('radio lists must have one selected item');
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
const convert = (template, sections) => {
|
|
14
|
+
if (sections == null) {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
if (Array.isArray(sections)) {
|
|
18
|
+
return sections.map((section) => {
|
|
19
|
+
const { title, type } = section;
|
|
20
|
+
const items = section.items.map((item) => convertRow(template, item));
|
|
21
|
+
validateRadioItems(type, items);
|
|
22
|
+
return {
|
|
23
|
+
items,
|
|
24
|
+
type,
|
|
25
|
+
title,
|
|
26
|
+
};
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
const items = sections.items.map((item) => convertRow(template, item));
|
|
30
|
+
validateRadioItems(sections.type, items);
|
|
31
|
+
return [
|
|
32
|
+
{
|
|
33
|
+
items,
|
|
34
|
+
type: sections.type,
|
|
35
|
+
},
|
|
36
|
+
];
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* `AutoText.distance`/`.duration` only take effect if `text` actually uses the matching
|
|
40
|
+
* `TextPlaceholders` marker — populate whichever of those the text references, leaving the rest
|
|
41
|
+
* of `text` untouched, so a title/address that doesn't opt in via a placeholder is unaffected.
|
|
42
|
+
*/
|
|
43
|
+
const withTravelEstimates = (text, distance, durationSeconds) => {
|
|
44
|
+
const hasDistance = text.text.includes(Text_1.TextPlaceholders.Distance);
|
|
45
|
+
const hasDuration = text.text.includes(Text_1.TextPlaceholders.Duration);
|
|
46
|
+
if (!hasDistance && !hasDuration) {
|
|
47
|
+
return text;
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
...text,
|
|
51
|
+
distance: hasDistance ? distance : text.distance,
|
|
52
|
+
duration: hasDuration ? durationSeconds : text.duration,
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
const convertRow = (template, item) => {
|
|
56
|
+
const { type, enabled = true, image, imageType } = item;
|
|
57
|
+
// `WaypointRow` has no `detailedText` of its own — `address` doubles as the detail line
|
|
58
|
+
// whenever this falls back to a plain row (non-panel context, Android).
|
|
59
|
+
let title = item.title;
|
|
60
|
+
let detailedText = item.type === 'waypoint'
|
|
61
|
+
? item.address != null
|
|
62
|
+
? { text: item.address }
|
|
63
|
+
: undefined
|
|
64
|
+
: 'detailedText' in item
|
|
65
|
+
? item.detailedText
|
|
66
|
+
: undefined;
|
|
67
|
+
// Opt-in only: a title/address using `{distance}`/`{duration}` gets those values filled in,
|
|
68
|
+
// via the same substitution `AutoText` already does everywhere else — no separate "estimate"
|
|
69
|
+
// UI element needed for a row embedded in a list alongside other rows. Deliberately NOT gated
|
|
70
|
+
// on `travelEstimates.visible` — that flag only controls the panel-only sibling
|
|
71
|
+
// `CPTravelEstimates` item (see `Parser.swift`'s `travelEstimatesVisible` check), which has no
|
|
72
|
+
// bearing on the non-panel/Android fallback text this feeds; a placeholder in the text is
|
|
73
|
+
// already its own explicit opt-in regardless of `visible`.
|
|
74
|
+
if (item.type === 'waypoint') {
|
|
75
|
+
const { distance, duration } = item.travelEstimates;
|
|
76
|
+
title = withTravelEstimates(title, distance, duration.seconds);
|
|
77
|
+
if (detailedText != null) {
|
|
78
|
+
detailedText = withTravelEstimates(detailedText, distance, duration.seconds);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const selected = type === 'radio' ? (item.selected ?? false) : undefined;
|
|
82
|
+
const onTogglePress = item.type === 'toggle' ? item.onPress : undefined;
|
|
83
|
+
const onRowPress = item.type !== 'text' && item.type !== 'toggle' ? item.onPress : undefined;
|
|
84
|
+
const onPress = item.type === 'text'
|
|
85
|
+
? undefined
|
|
86
|
+
: (checked) => {
|
|
87
|
+
if (onTogglePress != null && checked != null) {
|
|
88
|
+
onTogglePress(template, checked);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (onRowPress != null) {
|
|
92
|
+
onRowPress(template);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
return {
|
|
96
|
+
browsable: type === 'default' ? item.browsable : undefined,
|
|
97
|
+
detailedText,
|
|
98
|
+
enabled,
|
|
99
|
+
image: NitroImage_1.NitroImageUtil.convert(image),
|
|
100
|
+
imageType,
|
|
101
|
+
title,
|
|
102
|
+
checked: type === 'toggle' ? item.checked : undefined,
|
|
103
|
+
onPress,
|
|
104
|
+
selected,
|
|
105
|
+
coordinate: item.type === 'waypoint' ? item.coordinate : undefined,
|
|
106
|
+
distance: item.type === 'waypoint' ? item.travelEstimates.distance : undefined,
|
|
107
|
+
duration: item.type === 'waypoint' ? item.travelEstimates.duration : undefined,
|
|
108
|
+
travelEstimatesVisible: item.type === 'waypoint' ? item.travelEstimates.visible : undefined,
|
|
109
|
+
address: item.type === 'waypoint' ? item.address : undefined,
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
exports.NitroSectionUtil = { convert };
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
#include <fbjni/fbjni.h>
|
|
11
11
|
#include "NitroColor.hpp"
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
#include <optional>
|
|
14
14
|
|
|
15
15
|
namespace margelo::nitro::swe::iternio::reactnativeautoplay {
|
|
16
16
|
|
|
@@ -35,9 +35,12 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay {
|
|
|
35
35
|
double lightColor = this->getFieldValue(fieldLightColor);
|
|
36
36
|
static const auto fieldDarkColor = clazz->getField<double>("darkColor");
|
|
37
37
|
double darkColor = this->getFieldValue(fieldDarkColor);
|
|
38
|
+
static const auto fieldIsDefault = clazz->getField<jni::JBoolean>("isDefault");
|
|
39
|
+
jni::local_ref<jni::JBoolean> isDefault = this->getFieldValue(fieldIsDefault);
|
|
38
40
|
return NitroColor(
|
|
39
41
|
lightColor,
|
|
40
|
-
darkColor
|
|
42
|
+
darkColor,
|
|
43
|
+
isDefault != nullptr ? std::make_optional(static_cast<bool>(isDefault->value())) : std::nullopt
|
|
41
44
|
);
|
|
42
45
|
}
|
|
43
46
|
|
|
@@ -47,13 +50,14 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay {
|
|
|
47
50
|
*/
|
|
48
51
|
[[maybe_unused]]
|
|
49
52
|
static jni::local_ref<JNitroColor::javaobject> fromCpp(const NitroColor& value) {
|
|
50
|
-
using JSignature = JNitroColor(double, double);
|
|
53
|
+
using JSignature = JNitroColor(double, double, jni::alias_ref<jni::JBoolean>);
|
|
51
54
|
static const auto clazz = javaClassStatic();
|
|
52
55
|
static const auto create = clazz->getStaticMethod<JSignature>("fromCpp");
|
|
53
56
|
return create(
|
|
54
57
|
clazz,
|
|
55
58
|
value.lightColor,
|
|
56
|
-
value.darkColor
|
|
59
|
+
value.darkColor,
|
|
60
|
+
value.isDefault.has_value() ? jni::JBoolean::valueOf(value.isDefault.value()) : nullptr
|
|
57
61
|
);
|
|
58
62
|
}
|
|
59
63
|
};
|
|
@@ -23,7 +23,10 @@ data class NitroColor(
|
|
|
23
23
|
val lightColor: Double,
|
|
24
24
|
@DoNotStrip
|
|
25
25
|
@Keep
|
|
26
|
-
val darkColor: Double
|
|
26
|
+
val darkColor: Double,
|
|
27
|
+
@DoNotStrip
|
|
28
|
+
@Keep
|
|
29
|
+
val isDefault: Boolean?
|
|
27
30
|
) {
|
|
28
31
|
/* primary constructor */
|
|
29
32
|
|
|
@@ -32,12 +35,14 @@ data class NitroColor(
|
|
|
32
35
|
if (other !is NitroColor) return false
|
|
33
36
|
return Objects.deepEquals(this.lightColor, other.lightColor)
|
|
34
37
|
&& Objects.deepEquals(this.darkColor, other.darkColor)
|
|
38
|
+
&& Objects.deepEquals(this.isDefault, other.isDefault)
|
|
35
39
|
}
|
|
36
40
|
|
|
37
41
|
override fun hashCode(): Int {
|
|
38
42
|
return arrayOf<Any?>(
|
|
39
43
|
lightColor,
|
|
40
|
-
darkColor
|
|
44
|
+
darkColor,
|
|
45
|
+
isDefault
|
|
41
46
|
).contentDeepHashCode()
|
|
42
47
|
}
|
|
43
48
|
|
|
@@ -49,8 +54,8 @@ data class NitroColor(
|
|
|
49
54
|
@Keep
|
|
50
55
|
@Suppress("unused")
|
|
51
56
|
@JvmStatic
|
|
52
|
-
private fun fromCpp(lightColor: Double, darkColor: Double): NitroColor {
|
|
53
|
-
return NitroColor(lightColor, darkColor)
|
|
57
|
+
private fun fromCpp(lightColor: Double, darkColor: Double, isDefault: Boolean?): NitroColor {
|
|
58
|
+
return NitroColor(lightColor, darkColor, isDefault)
|
|
54
59
|
}
|
|
55
60
|
}
|
|
56
61
|
}
|
|
@@ -18,8 +18,14 @@ public extension NitroColor {
|
|
|
18
18
|
/**
|
|
19
19
|
* Create a new instance of `NitroColor`.
|
|
20
20
|
*/
|
|
21
|
-
init(lightColor: Double, darkColor: Double) {
|
|
22
|
-
self.init(lightColor, darkColor)
|
|
21
|
+
init(lightColor: Double, darkColor: Double, isDefault: Bool?) {
|
|
22
|
+
self.init(lightColor, darkColor, { () -> bridge.std__optional_bool_ in
|
|
23
|
+
if let __unwrappedValue = isDefault {
|
|
24
|
+
return bridge.create_std__optional_bool_(__unwrappedValue)
|
|
25
|
+
} else {
|
|
26
|
+
return .init()
|
|
27
|
+
}
|
|
28
|
+
}())
|
|
23
29
|
}
|
|
24
30
|
|
|
25
31
|
@inline(__always)
|
|
@@ -31,4 +37,16 @@ public extension NitroColor {
|
|
|
31
37
|
var darkColor: Double {
|
|
32
38
|
return self.__darkColor
|
|
33
39
|
}
|
|
40
|
+
|
|
41
|
+
@inline(__always)
|
|
42
|
+
var isDefault: Bool? {
|
|
43
|
+
return { () -> Bool? in
|
|
44
|
+
if bridge.has_value_std__optional_bool_(self.__isDefault) {
|
|
45
|
+
let __unwrapped = bridge.get_std__optional_bool_(self.__isDefault)
|
|
46
|
+
return __unwrapped
|
|
47
|
+
} else {
|
|
48
|
+
return nil
|
|
49
|
+
}
|
|
50
|
+
}()
|
|
51
|
+
}
|
|
34
52
|
}
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
#include <optional>
|
|
34
34
|
|
|
35
35
|
namespace margelo::nitro::swe::iternio::reactnativeautoplay {
|
|
36
36
|
|
|
@@ -41,10 +41,11 @@ namespace margelo::nitro::swe::iternio::reactnativeautoplay {
|
|
|
41
41
|
public:
|
|
42
42
|
double lightColor SWIFT_PRIVATE;
|
|
43
43
|
double darkColor SWIFT_PRIVATE;
|
|
44
|
+
std::optional<bool> isDefault SWIFT_PRIVATE;
|
|
44
45
|
|
|
45
46
|
public:
|
|
46
47
|
NitroColor() = default;
|
|
47
|
-
explicit NitroColor(double lightColor, double darkColor): lightColor(lightColor), darkColor(darkColor) {}
|
|
48
|
+
explicit NitroColor(double lightColor, double darkColor, std::optional<bool> isDefault): lightColor(lightColor), darkColor(darkColor), isDefault(isDefault) {}
|
|
48
49
|
|
|
49
50
|
public:
|
|
50
51
|
friend bool operator==(const NitroColor& lhs, const NitroColor& rhs) = default;
|
|
@@ -61,13 +62,15 @@ namespace margelo::nitro {
|
|
|
61
62
|
jsi::Object obj = arg.asObject(runtime);
|
|
62
63
|
return margelo::nitro::swe::iternio::reactnativeautoplay::NitroColor(
|
|
63
64
|
JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "lightColor"))),
|
|
64
|
-
JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "darkColor")))
|
|
65
|
+
JSIConverter<double>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "darkColor"))),
|
|
66
|
+
JSIConverter<std::optional<bool>>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "isDefault")))
|
|
65
67
|
);
|
|
66
68
|
}
|
|
67
69
|
static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::swe::iternio::reactnativeautoplay::NitroColor& arg) {
|
|
68
70
|
jsi::Object obj(runtime);
|
|
69
71
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "lightColor"), JSIConverter<double>::toJSI(runtime, arg.lightColor));
|
|
70
72
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "darkColor"), JSIConverter<double>::toJSI(runtime, arg.darkColor));
|
|
73
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "isDefault"), JSIConverter<std::optional<bool>>::toJSI(runtime, arg.isDefault));
|
|
71
74
|
return obj;
|
|
72
75
|
}
|
|
73
76
|
static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
|
|
@@ -80,6 +83,7 @@ namespace margelo::nitro {
|
|
|
80
83
|
}
|
|
81
84
|
if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "lightColor")))) return false;
|
|
82
85
|
if (!JSIConverter<double>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "darkColor")))) return false;
|
|
86
|
+
if (!JSIConverter<std::optional<bool>>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "isDefault")))) return false;
|
|
83
87
|
return true;
|
|
84
88
|
}
|
|
85
89
|
};
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iternio/react-native-auto-play",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Android Auto and Apple CarPlay for react-native",
|
|
5
5
|
"main": "lib/index",
|
|
6
6
|
"module": "lib/index",
|
|
7
|
+
"browser": "lib/index.web",
|
|
7
8
|
"types": "lib/index.d.ts",
|
|
8
9
|
"react-native": "src/index",
|
|
9
10
|
"source": "src/index",
|
|
@@ -11,6 +12,8 @@
|
|
|
11
12
|
"src",
|
|
12
13
|
"react-native.config.js",
|
|
13
14
|
"lib",
|
|
15
|
+
"lib-cjs",
|
|
16
|
+
"jest.js",
|
|
14
17
|
"nitrogen",
|
|
15
18
|
"android/build.gradle",
|
|
16
19
|
"android/gradle.properties",
|
|
@@ -30,12 +33,13 @@
|
|
|
30
33
|
],
|
|
31
34
|
"scripts": {
|
|
32
35
|
"typecheck": "tsc --noEmit",
|
|
33
|
-
"clean": "rm -rf android/build node_modules/**/android/build lib",
|
|
36
|
+
"clean": "rm -rf android/build node_modules/**/android/build lib lib-cjs",
|
|
34
37
|
"lint": "biome check src",
|
|
35
38
|
"lint-ci": "biome ci src --reporter=summary",
|
|
36
39
|
"typescript": "tsc",
|
|
40
|
+
"build:jest": "tsc -p tsconfig.jest.json",
|
|
37
41
|
"specs": "nitrogen --logLevel=\"debug\"",
|
|
38
|
-
"prepare": "yarn circular && tsc && nitrogen",
|
|
42
|
+
"prepare": "yarn circular && tsc && yarn build:jest && nitrogen",
|
|
39
43
|
"swift:format": "swift-format format ./ios --in-place --recursive",
|
|
40
44
|
"circular": "dpdm ./src/* --circular --exit-code circular:1 --no-tree --warning=false --transform"
|
|
41
45
|
},
|
package/src/index.web.ts
CHANGED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
// Web/Jest stub for the native CarPlay/Android Auto surface. Nothing here talks to a real native
|
|
2
|
+
// module — every function call resolves to `undefined` (or an already-resolved promise, which is
|
|
3
|
+
// indistinguishable from `undefined` to an `await`er) rather than throwing. Types are preserved by
|
|
4
|
+
// casting against the real exports, so callers still get full type-checking/autocomplete.
|
|
5
|
+
//
|
|
6
|
+
// Anything below that's already safe as-is (pure types, plain enums, or modules that neither
|
|
7
|
+
// create native objects nor import anything that does) is re-exported directly instead of stubbed.
|
|
8
|
+
|
|
9
|
+
import { createElement } from 'react';
|
|
10
|
+
import { View, type ViewProps } from 'react-native';
|
|
11
|
+
import type { AndroidAutomotive } from './specs/AndroidAutomotive.nitro';
|
|
12
|
+
import type { AutoPlay } from './specs/AutoPlay.nitro';
|
|
13
|
+
import type { Voice } from './specs/Voice.nitro';
|
|
14
|
+
import type { GridTemplate as RealGridTemplate } from './templates/GridTemplate';
|
|
15
|
+
import type { InformationTemplate as RealInformationTemplate } from './templates/InformationTemplate';
|
|
16
|
+
import type { ListTemplate as RealListTemplate } from './templates/ListTemplate';
|
|
17
|
+
import type { MapTemplate as RealMapTemplate } from './templates/MapTemplate';
|
|
18
|
+
import type { MessageTemplate as RealMessageTemplate } from './templates/MessageTemplate';
|
|
19
|
+
import type { SearchTemplate as RealSearchTemplate } from './templates/SearchTemplate';
|
|
20
|
+
import type { SignInTemplate as RealSignInTemplate } from './templates/SignInTemplate';
|
|
21
|
+
import type { Template as RealTemplate } from './templates/Template';
|
|
22
|
+
import type { SafeAreaInsets } from './types/Event';
|
|
23
|
+
import type { Telemetry } from './types/Telemetry';
|
|
24
|
+
|
|
25
|
+
function noop() {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Any property access returns a no-op function, so any method call is safe regardless of name. */
|
|
30
|
+
function createNoopObject<T>(): T {
|
|
31
|
+
return new Proxy(
|
|
32
|
+
{},
|
|
33
|
+
{
|
|
34
|
+
get: (_target, prop) => (prop === 'then' || prop === 'toJSON' ? undefined : noop),
|
|
35
|
+
}
|
|
36
|
+
) as T;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function createNoopClass<T>(): new (...args: never[]) => T {
|
|
40
|
+
function NoopInstance() {
|
|
41
|
+
return createNoopObject<T>();
|
|
42
|
+
}
|
|
43
|
+
return NoopInstance as unknown as new (
|
|
44
|
+
...args: never[]
|
|
45
|
+
) => T;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export * from './Constants';
|
|
49
|
+
export * from './hooks/useMapTemplate';
|
|
50
|
+
export type {
|
|
51
|
+
ActiveCarUxRestrictions,
|
|
52
|
+
AppFocusState,
|
|
53
|
+
} from './specs/AndroidAutomotive.nitro';
|
|
54
|
+
export { CarUxRestrictions } from './specs/AndroidAutomotive.nitro';
|
|
55
|
+
export type { GridImageSize, GridTemplateConfig } from './templates/GridTemplate';
|
|
56
|
+
export type { InformationItems, InformationTemplateConfig } from './templates/InformationTemplate';
|
|
57
|
+
export type {
|
|
58
|
+
DefaultRow,
|
|
59
|
+
ListImageType,
|
|
60
|
+
ListTemplateConfig,
|
|
61
|
+
MultiSection,
|
|
62
|
+
RadioRow,
|
|
63
|
+
Section,
|
|
64
|
+
SingleSection,
|
|
65
|
+
TextRow,
|
|
66
|
+
ToggleRow,
|
|
67
|
+
WaypointCoordinate,
|
|
68
|
+
WaypointRow,
|
|
69
|
+
} from './templates/ListTemplate';
|
|
70
|
+
export type {
|
|
71
|
+
BaseMapTemplateConfig,
|
|
72
|
+
ChargerLocation,
|
|
73
|
+
ChargerOutlet,
|
|
74
|
+
ChargingConnector,
|
|
75
|
+
HeaderActionsAndroidMap,
|
|
76
|
+
MapButtons,
|
|
77
|
+
MapHeaderActions,
|
|
78
|
+
MapTemplateConfig,
|
|
79
|
+
OptionsPanelChargerSection,
|
|
80
|
+
OptionsPanelConfig,
|
|
81
|
+
OptionsPanelGridSection,
|
|
82
|
+
OptionsPanelListSection,
|
|
83
|
+
OptionsPanelSection,
|
|
84
|
+
PanelActionsIos,
|
|
85
|
+
PanelHeaderActions,
|
|
86
|
+
Point,
|
|
87
|
+
TripSelectorCallback,
|
|
88
|
+
VisibleTravelEstimate,
|
|
89
|
+
} from './templates/MapTemplate';
|
|
90
|
+
export type { MessageTemplateConfig } from './templates/MessageTemplate';
|
|
91
|
+
export type { SearchSection, SearchTemplateConfig } from './templates/SearchTemplate';
|
|
92
|
+
export type { SignInTemplateConfig } from './templates/SignInTemplate';
|
|
93
|
+
export type {
|
|
94
|
+
ActionButton,
|
|
95
|
+
HeaderActions,
|
|
96
|
+
HeaderActionsAndroid,
|
|
97
|
+
HeaderActionsIos,
|
|
98
|
+
NitroBaseMapTemplateConfig,
|
|
99
|
+
NitroTemplateConfig,
|
|
100
|
+
TemplateConfig,
|
|
101
|
+
} from './templates/Template';
|
|
102
|
+
export * from './types/Button';
|
|
103
|
+
export * from './types/Event';
|
|
104
|
+
export * from './types/Image';
|
|
105
|
+
export * from './types/Maneuver';
|
|
106
|
+
export * from './types/RootComponent';
|
|
107
|
+
export * from './types/SignInMethod';
|
|
108
|
+
export * from './types/Telemetry';
|
|
109
|
+
export * from './types/Text';
|
|
110
|
+
export * from './types/Trip';
|
|
111
|
+
export type { VoiceInputChunk, VoiceInputOptions, VoiceInputResult } from './types/Voice';
|
|
112
|
+
export * from './utils/ErrorUtil';
|
|
113
|
+
export type {
|
|
114
|
+
AlertPriority,
|
|
115
|
+
NavigationAlert as Alert,
|
|
116
|
+
NavigationAlertAction as AlertAction,
|
|
117
|
+
} from './utils/NitroAlert';
|
|
118
|
+
export type { ThemedColor } from './utils/NitroColor';
|
|
119
|
+
export type { GridButton } from './utils/NitroGrid';
|
|
120
|
+
|
|
121
|
+
export enum AutoPlayModules {
|
|
122
|
+
App = 'main',
|
|
123
|
+
AutoPlayRoot = 'AutoPlayRoot',
|
|
124
|
+
CarPlayDashboard = 'CarPlayDashboard',
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const NO_INSETS: SafeAreaInsets = { top: 0, bottom: 0, left: 0, right: 0 };
|
|
128
|
+
export const useSafeAreaInsets = () => NO_INSETS;
|
|
129
|
+
export const SafeAreaView = (props: ViewProps) => createElement(View, props);
|
|
130
|
+
|
|
131
|
+
export function setIconFont(_name: string, _glyphMap?: Record<string, number>): void {}
|
|
132
|
+
|
|
133
|
+
export const useFocusedEffect = () => {};
|
|
134
|
+
|
|
135
|
+
export const useVoiceInput = () => ({
|
|
136
|
+
voiceInputResult: undefined,
|
|
137
|
+
resetVoiceInputResult: () => {},
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
export const useAndroidAutoTelemetry = (): {
|
|
141
|
+
permissionsGranted: boolean | null;
|
|
142
|
+
telemetry: Telemetry | undefined;
|
|
143
|
+
error: string | undefined;
|
|
144
|
+
} => ({
|
|
145
|
+
permissionsGranted: null,
|
|
146
|
+
telemetry: undefined,
|
|
147
|
+
error: undefined,
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
export const AutoPlayCluster = createNoopObject<Record<string, unknown>>();
|
|
151
|
+
export const CarPlayDashboard = createNoopObject<Record<string, unknown>>();
|
|
152
|
+
|
|
153
|
+
export const HybridAndroidAutomotive: AndroidAutomotive | null = null;
|
|
154
|
+
export { HybridAndroidAutoTelemetry } from './hybrid/HybridAndroidAutoTelemetry';
|
|
155
|
+
export { HybridAndroidWindowInformation } from './hybrid/HybridAndroidWindowInformation';
|
|
156
|
+
export const HybridAutoPlay = createNoopObject<AutoPlay>();
|
|
157
|
+
export const HybridVoice = createNoopObject<Voice>();
|
|
158
|
+
|
|
159
|
+
export const Template = createNoopClass<InstanceType<typeof RealTemplate>>();
|
|
160
|
+
export const ListTemplate = createNoopClass<RealListTemplate>();
|
|
161
|
+
export const GridTemplate = createNoopClass<RealGridTemplate>();
|
|
162
|
+
export const InformationTemplate = createNoopClass<RealInformationTemplate>();
|
|
163
|
+
export const MessageTemplate = createNoopClass<RealMessageTemplate>();
|
|
164
|
+
export const MapTemplate = createNoopClass<RealMapTemplate>();
|
|
165
|
+
export const SearchTemplate = createNoopClass<RealSearchTemplate>();
|
|
166
|
+
export const SignInTemplate = createNoopClass<RealSignInTemplate>();
|
package/src/types/Image.ts
CHANGED
|
@@ -24,7 +24,8 @@ export type GlyphMapKey = keyof AutoPlayGlyphMap extends never
|
|
|
24
24
|
type GlyphStyleFields = {
|
|
25
25
|
/**
|
|
26
26
|
* Sets the icon dark and light mode color or a single color for both.
|
|
27
|
-
* Defaults to white for dark mode and black for light mode
|
|
27
|
+
* Defaults to `'default'` if not specified, which is white for dark mode and black for light mode.
|
|
28
|
+
* On Android Auto the host tint that follows the template is not applied when `backgroundColor` is not transparent.
|
|
28
29
|
* Might not get applied everywhere like MapTemplate buttons on Android.
|
|
29
30
|
*/
|
|
30
31
|
color?: ThemedColor | string;
|
|
@@ -61,6 +62,8 @@ export type AutoImage =
|
|
|
61
62
|
/**
|
|
62
63
|
* if specified the image gets tinted, if not it will just use the original image
|
|
63
64
|
* Might not get applied everywhere like MapTemplate buttons on Android.
|
|
65
|
+
* Use `'default'` for monochrome icons that must stay readable on both dark and light
|
|
66
|
+
* Android Auto templates (17.8+), see README.
|
|
64
67
|
*/
|
|
65
68
|
color?: ThemedColor | string;
|
|
66
69
|
type: 'asset';
|
|
@@ -70,6 +73,8 @@ export type AutoImage =
|
|
|
70
73
|
uri: string;
|
|
71
74
|
/**
|
|
72
75
|
* if specified the image gets tinted, if not it will just use the original image
|
|
76
|
+
* Use `'default'` for monochrome icons that must stay readable on both dark and light
|
|
77
|
+
* Android Auto templates (17.8+), see README.
|
|
73
78
|
*/
|
|
74
79
|
color?: ThemedColor | string;
|
|
75
80
|
/**
|
package/src/utils/NitroColor.ts
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { processColor } from 'react-native';
|
|
2
2
|
|
|
3
|
-
export type NitroColor = { lightColor: number; darkColor: number };
|
|
3
|
+
export type NitroColor = { lightColor: number; darkColor: number; isDefault?: boolean };
|
|
4
4
|
export type ThemedColor = { lightColor: string; darkColor: string };
|
|
5
5
|
|
|
6
|
+
const DefaultNitroColor = {
|
|
7
|
+
darkColor: convertColor('white'),
|
|
8
|
+
lightColor: convertColor('black'),
|
|
9
|
+
isDefault: true,
|
|
10
|
+
};
|
|
11
|
+
|
|
6
12
|
function convertColor(color: string): number;
|
|
7
13
|
function convertColor(color?: string): number | undefined;
|
|
8
14
|
function convertColor(color?: string): number | undefined {
|
|
@@ -18,6 +24,9 @@ function convert(color?: ThemedColor | string): NitroColor | undefined {
|
|
|
18
24
|
}
|
|
19
25
|
|
|
20
26
|
if (typeof color === 'string') {
|
|
27
|
+
if (color === 'default') {
|
|
28
|
+
return DefaultNitroColor;
|
|
29
|
+
}
|
|
21
30
|
const convertedColor = convertColor(color);
|
|
22
31
|
return { darkColor: convertedColor, lightColor: convertedColor };
|
|
23
32
|
}
|
package/src/utils/NitroImage.ts
CHANGED
|
@@ -96,11 +96,7 @@ function convert(image?: AutoImage): NitroImage | undefined {
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
if (image.type === 'glyph') {
|
|
99
|
-
const {
|
|
100
|
-
color = { darkColor: 'white', lightColor: 'black' },
|
|
101
|
-
fontScale,
|
|
102
|
-
backgroundColor = 'transparent',
|
|
103
|
-
} = image;
|
|
99
|
+
const { color = 'default', fontScale, backgroundColor = 'transparent' } = image;
|
|
104
100
|
|
|
105
101
|
return {
|
|
106
102
|
glyph: resolveGlyph(image),
|
|
@@ -71,10 +71,7 @@ function convertManeuverImage(image?: ManeuverImage): NitroImage | undefined {
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
if (image.type === 'glyph') {
|
|
74
|
-
const color =
|
|
75
|
-
typeof image.color === 'string'
|
|
76
|
-
? image.color
|
|
77
|
-
: (image.color ?? { darkColor: 'white', lightColor: 'black' });
|
|
74
|
+
const color = typeof image.color === 'string' ? image.color : (image.color ?? 'default');
|
|
78
75
|
return NitroImageUtil.convert({
|
|
79
76
|
...image,
|
|
80
77
|
color: color,
|