craft-native 0.0.238 → 0.0.241
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/dist/android/src/index.d.ts +17 -1
- package/dist/android/src/index.js +83 -6
- package/dist/android/src/native-map.d.ts +7 -0
- package/dist/android/templates/CraftBridge.kt.template +2 -1
- package/dist/android/templates/CraftNativeMapGoogle.kt.template +440 -0
- package/dist/android/templates/CraftNativeMapLibre.kt.template +438 -0
- package/dist/android/templates/CraftNativeMessagingService.kt.template +3 -1
- package/dist/android/templates/CraftNativeNotificationReceiver.kt.template +2 -1
- package/dist/android/templates/LocationRecordingService.kt.template +3 -1
- package/dist/android/templates/MainActivityNative.kt.template +7 -428
- package/dist/android/templates/build.gradle.kts.app.template +1 -1
- package/dist/android/templates/build.gradle.kts.project.template +1 -1
- package/dist/cli.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/ios/src/index.js +8 -0
- package/dist/ios/src/testing.d.ts +14 -2
- package/dist/ios/templates/CraftApp.swift +43 -6
- package/dist/ios/templates/CraftNativeScreen.swift +71 -13
- package/dist/ios/templates/testing/DriverTests.swift.template +37 -0
- package/dist/macos/templates/native_layout.zig +41 -5
- package/package.json +1 -1
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Generates Android apps with native Craft components and optional WebView content.
|
|
5
5
|
*/
|
|
6
|
+
import { type AndroidMapProvider } from './native-map.js';
|
|
7
|
+
export type { AndroidMapProvider } from './native-map.js';
|
|
8
|
+
/** Providers this published builder can generate as real Android map views. */
|
|
9
|
+
export declare const nativeMapProviders: readonly ['google', 'maplibre'];
|
|
6
10
|
export { runKotlinFixture } from './testing.js';
|
|
7
11
|
export { createAndroidEmulator } from './emulator.js';
|
|
8
12
|
export type { AndroidEmulatorOptions, AndroidEmulatorSession } from './emulator.js';
|
|
@@ -71,8 +75,20 @@ export interface CraftAndroidConfig {
|
|
|
71
75
|
}>;
|
|
72
76
|
trustedOrigins?: string[];
|
|
73
77
|
appIconPath?: string;
|
|
78
|
+
/**
|
|
79
|
+
* The small icon in the status bar and on every notification the app
|
|
80
|
+
* shows, push or local: an Android vector drawable (`.xml`) or a `.png`,
|
|
81
|
+
* white on transparent, since Android draws only its shape. Without one,
|
|
82
|
+
* a white Craft mark. Never the launcher icon, which shows as a white
|
|
83
|
+
* square.
|
|
84
|
+
*/
|
|
85
|
+
notificationIconPath?: string;
|
|
86
|
+
/** The `#RRGGBB` Android tints the notification icon and app name with. The system's own colour without it. */
|
|
87
|
+
notificationColor?: string;
|
|
74
88
|
googleServicesFile?: string;
|
|
75
|
-
/**
|
|
89
|
+
/** Native map renderer. MapLibre needs no SDK key; Google remains the default for compatibility. */
|
|
90
|
+
mapProvider?: AndroidMapProvider;
|
|
91
|
+
/** Google Maps Android SDK key, used only by the Google native map host. */
|
|
76
92
|
mapsApiKey?: string;
|
|
77
93
|
devServerURL?: string;
|
|
78
94
|
hasBundledFallback?: boolean;
|
|
@@ -4,6 +4,48 @@ import { cpSync, existsSync, mkdirSync as mkdirSync2, readFileSync as readFileSy
|
|
|
4
4
|
import { dirname as dirname2, extname, isAbsolute as isAbsolute2, join as join3, relative, resolve as resolve2, sep } from "path";
|
|
5
5
|
var {$ } = globalThis.Bun;
|
|
6
6
|
|
|
7
|
+
// ../android/src/native-map.ts
|
|
8
|
+
function androidMapHost(provider = "google") {
|
|
9
|
+
if (provider === "google")
|
|
10
|
+
return {
|
|
11
|
+
template: "CraftNativeMapGoogle.kt.template",
|
|
12
|
+
imports: `import com.google.android.gms.maps.CameraUpdateFactory
|
|
13
|
+
import com.google.android.gms.maps.GoogleMap
|
|
14
|
+
import com.google.android.gms.maps.MapView
|
|
15
|
+
import com.google.android.gms.maps.OnMapReadyCallback
|
|
16
|
+
import com.google.android.gms.maps.model.BitmapDescriptorFactory
|
|
17
|
+
import com.google.android.gms.maps.model.LatLng
|
|
18
|
+
import com.google.android.gms.maps.model.LatLngBounds
|
|
19
|
+
import com.google.android.gms.maps.model.Marker
|
|
20
|
+
import com.google.android.gms.maps.model.MarkerOptions
|
|
21
|
+
import com.google.android.gms.maps.model.Polyline
|
|
22
|
+
import com.google.android.gms.maps.model.PolylineOptions`,
|
|
23
|
+
dependency: "com.google.android.gms:play-services-maps:18.2.0"
|
|
24
|
+
};
|
|
25
|
+
if (provider === "maplibre")
|
|
26
|
+
return {
|
|
27
|
+
template: "CraftNativeMapLibre.kt.template",
|
|
28
|
+
imports: `import org.maplibre.android.MapLibre
|
|
29
|
+
import org.maplibre.android.camera.CameraPosition
|
|
30
|
+
import org.maplibre.android.camera.CameraUpdateFactory
|
|
31
|
+
import org.maplibre.android.geometry.LatLng
|
|
32
|
+
import org.maplibre.android.geometry.LatLngBounds
|
|
33
|
+
import org.maplibre.android.location.LocationComponentActivationOptions
|
|
34
|
+
import org.maplibre.android.maps.MapLibreMap
|
|
35
|
+
import org.maplibre.android.maps.MapView
|
|
36
|
+
import org.maplibre.android.maps.OnMapReadyCallback
|
|
37
|
+
import org.maplibre.android.maps.Style
|
|
38
|
+
import org.maplibre.android.style.expressions.Expression
|
|
39
|
+
import org.maplibre.android.style.layers.CircleLayer
|
|
40
|
+
import org.maplibre.android.style.layers.LineLayer
|
|
41
|
+
import org.maplibre.android.style.layers.SymbolLayer
|
|
42
|
+
import org.maplibre.android.style.layers.PropertyFactory.*
|
|
43
|
+
import org.maplibre.android.style.sources.GeoJsonSource`,
|
|
44
|
+
dependency: "org.maplibre.gl:android-sdk:13.7.1"
|
|
45
|
+
};
|
|
46
|
+
throw new Error(`Unknown Android native map provider: ${provider}. Expected google or maplibre.`);
|
|
47
|
+
}
|
|
48
|
+
|
|
7
49
|
// ../android/src/promise-runtime.ts
|
|
8
50
|
var ANDROID_PROMISE_RUNTIME = `
|
|
9
51
|
if (window.__craftRejectPendingPromises) {
|
|
@@ -315,6 +357,7 @@ async function createAndroidEmulator(options) {
|
|
|
315
357
|
}
|
|
316
358
|
|
|
317
359
|
// ../android/src/index.ts
|
|
360
|
+
var nativeMapProviders = ["google", "maplibre"];
|
|
318
361
|
function syncNativeFonts(fonts, output) {
|
|
319
362
|
const destination = join3(output, "app/src/main/assets/NativeFonts");
|
|
320
363
|
const names = new Set;
|
|
@@ -549,6 +592,7 @@ function normalizeAndroidNetworkConfig(config) {
|
|
|
549
592
|
config.trustedOrigins = [...new Set(trustedOrigins)];
|
|
550
593
|
}
|
|
551
594
|
function validateAndroidConfig(config) {
|
|
595
|
+
androidMapHost(config.mapProvider);
|
|
552
596
|
if (!config.appName.trim())
|
|
553
597
|
throw new Error("Android app name must not be empty");
|
|
554
598
|
if (config.renderer !== undefined && config.renderer !== "web" && config.renderer !== "native") {
|
|
@@ -682,6 +726,7 @@ function writeAndroidConfig(output, config) {
|
|
|
682
726
|
writeFileSync(join3(output, "craft.config.json"), JSON.stringify(config, null, 2));
|
|
683
727
|
const runtimeConfig = { ...config };
|
|
684
728
|
delete runtimeConfig.appIconPath;
|
|
729
|
+
delete runtimeConfig.notificationIconPath;
|
|
685
730
|
delete runtimeConfig.googleServicesFile;
|
|
686
731
|
writeFileSync(join3(output, "app/src/main/assets/craft.config.json"), JSON.stringify(runtimeConfig, null, 2));
|
|
687
732
|
}
|
|
@@ -802,7 +847,9 @@ function renderNativeShellManifest(config) {
|
|
|
802
847
|
<intent-filter>
|
|
803
848
|
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
|
804
849
|
</intent-filter>
|
|
805
|
-
</service
|
|
850
|
+
</service>
|
|
851
|
+
<meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/craft_notification_icon" />${config.notificationColor ? `
|
|
852
|
+
<meta-data android:name="com.google.firebase.messaging.default_notification_color" android:resource="@color/craft_notification_color" />` : ""}`);
|
|
806
853
|
}
|
|
807
854
|
if (config.enableHealthConnect) {
|
|
808
855
|
parts.push(` <activity-alias
|
|
@@ -912,6 +959,18 @@ async function init(options) {
|
|
|
912
959
|
if (config.appIconPath && ![".gif", ".jpg", ".png", ".webp"].includes(appIconExtension ?? "")) {
|
|
913
960
|
throw new Error(`Unsupported Android app icon format: ${appIconExtension || "(none)"}`);
|
|
914
961
|
}
|
|
962
|
+
if (config.notificationIconPath)
|
|
963
|
+
requireRegularFile(config.notificationIconPath, "Notification icon");
|
|
964
|
+
const notificationIconExtension = config.notificationIconPath ? extname(config.notificationIconPath).toLowerCase() : undefined;
|
|
965
|
+
if (config.notificationIconPath && ![".png", ".xml"].includes(notificationIconExtension ?? "")) {
|
|
966
|
+
throw new Error(`Unsupported Android notification icon format: ${notificationIconExtension || "(none)"} (use a vector drawable .xml or a white-on-transparent .png)`);
|
|
967
|
+
}
|
|
968
|
+
if (config.notificationIconPath && notificationIconExtension === ".xml" && !/<vector[\s>]/.test(readFileSync2(config.notificationIconPath, "utf8"))) {
|
|
969
|
+
throw new Error("Notification icon .xml must be an Android vector drawable (<vector>)");
|
|
970
|
+
}
|
|
971
|
+
if (config.notificationColor !== undefined && !/^#[0-9a-f]{6}$/i.test(config.notificationColor)) {
|
|
972
|
+
throw new Error(`notificationColor must be #RRGGBB, not ${String(config.notificationColor)}`);
|
|
973
|
+
}
|
|
915
974
|
const dirs = [
|
|
916
975
|
output,
|
|
917
976
|
join3(output, "app/src/main/java", packagePath),
|
|
@@ -936,7 +995,7 @@ async function init(options) {
|
|
|
936
995
|
cpSync(config.googleServicesFile, join3(output, "app/google-services.json"));
|
|
937
996
|
}
|
|
938
997
|
const mainActivityTemplate = readFileSync2(join3(TEMPLATES_DIR, config.renderer === "native" ? "MainActivityNative.kt.template" : "MainActivity.kt.template"), "utf-8");
|
|
939
|
-
const mainActivity = mainActivityTemplate.replace(/\{\{PACKAGE_NAME\}\}/g, finalPackageName).replace(/\{\{APP_NAME\}\}/g, name);
|
|
998
|
+
const mainActivity = mainActivityTemplate.replace(/\{\{NATIVE_MAP_IMPORTS\}\}/g, () => androidMapHost(config.mapProvider).imports).replace(/\{\{NATIVE_MAP_HOST\}\}/g, () => readFileSync2(join3(TEMPLATES_DIR, androidMapHost(config.mapProvider).template), "utf8")).replace(/\{\{PACKAGE_NAME\}\}/g, finalPackageName).replace(/\{\{APP_NAME\}\}/g, name);
|
|
940
999
|
writeFileSync(join3(output, "app/src/main/java", packagePath, "MainActivity.kt"), mainActivity);
|
|
941
1000
|
writeFileSync(join3(output, "app/src/main/java", packagePath, "CraftAppLinks.kt"), readFileSync2(join3(TEMPLATES_DIR, "CraftAppLinks.kt.template"), "utf8").replace(/\{\{PACKAGE_NAME\}\}/g, finalPackageName));
|
|
942
1001
|
writeFileSync(join3(output, "app/src/main/java", packagePath, "CraftCrashReporter.kt"), readFileSync2(join3(TEMPLATES_DIR, "CraftCrashReporter.kt.template"), "utf-8").replace(/\{\{PACKAGE_NAME\}\}/g, finalPackageName).replace(/\{\{CRAFT_VERSION\}\}/g, CRAFT_ANDROID_VERSION));
|
|
@@ -979,11 +1038,11 @@ async function init(options) {
|
|
|
979
1038
|
mkdirSync2(nativeDir, { recursive: true });
|
|
980
1039
|
writeFileSync(join3(nativeDir, "CraftNative.kt"), craftNative);
|
|
981
1040
|
const serviceTemplate = readFileSync2(join3(TEMPLATES_DIR, "LocationRecordingService.kt.template"), "utf-8");
|
|
982
|
-
writeFileSync(join3(nativeDir, "LocationRecordingService.kt"), serviceTemplate);
|
|
1041
|
+
writeFileSync(join3(nativeDir, "LocationRecordingService.kt"), serviceTemplate.replace(/\{\{PACKAGE_NAME\}\}/g, finalPackageName));
|
|
983
1042
|
const healthTemplate = readFileSync2(join3(TEMPLATES_DIR, config.enableHealthConnect ? "CraftHealthConnect.kt.template" : "CraftHealthConnectStub.kt.template"), "utf-8");
|
|
984
1043
|
writeFileSync(join3(output, "app/src/main/java", packagePath, "CraftHealthConnect.kt"), healthTemplate.replace(/\{\{PACKAGE_NAME\}\}/g, finalPackageName));
|
|
985
1044
|
const manifestTemplate = readFileSync2(join3(TEMPLATES_DIR, "AndroidManifest.xml.template"), "utf-8");
|
|
986
|
-
const manifest = manifestTemplate.replace(/\{\{PACKAGE_NAME\}\}/g, finalPackageName).replace(/\{\{APP_NAME\}\}/g, name).replace(/\{\{PERMISSIONS\}\}/g, renderAndroidPermissions(config)).replace(/\{\{USES_CLEARTEXT\}\}/g, config.devServerURL?.startsWith("http://") || config.enableLocalNetwork ? "true" : "false").replace(/\{\{DEEP_LINK_INTENT_FILTERS\}\}/g, renderAndroidDeepLinks(config)).replace(/\{\{BACKGROUND_SERVICE\}\}/g, config.enableBackgroundLocation ? ' <service android:name="com.craft.runtime.LocationRecordingService" android:exported="false" android:foregroundServiceType="location" android:stopWithTask="false" />' : "").replace(/\{\{NATIVE_NOTIFICATION_RECEIVER\}\}/g, config.renderer === "native" ? renderNativeShellManifest(config) : "").replace(/\{\{CRASH_REPORTER_PROVIDER\}\}/g, ` <provider android:name=".CraftCrashReporterInit" android:authorities="\${applicationId}.craft-crash" android:exported="false" android:initOrder="1000" />`).replace(/\{\{GOOGLE_MAPS_API_KEY\}\}/g, config.mapsApiKey ? ` <meta-data android:name="com.google.android.geo.API_KEY" android:value="${escapeXml(config.mapsApiKey)}" />` : "").replace(/\{\{HEALTH_CONNECT_QUERIES\}\}/g, config.enableHealthConnect ? ` <queries>
|
|
1045
|
+
const manifest = manifestTemplate.replace(/\{\{PACKAGE_NAME\}\}/g, finalPackageName).replace(/\{\{APP_NAME\}\}/g, name).replace(/\{\{PERMISSIONS\}\}/g, renderAndroidPermissions(config)).replace(/\{\{USES_CLEARTEXT\}\}/g, config.devServerURL?.startsWith("http://") || config.enableLocalNetwork ? "true" : "false").replace(/\{\{DEEP_LINK_INTENT_FILTERS\}\}/g, renderAndroidDeepLinks(config)).replace(/\{\{BACKGROUND_SERVICE\}\}/g, config.enableBackgroundLocation ? ' <service android:name="com.craft.runtime.LocationRecordingService" android:exported="false" android:foregroundServiceType="location" android:stopWithTask="false" />' : "").replace(/\{\{NATIVE_NOTIFICATION_RECEIVER\}\}/g, config.renderer === "native" ? renderNativeShellManifest(config) : "").replace(/\{\{CRASH_REPORTER_PROVIDER\}\}/g, ` <provider android:name=".CraftCrashReporterInit" android:authorities="\${applicationId}.craft-crash" android:exported="false" android:initOrder="1000" />`).replace(/\{\{GOOGLE_MAPS_API_KEY\}\}/g, config.mapProvider !== "maplibre" && config.mapsApiKey ? ` <meta-data android:name="com.google.android.geo.API_KEY" android:value="${escapeXml(config.mapsApiKey)}" />` : "").replace(/\{\{HEALTH_CONNECT_QUERIES\}\}/g, config.enableHealthConnect ? ` <queries>
|
|
987
1046
|
<package android:name="com.google.android.apps.healthdata" />
|
|
988
1047
|
</queries>` : "").replace(/\{\{HEALTH_CONNECT_RATIONALE\}\}/g, config.enableHealthConnect ? ` <intent-filter>
|
|
989
1048
|
<action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE" />
|
|
@@ -996,8 +1055,8 @@ async function init(options) {
|
|
|
996
1055
|
const projectGradleTemplate = readFileSync2(join3(TEMPLATES_DIR, "build.gradle.kts.project.template"), "utf-8");
|
|
997
1056
|
writeFileSync(join3(output, "build.gradle.kts"), projectGradleTemplate.replace(/\{\{GOOGLE_SERVICES_PLUGIN\}\}/g, hasGoogleServices ? ' id("com.google.gms.google-services") version "4.4.2" apply false' : ""));
|
|
998
1057
|
const appGradleTemplate = readFileSync2(join3(TEMPLATES_DIR, "build.gradle.kts.app.template"), "utf-8");
|
|
999
|
-
const appGradle = appGradleTemplate.replace(/\{\{PACKAGE_NAME\}\}/g, finalPackageName).replace(/\{\{VERSION_NAME\}\}/g, escapeKotlinString(config.version || "1.0.0")).replace(/\{\{VERSION_CODE\}\}/g, String(config.versionCode || 1)).replace(/\{\{MIN_SDK\}\}/g, String(config.minSdk ?? ANDROID_MIN_SDK)).replace(/\{\{COMPILE_SDK\}\}/g, String(config.compileSdk || 36)).replace(/\{\{TARGET_SDK\}\}/g, String(config.targetSdk || 35)).replace(/\{\{GOOGLE_SERVICES_PLUGIN\}\}/g, hasGoogleServices ? ' id("com.google.gms.google-services")' : "").replace(/\{\{FIREBASE_MESSAGING_DEPENDENCY\}\}/g, config.enablePushNotifications ? ' implementation("com.google.firebase:firebase-messaging:24.1.0")' : "").replace(/\{\{REFRESH_LAYOUT_DEPENDENCY\}\}/g, config.renderer === "native" ? ' implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")' : "").replace(/\{\{
|
|
1000
|
-
implementation("
|
|
1058
|
+
const appGradle = appGradleTemplate.replace(/\{\{PACKAGE_NAME\}\}/g, finalPackageName).replace(/\{\{VERSION_NAME\}\}/g, escapeKotlinString(config.version || "1.0.0")).replace(/\{\{VERSION_CODE\}\}/g, String(config.versionCode || 1)).replace(/\{\{MIN_SDK\}\}/g, String(config.minSdk ?? ANDROID_MIN_SDK)).replace(/\{\{COMPILE_SDK\}\}/g, String(config.compileSdk || 36)).replace(/\{\{TARGET_SDK\}\}/g, String(config.targetSdk || 35)).replace(/\{\{GOOGLE_SERVICES_PLUGIN\}\}/g, hasGoogleServices ? ' id("com.google.gms.google-services")' : "").replace(/\{\{FIREBASE_MESSAGING_DEPENDENCY\}\}/g, config.enablePushNotifications ? ' implementation("com.google.firebase:firebase-messaging:24.1.0")' : "").replace(/\{\{REFRESH_LAYOUT_DEPENDENCY\}\}/g, config.renderer === "native" ? ' implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")' : "").replace(/\{\{NATIVE_MAP_DEPENDENCY\}\}/g, config.renderer === "native" ? ` // Native STX Map overlays and trail routes
|
|
1059
|
+
implementation("${androidMapHost(config.mapProvider).dependency}")` : "").replace(/\{\{HEALTH_CONNECT_DEPENDENCIES\}\}/g, config.enableHealthConnect ? ` implementation("androidx.health.connect:connect-client:1.1.0")
|
|
1001
1060
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1")` : "").replace(/\{\{JAVASCRIPT_ENGINE_DEPENDENCY\}\}/g, config.renderer === "native" ? ` implementation("androidx.javascriptengine:javascriptengine:1.1.0")
|
|
1002
1061
|
// Native background refresh (WorkManager).
|
|
1003
1062
|
implementation("androidx.work:work-runtime-ktx:2.9.1")` : "");
|
|
@@ -1036,6 +1095,8 @@ zipStorePath=wrapper/dists
|
|
|
1036
1095
|
<color name="primary_dark">#16162b</color>
|
|
1037
1096
|
<color name="accent">#4ade80</color>
|
|
1038
1097
|
<color name="background">${config.backgroundColor}</color>
|
|
1098
|
+
<!-- Transparent is NotificationCompat's COLOR_DEFAULT: the system picks. -->
|
|
1099
|
+
<color name="craft_notification_color">${config.notificationColor ?? "#00000000"}</color>
|
|
1039
1100
|
</resources>
|
|
1040
1101
|
`;
|
|
1041
1102
|
writeFileSync(join3(output, "app/src/main/res/values/colors.xml"), colorsXml);
|
|
@@ -1064,6 +1125,21 @@ zipStorePath=wrapper/dists
|
|
|
1064
1125
|
} else {
|
|
1065
1126
|
writeFileSync(join3(output, "app/src/main/res/drawable/craft_app_icon.xml"), appIconXml);
|
|
1066
1127
|
}
|
|
1128
|
+
for (const extension of [".png", ".xml"])
|
|
1129
|
+
rmSync2(join3(output, `app/src/main/res/drawable/craft_notification_icon${extension}`), { force: true });
|
|
1130
|
+
if (config.notificationIconPath) {
|
|
1131
|
+
cpSync(config.notificationIconPath, join3(output, `app/src/main/res/drawable/craft_notification_icon${notificationIconExtension}`));
|
|
1132
|
+
} else {
|
|
1133
|
+
writeFileSync(join3(output, "app/src/main/res/drawable/craft_notification_icon.xml"), `<?xml version="1.0" encoding="utf-8"?>
|
|
1134
|
+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
1135
|
+
android:width="24dp"
|
|
1136
|
+
android:height="24dp"
|
|
1137
|
+
android:viewportWidth="108"
|
|
1138
|
+
android:viewportHeight="108">
|
|
1139
|
+
<path android:fillColor="#FFFFFFFF" android:pathData="M18,78L42,42l12,18l12,-12l24,30z" />
|
|
1140
|
+
</vector>
|
|
1141
|
+
`);
|
|
1142
|
+
}
|
|
1067
1143
|
const themesXml = `<?xml version="1.0" encoding="utf-8"?>
|
|
1068
1144
|
<resources>
|
|
1069
1145
|
<style name="Theme.CraftApp" parent="Theme.Material3.DayNight.NoActionBar">
|
|
@@ -1286,6 +1362,7 @@ export {
|
|
|
1286
1362
|
renderAndroidPermissions,
|
|
1287
1363
|
renderAndroidDeepLinks,
|
|
1288
1364
|
open,
|
|
1365
|
+
nativeMapProviders,
|
|
1289
1366
|
installRuntime,
|
|
1290
1367
|
init,
|
|
1291
1368
|
healthConnectPermissions,
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Build-time native map selection. Both providers are native Android views. */
|
|
2
|
+
export type AndroidMapProvider = 'google' | 'maplibre';
|
|
3
|
+
export declare function androidMapHost(provider?: AndroidMapProvider): {
|
|
4
|
+
template: string;
|
|
5
|
+
imports: string;
|
|
6
|
+
dependency: string;
|
|
7
|
+
};
|
|
@@ -3475,7 +3475,8 @@ class CraftBridge(
|
|
|
3475
3475
|
val notificationManager = activity.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
|
3476
3476
|
|
|
3477
3477
|
val builder = androidx.core.app.NotificationCompat.Builder(activity, notificationChannelId)
|
|
3478
|
-
.setSmallIcon(
|
|
3478
|
+
.setSmallIcon(R.drawable.craft_notification_icon)
|
|
3479
|
+
.setColor(ContextCompat.getColor(activity, R.color.craft_notification_color))
|
|
3479
3480
|
.setContentTitle(title)
|
|
3480
3481
|
.setContentText(body)
|
|
3481
3482
|
.setPriority(androidx.core.app.NotificationCompat.PRIORITY_DEFAULT)
|