craft-native 0.0.109 → 0.0.111
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 +2 -0
- package/dist/android/src/index.js +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.d.ts +2 -0
- package/dist/ios/src/index.js +2 -0
- package/dist/ios/templates/CraftApp.swift +37 -25
- package/package.json +1 -1
|
@@ -25,6 +25,8 @@ export interface CraftAndroidConfig {
|
|
|
25
25
|
enableHealthConnect?: boolean;
|
|
26
26
|
enableKeepAwake?: boolean;
|
|
27
27
|
enableDeepLinks?: boolean;
|
|
28
|
+
/** Reach the person's own devices on the local network over plain HTTP (a Mac companion). */
|
|
29
|
+
enableLocalNetwork?: boolean;
|
|
28
30
|
urlSchemes?: string[];
|
|
29
31
|
trustedOrigins?: string[];
|
|
30
32
|
appIconPath?: string;
|
|
@@ -445,7 +445,7 @@ async function init(options) {
|
|
|
445
445
|
const healthTemplate = readFileSync(join(TEMPLATES_DIR, config.enableHealthConnect ? "CraftHealthConnect.kt.template" : "CraftHealthConnectStub.kt.template"), "utf-8");
|
|
446
446
|
writeFileSync(join(output, "app/src/main/java", packagePath, "CraftHealthConnect.kt"), healthTemplate.replace(/\{\{PACKAGE_NAME\}\}/g, finalPackageName));
|
|
447
447
|
const manifestTemplate = readFileSync(join(TEMPLATES_DIR, "AndroidManifest.xml.template"), "utf-8");
|
|
448
|
-
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://") ? "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(/\{\{HEALTH_CONNECT_QUERIES\}\}/g, config.enableHealthConnect ? ` <queries>
|
|
448
|
+
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(/\{\{HEALTH_CONNECT_QUERIES\}\}/g, config.enableHealthConnect ? ` <queries>
|
|
449
449
|
<package android:name="com.google.android.apps.healthdata" />
|
|
450
450
|
</queries>` : "").replace(/\{\{HEALTH_CONNECT_RATIONALE\}\}/g, config.enableHealthConnect ? ` <intent-filter>
|
|
451
451
|
<action android:name="androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE" />
|
package/dist/cli.js
CHANGED
|
@@ -3303,7 +3303,7 @@ function pinCraftNativeDependency(packagePath, craftVersion) {
|
|
|
3303
3303
|
`);
|
|
3304
3304
|
}
|
|
3305
3305
|
// package.json
|
|
3306
|
-
var version = "0.0.
|
|
3306
|
+
var version = "0.0.111";
|
|
3307
3307
|
|
|
3308
3308
|
// bin/cli.ts
|
|
3309
3309
|
var spawnedFrom = process6.env[CRAFT_CLI_SPAWN_MARKER];
|
package/dist/index.cjs
CHANGED
package/dist/index.js
CHANGED
package/dist/ios/src/index.d.ts
CHANGED
|
@@ -40,6 +40,8 @@ export interface CraftConfig {
|
|
|
40
40
|
enableOrientationLock?: boolean;
|
|
41
41
|
enableDeepLinks?: boolean;
|
|
42
42
|
enableQRScanner?: boolean;
|
|
43
|
+
/** Reach devices on the local network (a Mac on the same Wi-Fi); iOS asks first. */
|
|
44
|
+
enableLocalNetwork?: boolean;
|
|
43
45
|
enableFilePicker?: boolean;
|
|
44
46
|
enableFileDownload?: boolean;
|
|
45
47
|
enableSocialAuth?: boolean;
|
package/dist/ios/src/index.js
CHANGED
|
@@ -27,6 +27,7 @@ var DEFAULT_CONFIG = {
|
|
|
27
27
|
enableOrientationLock: false,
|
|
28
28
|
enableDeepLinks: false,
|
|
29
29
|
enableQRScanner: false,
|
|
30
|
+
enableLocalNetwork: false,
|
|
30
31
|
enableFilePicker: false,
|
|
31
32
|
enableFileDownload: false,
|
|
32
33
|
enableSocialAuth: false,
|
|
@@ -91,6 +92,7 @@ function renderUsageDescriptions(config) {
|
|
|
91
92
|
[config.enableBluetooth, "NSBluetoothAlwaysUsageDescription", `${config.appName} uses Bluetooth to connect to nearby devices.`],
|
|
92
93
|
[config.enableMotionSensors, "NSMotionUsageDescription", `${config.appName} uses motion data for activity features.`],
|
|
93
94
|
[config.enableNFC, "NFCReaderUsageDescription", `${config.appName} reads NFC tags when you start a scan.`],
|
|
95
|
+
[config.enableLocalNetwork, "NSLocalNetworkUsageDescription", `${config.appName} connects to your own devices on this network.`],
|
|
94
96
|
[config.enableHealthKit, "NSHealthShareUsageDescription", `${config.appName} reads health data you choose to share.`],
|
|
95
97
|
[config.enableHealthKit, "NSHealthUpdateUsageDescription", `${config.appName} writes health data only with your permission.`],
|
|
96
98
|
[config.enableBiometric, "NSFaceIDUsageDescription", `${config.appName} uses Face ID to protect your account.`]
|
|
@@ -3392,6 +3392,11 @@ struct CraftWebView: UIViewRepresentable {
|
|
|
3392
3392
|
getBiometricType: function() { return Promise.resolve(craft.capabilities.biometric ? 'faceId' : null); },
|
|
3393
3393
|
authenticate: function(reason) { return legacyAuthenticate(reason); }
|
|
3394
3394
|
};
|
|
3395
|
+
// The app's own SQLite database (Documents/craft.db), as on Android.
|
|
3396
|
+
craft.db = {
|
|
3397
|
+
execute: function(sql, params) { return craft._invoke('dbExecute', { sql: sql, params: params || [] }); },
|
|
3398
|
+
query: function(sql, params) { return craft._invoke('dbQuery', { sql: sql, params: params || [] }); }
|
|
3399
|
+
};
|
|
3395
3400
|
craft.secureStorage = {
|
|
3396
3401
|
set: function(key, value) { return legacySecureStore.set(key, value).then(function() {}); },
|
|
3397
3402
|
get: function(key) { return legacySecureStore.get(key); },
|
|
@@ -5044,6 +5049,34 @@ struct CraftWebView: UIViewRepresentable {
|
|
|
5044
5049
|
}
|
|
5045
5050
|
|
|
5046
5051
|
// MARK: - Local Database (SQLite)
|
|
5052
|
+
/// SQLite copies what it is given only when told to (SQLITE_TRANSIENT);
|
|
5053
|
+
/// with a nil destructor it keeps a pointer to a Swift string that is
|
|
5054
|
+
/// freed as soon as the bind call returns, and stores whatever is there
|
|
5055
|
+
/// later.
|
|
5056
|
+
private let sqliteTransient = unsafeBitCast(-1, to: sqlite3_destructor_type.self)
|
|
5057
|
+
|
|
5058
|
+
/// Binds JSON-bridged values: strings, integers as 64-bit (JS numbers
|
|
5059
|
+
/// that are whole, such as millisecond timestamps), other numbers as
|
|
5060
|
+
/// doubles, booleans as 0/1, and null.
|
|
5061
|
+
private func bindParameters(_ statement: OpaquePointer?, _ params: [Any]) {
|
|
5062
|
+
for (index, param) in params.enumerated() {
|
|
5063
|
+
let idx = Int32(index + 1)
|
|
5064
|
+
if let str = param as? String {
|
|
5065
|
+
sqlite3_bind_text(statement, idx, str, -1, sqliteTransient)
|
|
5066
|
+
} else if let number = param as? NSNumber {
|
|
5067
|
+
if CFGetTypeID(number) == CFBooleanGetTypeID() {
|
|
5068
|
+
sqlite3_bind_int64(statement, idx, number.boolValue ? 1 : 0)
|
|
5069
|
+
} else if CFNumberIsFloatType(number), number.doubleValue.rounded() != number.doubleValue {
|
|
5070
|
+
sqlite3_bind_double(statement, idx, number.doubleValue)
|
|
5071
|
+
} else {
|
|
5072
|
+
sqlite3_bind_int64(statement, idx, number.int64Value)
|
|
5073
|
+
}
|
|
5074
|
+
} else {
|
|
5075
|
+
sqlite3_bind_null(statement, idx)
|
|
5076
|
+
}
|
|
5077
|
+
}
|
|
5078
|
+
}
|
|
5079
|
+
|
|
5047
5080
|
private func dbExecute(sql: String, params: [Any]?, callbackId: String?) {
|
|
5048
5081
|
guard let db = db else {
|
|
5049
5082
|
rejectCallback(callbackId, error: "Database not initialized")
|
|
@@ -5054,18 +5087,7 @@ struct CraftWebView: UIViewRepresentable {
|
|
|
5054
5087
|
if sqlite3_prepare_v2(db, sql, -1, &statement, nil) == SQLITE_OK {
|
|
5055
5088
|
// Bind parameters
|
|
5056
5089
|
if let params = params {
|
|
5057
|
-
|
|
5058
|
-
let idx = Int32(index + 1)
|
|
5059
|
-
if let str = param as? String {
|
|
5060
|
-
sqlite3_bind_text(statement, idx, str, -1, nil)
|
|
5061
|
-
} else if let int = param as? Int {
|
|
5062
|
-
sqlite3_bind_int(statement, idx, Int32(int))
|
|
5063
|
-
} else if let double = param as? Double {
|
|
5064
|
-
sqlite3_bind_double(statement, idx, double)
|
|
5065
|
-
} else {
|
|
5066
|
-
sqlite3_bind_null(statement, idx)
|
|
5067
|
-
}
|
|
5068
|
-
}
|
|
5090
|
+
bindParameters(statement, params)
|
|
5069
5091
|
}
|
|
5070
5092
|
|
|
5071
5093
|
if sqlite3_step(statement) == SQLITE_DONE {
|
|
@@ -5095,18 +5117,7 @@ struct CraftWebView: UIViewRepresentable {
|
|
|
5095
5117
|
if sqlite3_prepare_v2(db, sql, -1, &statement, nil) == SQLITE_OK {
|
|
5096
5118
|
// Bind parameters
|
|
5097
5119
|
if let params = params {
|
|
5098
|
-
|
|
5099
|
-
let idx = Int32(index + 1)
|
|
5100
|
-
if let str = param as? String {
|
|
5101
|
-
sqlite3_bind_text(statement, idx, str, -1, nil)
|
|
5102
|
-
} else if let int = param as? Int {
|
|
5103
|
-
sqlite3_bind_int(statement, idx, Int32(int))
|
|
5104
|
-
} else if let double = param as? Double {
|
|
5105
|
-
sqlite3_bind_double(statement, idx, double)
|
|
5106
|
-
} else {
|
|
5107
|
-
sqlite3_bind_null(statement, idx)
|
|
5108
|
-
}
|
|
5109
|
-
}
|
|
5120
|
+
bindParameters(statement, params)
|
|
5110
5121
|
}
|
|
5111
5122
|
|
|
5112
5123
|
let columnCount = sqlite3_column_count(statement)
|
|
@@ -5119,7 +5130,8 @@ struct CraftWebView: UIViewRepresentable {
|
|
|
5119
5130
|
|
|
5120
5131
|
switch type {
|
|
5121
5132
|
case SQLITE_INTEGER:
|
|
5122
|
-
|
|
5133
|
+
// 64-bit: millisecond timestamps overflow Int32.
|
|
5134
|
+
row[columnName] = sqlite3_column_int64(statement, i)
|
|
5123
5135
|
case SQLITE_FLOAT:
|
|
5124
5136
|
row[columnName] = sqlite3_column_double(statement, i)
|
|
5125
5137
|
case SQLITE_TEXT:
|