expo-beacon 0.7.8 → 0.7.9
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/app.plugin.js +1 -1
- package/build/index.d.ts +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -1
- package/build/index.js.map +1 -1
- package/package.json +1 -1
- package/plugin/build/{withBeaconBGLocation.d.ts → index.d.ts} +1 -1
- package/plugin/build/index.d.ts.map +1 -0
- package/plugin/build/index.js +21 -0
- package/plugin/build/withBeaconAndroid.d.ts +5 -0
- package/plugin/build/withBeaconAndroid.d.ts.map +1 -0
- package/plugin/build/withBeaconAndroid.js +97 -0
- package/plugin/build/withBeaconIOS.d.ts +5 -0
- package/plugin/build/withBeaconIOS.d.ts.map +1 -0
- package/plugin/build/withBeaconIOS.js +100 -0
- package/src/index.ts +1 -1
- package/plugin/build/withBeaconBGLocation.d.ts.map +0 -1
- package/plugin/build/withBeaconBGLocation.js +0 -197
package/app.plugin.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
module.exports = require('./plugin/build
|
|
1
|
+
module.exports = require('./plugin/build');
|
package/build/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { default } from "./ExpoBeaconModule
|
|
1
|
+
export { default } from "./ExpoBeaconModule";
|
|
2
2
|
export type { BeaconScanResult, PairedBeacon, BeaconRegionEvent, BeaconDistanceEvent, BeaconTimeoutEvent, ExpoBeaconModuleEvents, NotificationConfig, MonitoringOptions, MonitoringConfig, MonitoredDeviceState, BeaconNotificationConfig, ForegroundServiceConfig, NotificationChannelConfig, EddystoneFrameType, EddystoneScanResult, PairedEddystone, EddystoneRegionEvent, EddystoneDistanceEvent, EddystoneTimeoutEvent, EventLogQueryOptions, EventLogEntry, } from "./ExpoBeacon.types";
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
package/build/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAG7C,YAAY,EACV,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,EACtB,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,wBAAwB,EACxB,uBAAuB,EACvB,yBAAyB,EACzB,kBAAkB,EAClB,mBAAmB,EACnB,eAAe,EACf,oBAAoB,EACpB,sBAAsB,EACtB,qBAAqB,EACrB,oBAAoB,EACpB,aAAa,GACd,MAAM,oBAAoB,CAAC"}
|
package/build/index.js
CHANGED
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC","sourcesContent":["// Native module (default export)\r\nexport { default } from \"./ExpoBeaconModule\";\r\n\r\n// All public types\r\nexport type {\r\n BeaconScanResult,\r\n PairedBeacon,\r\n BeaconRegionEvent,\r\n BeaconDistanceEvent,\r\n BeaconTimeoutEvent,\r\n ExpoBeaconModuleEvents,\r\n NotificationConfig,\r\n MonitoringOptions,\r\n MonitoringConfig,\r\n MonitoredDeviceState,\r\n BeaconNotificationConfig,\r\n ForegroundServiceConfig,\r\n NotificationChannelConfig,\r\n EddystoneFrameType,\r\n EddystoneScanResult,\r\n PairedEddystone,\r\n EddystoneRegionEvent,\r\n EddystoneDistanceEvent,\r\n EddystoneTimeoutEvent,\r\n EventLogQueryOptions,\r\n EventLogEntry,\r\n} from \"./ExpoBeacon.types\";\r\n"]}
|
package/package.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAuB,MAAM,sBAAsB,CAAC;;AAqBzE,wBAIE"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const config_plugins_1 = require("@expo/config-plugins");
|
|
4
|
+
const withBeaconAndroid_1 = require("./withBeaconAndroid");
|
|
5
|
+
const withBeaconIOS_1 = require("./withBeaconIOS");
|
|
6
|
+
const withBeaconBGLocation = (config) => {
|
|
7
|
+
var _a;
|
|
8
|
+
const platform = config.sdkVersion !== undefined
|
|
9
|
+
? (_a = config._resolvedLinkedPackages) === null || _a === void 0 ? void 0 : _a.platform
|
|
10
|
+
: undefined;
|
|
11
|
+
// Apply iOS plugin only when building for iOS (or when platform is unknown,
|
|
12
|
+
// in which case both are applied — the individual mods are platform-gated).
|
|
13
|
+
if (platform !== 'android') {
|
|
14
|
+
config = (0, withBeaconIOS_1.default)(config);
|
|
15
|
+
}
|
|
16
|
+
if (platform !== 'ios') {
|
|
17
|
+
config = (0, withBeaconAndroid_1.default)(config);
|
|
18
|
+
}
|
|
19
|
+
return config;
|
|
20
|
+
};
|
|
21
|
+
exports.default = (0, config_plugins_1.createRunOncePlugin)(withBeaconBGLocation, 'expo-beacon-bglocation', '1.0.0');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"withBeaconAndroid.d.ts","sourceRoot":"","sources":["../src/withBeaconAndroid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAoB,MAAM,sBAAsB,CAAC;AAMtE,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAqBlE;AAqCD,QAAA,MAAM,iBAAiB,EAAE,YA0DxB,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getAndroidPluginKotlin = getAndroidPluginKotlin;
|
|
4
|
+
const config_plugins_1 = require("@expo/config-plugins");
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
// ─── Generated Kotlin file ────────────────────────────────────────────────────
|
|
8
|
+
function getAndroidPluginKotlin(packageName) {
|
|
9
|
+
return `\
|
|
10
|
+
package ${packageName}
|
|
11
|
+
|
|
12
|
+
import android.content.Context
|
|
13
|
+
import com.transistorsoft.locationmanager.adapter.BackgroundGeolocation
|
|
14
|
+
import expo.modules.beacon.BeaconEventPlugin
|
|
15
|
+
|
|
16
|
+
class BeaconGeoPlugin(ctx: Context) : BeaconEventPlugin {
|
|
17
|
+
private val bgGeo = BackgroundGeolocation.getInstance(ctx, null)
|
|
18
|
+
|
|
19
|
+
override fun onBeaconEnter(identifier: String, uuid: String, major: Int, minor: Int, distance: Double) =
|
|
20
|
+
bgGeo.start(null)
|
|
21
|
+
override fun onBeaconExit(identifier: String, uuid: String, major: Int, minor: Int, distance: Double) =
|
|
22
|
+
bgGeo.stop(null)
|
|
23
|
+
override fun onEddystoneEnter(identifier: String, namespace: String, instance: String, distance: Double) =
|
|
24
|
+
bgGeo.start(null)
|
|
25
|
+
override fun onEddystoneExit(identifier: String, namespace: String, instance: String, distance: Double) =
|
|
26
|
+
bgGeo.stop(null)
|
|
27
|
+
}
|
|
28
|
+
`;
|
|
29
|
+
}
|
|
30
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
31
|
+
function modifyMainApplication(contents) {
|
|
32
|
+
const importLine = 'import expo.modules.beacon.BeaconPluginRegistry';
|
|
33
|
+
// Add missing import after the last existing import.
|
|
34
|
+
if (!contents.includes(importLine)) {
|
|
35
|
+
const lines = contents.split('\n');
|
|
36
|
+
const lastImportIdx = lines.reduce((last, line, i) => (line.trimStart().startsWith('import ') ? i : last), -1);
|
|
37
|
+
if (lastImportIdx >= 0) {
|
|
38
|
+
lines.splice(lastImportIdx + 1, 0, importLine);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
const pkgIdx = lines.findIndex((l) => l.startsWith('package '));
|
|
42
|
+
lines.splice(pkgIdx >= 0 ? pkgIdx + 1 : 0, 0, '', importLine);
|
|
43
|
+
}
|
|
44
|
+
contents = lines.join('\n');
|
|
45
|
+
}
|
|
46
|
+
// Add registration call immediately after `super.onCreate()`.
|
|
47
|
+
const registration = ' BeaconPluginRegistry.register(BeaconGeoPlugin(this))';
|
|
48
|
+
if (!contents.includes('BeaconPluginRegistry.register(BeaconGeoPlugin(this))')) {
|
|
49
|
+
contents = contents.replace(/(super\.onCreate\(\)[ \t]*\n)/, `$1${registration}\n`);
|
|
50
|
+
}
|
|
51
|
+
return contents;
|
|
52
|
+
}
|
|
53
|
+
// ─── Plugin ───────────────────────────────────────────────────────────────────
|
|
54
|
+
const withBeaconAndroid = (config) => {
|
|
55
|
+
// Step 1 – write BeaconGeoPlugin.kt into the app source tree.
|
|
56
|
+
config = (0, config_plugins_1.withDangerousMod)(config, [
|
|
57
|
+
'android',
|
|
58
|
+
(config) => {
|
|
59
|
+
var _a;
|
|
60
|
+
const pkgName = (_a = config.android) === null || _a === void 0 ? void 0 : _a.package;
|
|
61
|
+
if (!pkgName) {
|
|
62
|
+
console.warn('[expo-beacon] android.package not set — BeaconGeoPlugin.kt was not written.');
|
|
63
|
+
return config;
|
|
64
|
+
}
|
|
65
|
+
const pkgPath = pkgName.replace(/\./g, '/');
|
|
66
|
+
const outputPath = path.join(config.modRequest.platformProjectRoot, 'app/src/main/java', pkgPath, 'BeaconGeoPlugin.kt');
|
|
67
|
+
fs.writeFileSync(outputPath, getAndroidPluginKotlin(pkgName));
|
|
68
|
+
return config;
|
|
69
|
+
},
|
|
70
|
+
]);
|
|
71
|
+
// Step 2 – patch MainApplication (Kotlin or Java) to call register().
|
|
72
|
+
config = (0, config_plugins_1.withDangerousMod)(config, [
|
|
73
|
+
'android',
|
|
74
|
+
(config) => {
|
|
75
|
+
var _a;
|
|
76
|
+
const pkgName = (_a = config.android) === null || _a === void 0 ? void 0 : _a.package;
|
|
77
|
+
if (!pkgName)
|
|
78
|
+
return config;
|
|
79
|
+
const pkgPath = pkgName.replace(/\./g, '/');
|
|
80
|
+
const javaRoot = path.join(config.modRequest.platformProjectRoot, 'app/src/main/java', pkgPath);
|
|
81
|
+
const mainAppPath = [
|
|
82
|
+
path.join(javaRoot, 'MainApplication.kt'),
|
|
83
|
+
path.join(javaRoot, 'MainApplication.java'),
|
|
84
|
+
].find(fs.existsSync);
|
|
85
|
+
if (!mainAppPath) {
|
|
86
|
+
console.warn('[expo-beacon] MainApplication.kt / .java not found — ' +
|
|
87
|
+
'please add BeaconPluginRegistry.register(BeaconGeoPlugin(this)) manually.');
|
|
88
|
+
return config;
|
|
89
|
+
}
|
|
90
|
+
const original = fs.readFileSync(mainAppPath, 'utf-8');
|
|
91
|
+
fs.writeFileSync(mainAppPath, modifyMainApplication(original));
|
|
92
|
+
return config;
|
|
93
|
+
},
|
|
94
|
+
]);
|
|
95
|
+
return config;
|
|
96
|
+
};
|
|
97
|
+
exports.default = withBeaconAndroid;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { ConfigPlugin } from '@expo/config-plugins';
|
|
2
|
+
export declare const IOS_PLUGIN_SWIFT = "import ExpoBeacon\nimport TSLocationManager\n\nfinal class BeaconGeoPlugin: BeaconLifecycleDelegate {\n func beaconDidEnter(identifier: String, uuid: String, major: Int, minor: Int, distance: Double) {\n TSLocationManager.sharedManager().start()\n }\n func beaconDidExit(identifier: String, uuid: String, major: Int, minor: Int, distance: Double) {\n TSLocationManager.sharedManager().stop()\n }\n func eddystoneDidEnter(identifier: String, namespace: String, instance: String, distance: Double) {\n TSLocationManager.sharedManager().start()\n }\n func eddystoneDidExit(identifier: String, namespace: String, instance: String, distance: Double) {\n TSLocationManager.sharedManager().stop()\n }\n}\n";
|
|
3
|
+
declare const withBeaconIOS: ConfigPlugin;
|
|
4
|
+
export default withBeaconIOS;
|
|
5
|
+
//# sourceMappingURL=withBeaconIOS.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"withBeaconIOS.d.ts","sourceRoot":"","sources":["../src/withBeaconIOS.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EAGb,MAAM,sBAAsB,CAAC;AAM9B,eAAO,MAAM,gBAAgB,mvBAkB5B,CAAC;AA4DF,QAAA,MAAM,aAAa,EAAE,YAqCpB,CAAC;AAEF,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IOS_PLUGIN_SWIFT = void 0;
|
|
4
|
+
const config_plugins_1 = require("@expo/config-plugins");
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
// ─── Generated Swift file ─────────────────────────────────────────────────────
|
|
8
|
+
exports.IOS_PLUGIN_SWIFT = `\
|
|
9
|
+
import ExpoBeacon
|
|
10
|
+
import TSLocationManager
|
|
11
|
+
|
|
12
|
+
final class BeaconGeoPlugin: BeaconLifecycleDelegate {
|
|
13
|
+
func beaconDidEnter(identifier: String, uuid: String, major: Int, minor: Int, distance: Double) {
|
|
14
|
+
TSLocationManager.sharedManager().start()
|
|
15
|
+
}
|
|
16
|
+
func beaconDidExit(identifier: String, uuid: String, major: Int, minor: Int, distance: Double) {
|
|
17
|
+
TSLocationManager.sharedManager().stop()
|
|
18
|
+
}
|
|
19
|
+
func eddystoneDidEnter(identifier: String, namespace: String, instance: String, distance: Double) {
|
|
20
|
+
TSLocationManager.sharedManager().start()
|
|
21
|
+
}
|
|
22
|
+
func eddystoneDidExit(identifier: String, namespace: String, instance: String, distance: Double) {
|
|
23
|
+
TSLocationManager.sharedManager().stop()
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
`;
|
|
27
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
28
|
+
/**
|
|
29
|
+
* Finds the UUID (key) of a PBXGroup by name, handling both quoted and unquoted
|
|
30
|
+
* name values produced by node-xcode's parser.
|
|
31
|
+
*/
|
|
32
|
+
function findPBXGroupKeyByName(xcodeProject, name) {
|
|
33
|
+
var _a;
|
|
34
|
+
const pbxGroups = (_a = xcodeProject.hash.project.objects['PBXGroup']) !== null && _a !== void 0 ? _a : {};
|
|
35
|
+
for (const key of Object.keys(pbxGroups)) {
|
|
36
|
+
if (key.endsWith('_comment'))
|
|
37
|
+
continue;
|
|
38
|
+
const group = pbxGroups[key];
|
|
39
|
+
if (group.name === `"${name}"` || group.name === name)
|
|
40
|
+
return key;
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
/** Returns true if a PBXFileReference for filename already exists (idempotency guard). */
|
|
45
|
+
function isFileInXcodeProject(xcodeProject, filename) {
|
|
46
|
+
var _a;
|
|
47
|
+
const refs = (_a = xcodeProject.hash.project.objects['PBXFileReference']) !== null && _a !== void 0 ? _a : {};
|
|
48
|
+
return Object.values(refs).some((f) => typeof f === 'object' &&
|
|
49
|
+
f !== null &&
|
|
50
|
+
(f.path === `"${filename}"` || f.path === filename));
|
|
51
|
+
}
|
|
52
|
+
function modifySwiftAppDelegate(contents) {
|
|
53
|
+
// Insert `import ExpoBeacon` after the last existing import line.
|
|
54
|
+
if (!contents.includes('import ExpoBeacon')) {
|
|
55
|
+
const lines = contents.split('\n');
|
|
56
|
+
const lastImportIdx = lines.reduce((last, line, i) => (line.trimStart().startsWith('import ') ? i : last), -1);
|
|
57
|
+
if (lastImportIdx >= 0) {
|
|
58
|
+
lines.splice(lastImportIdx + 1, 0, 'import ExpoBeacon');
|
|
59
|
+
contents = lines.join('\n');
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// Insert `BeaconLifecycleRegistry.register(BeaconGeoPlugin())` immediately
|
|
63
|
+
// before `return super.application(`, preserving indentation.
|
|
64
|
+
const marker = 'BeaconLifecycleRegistry.register(BeaconGeoPlugin())';
|
|
65
|
+
if (!contents.includes(marker)) {
|
|
66
|
+
contents = contents.replace(/([ \t]*)(return super\.application\()/, `$1${marker}\n$1$2`);
|
|
67
|
+
}
|
|
68
|
+
return contents;
|
|
69
|
+
}
|
|
70
|
+
// ─── Plugin ───────────────────────────────────────────────────────────────────
|
|
71
|
+
const withBeaconIOS = (config) => {
|
|
72
|
+
// Step 1 – write BeaconGeoPlugin.swift and add it to the Xcode project.
|
|
73
|
+
config = (0, config_plugins_1.withXcodeProject)(config, (config) => {
|
|
74
|
+
var _a;
|
|
75
|
+
const xcodeProject = config.modResults;
|
|
76
|
+
const { projectName, platformProjectRoot } = config.modRequest;
|
|
77
|
+
if (!projectName || !platformProjectRoot)
|
|
78
|
+
return config;
|
|
79
|
+
const swiftFilePath = path.join(platformProjectRoot, projectName, 'BeaconGeoPlugin.swift');
|
|
80
|
+
fs.writeFileSync(swiftFilePath, exports.IOS_PLUGIN_SWIFT);
|
|
81
|
+
if (!isFileInXcodeProject(xcodeProject, 'BeaconGeoPlugin.swift')) {
|
|
82
|
+
const groupKey = (_a = findPBXGroupKeyByName(xcodeProject, projectName)) !== null && _a !== void 0 ? _a : undefined;
|
|
83
|
+
xcodeProject.addSourceFile('BeaconGeoPlugin.swift', null, groupKey !== null && groupKey !== void 0 ? groupKey : undefined);
|
|
84
|
+
}
|
|
85
|
+
return config;
|
|
86
|
+
});
|
|
87
|
+
// Step 2 – patch AppDelegate.swift to register the plugin before super.
|
|
88
|
+
config = (0, config_plugins_1.withAppDelegate)(config, (config) => {
|
|
89
|
+
if (config.modResults.language === 'swift') {
|
|
90
|
+
config.modResults.contents = modifySwiftAppDelegate(config.modResults.contents);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
console.warn('[expo-beacon] withBeaconIOS: AppDelegate is not Swift — ' +
|
|
94
|
+
'please add BeaconLifecycleRegistry.register(BeaconGeoPlugin()) manually.');
|
|
95
|
+
}
|
|
96
|
+
return config;
|
|
97
|
+
});
|
|
98
|
+
return config;
|
|
99
|
+
};
|
|
100
|
+
exports.default = withBeaconIOS;
|
package/src/index.ts
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"withBeaconBGLocation.d.ts","sourceRoot":"","sources":["../src/withBeaconBGLocation.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EAKb,MAAM,sBAAsB,CAAC;;AA4P9B,wBAIE"}
|
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const config_plugins_1 = require("@expo/config-plugins");
|
|
4
|
-
const fs = require("fs");
|
|
5
|
-
const path = require("path");
|
|
6
|
-
// ─── Generated file contents ─────────────────────────────────────────────────
|
|
7
|
-
const IOS_PLUGIN_SWIFT = `\
|
|
8
|
-
import ExpoBeacon
|
|
9
|
-
import TSLocationManager
|
|
10
|
-
|
|
11
|
-
final class BeaconGeoPlugin: BeaconLifecycleDelegate {
|
|
12
|
-
func beaconDidEnter(identifier: String, uuid: String, major: Int, minor: Int, distance: Double) {
|
|
13
|
-
TSLocationManager.sharedManager().start()
|
|
14
|
-
}
|
|
15
|
-
func beaconDidExit(identifier: String, uuid: String, major: Int, minor: Int, distance: Double) {
|
|
16
|
-
TSLocationManager.sharedManager().stop()
|
|
17
|
-
}
|
|
18
|
-
func eddystoneDidEnter(identifier: String, namespace: String, instance: String, distance: Double) {
|
|
19
|
-
TSLocationManager.sharedManager().start()
|
|
20
|
-
}
|
|
21
|
-
func eddystoneDidExit(identifier: String, namespace: String, instance: String, distance: Double) {
|
|
22
|
-
TSLocationManager.sharedManager().stop()
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
`;
|
|
26
|
-
function getAndroidPluginKotlin(packageName) {
|
|
27
|
-
return `\
|
|
28
|
-
package ${packageName}
|
|
29
|
-
|
|
30
|
-
import android.content.Context
|
|
31
|
-
import com.transistorsoft.locationmanager.adapter.BackgroundGeolocation
|
|
32
|
-
import expo.modules.beacon.BeaconEventPlugin
|
|
33
|
-
|
|
34
|
-
class BeaconGeoPlugin(ctx: Context) : BeaconEventPlugin {
|
|
35
|
-
private val bgGeo = BackgroundGeolocation.getInstance(ctx, null)
|
|
36
|
-
|
|
37
|
-
override fun onBeaconEnter(identifier: String, uuid: String, major: Int, minor: Int, distance: Double) =
|
|
38
|
-
bgGeo.start(null)
|
|
39
|
-
override fun onBeaconExit(identifier: String, uuid: String, major: Int, minor: Int, distance: Double) =
|
|
40
|
-
bgGeo.stop(null)
|
|
41
|
-
override fun onEddystoneEnter(identifier: String, namespace: String, instance: String, distance: Double) =
|
|
42
|
-
bgGeo.start(null)
|
|
43
|
-
override fun onEddystoneExit(identifier: String, namespace: String, instance: String, distance: Double) =
|
|
44
|
-
bgGeo.stop(null)
|
|
45
|
-
}
|
|
46
|
-
`;
|
|
47
|
-
}
|
|
48
|
-
// ─── iOS helpers ─────────────────────────────────────────────────────────────
|
|
49
|
-
/**
|
|
50
|
-
* Finds the UUID (key) of a PBXGroup by name, handling both quoted and unquoted
|
|
51
|
-
* name values produced by node-xcode's parser.
|
|
52
|
-
*/
|
|
53
|
-
function findPBXGroupKeyByName(xcodeProject, name) {
|
|
54
|
-
var _a;
|
|
55
|
-
const pbxGroups = (_a = xcodeProject.hash.project.objects['PBXGroup']) !== null && _a !== void 0 ? _a : {};
|
|
56
|
-
for (const key of Object.keys(pbxGroups)) {
|
|
57
|
-
if (key.endsWith('_comment'))
|
|
58
|
-
continue;
|
|
59
|
-
const group = pbxGroups[key];
|
|
60
|
-
// node-xcode stores quoted strings with literal quote characters in the value.
|
|
61
|
-
if (group.name === `"${name}"` || group.name === name)
|
|
62
|
-
return key;
|
|
63
|
-
}
|
|
64
|
-
return null;
|
|
65
|
-
}
|
|
66
|
-
/** Returns true if a PBXFileReference for filename already exists (idempotency guard). */
|
|
67
|
-
function isFileInXcodeProject(xcodeProject, filename) {
|
|
68
|
-
var _a;
|
|
69
|
-
const refs = (_a = xcodeProject.hash.project.objects['PBXFileReference']) !== null && _a !== void 0 ? _a : {};
|
|
70
|
-
return Object.values(refs).some((f) => typeof f === 'object' &&
|
|
71
|
-
f !== null &&
|
|
72
|
-
(f.path === `"${filename}"` || f.path === filename));
|
|
73
|
-
}
|
|
74
|
-
function modifySwiftAppDelegate(contents) {
|
|
75
|
-
// Insert `import ExpoBeacon` after the last existing import line.
|
|
76
|
-
if (!contents.includes('import ExpoBeacon')) {
|
|
77
|
-
const lines = contents.split('\n');
|
|
78
|
-
const lastImportIdx = lines.reduce((last, line, i) => (line.trimStart().startsWith('import ') ? i : last), -1);
|
|
79
|
-
if (lastImportIdx >= 0) {
|
|
80
|
-
lines.splice(lastImportIdx + 1, 0, 'import ExpoBeacon');
|
|
81
|
-
contents = lines.join('\n');
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
// Insert `BeaconLifecycleRegistry.register(BeaconGeoPlugin())` immediately
|
|
85
|
-
// before `return super.application(`, preserving indentation.
|
|
86
|
-
const marker = 'BeaconLifecycleRegistry.register(BeaconGeoPlugin())';
|
|
87
|
-
if (!contents.includes(marker)) {
|
|
88
|
-
contents = contents.replace(/([ \t]*)(return super\.application\()/, `$1${marker}\n$1$2`);
|
|
89
|
-
}
|
|
90
|
-
return contents;
|
|
91
|
-
}
|
|
92
|
-
// ─── Android helpers ─────────────────────────────────────────────────────────
|
|
93
|
-
function modifyMainApplication(contents) {
|
|
94
|
-
const importLine = 'import expo.modules.beacon.BeaconPluginRegistry';
|
|
95
|
-
// Add missing import after the last existing import.
|
|
96
|
-
if (!contents.includes(importLine)) {
|
|
97
|
-
const lines = contents.split('\n');
|
|
98
|
-
const lastImportIdx = lines.reduce((last, line, i) => (line.trimStart().startsWith('import ') ? i : last), -1);
|
|
99
|
-
if (lastImportIdx >= 0) {
|
|
100
|
-
lines.splice(lastImportIdx + 1, 0, importLine);
|
|
101
|
-
}
|
|
102
|
-
else {
|
|
103
|
-
// No imports yet — insert after the package declaration.
|
|
104
|
-
const pkgIdx = lines.findIndex((l) => l.startsWith('package '));
|
|
105
|
-
lines.splice(pkgIdx >= 0 ? pkgIdx + 1 : 0, 0, '', importLine);
|
|
106
|
-
}
|
|
107
|
-
contents = lines.join('\n');
|
|
108
|
-
}
|
|
109
|
-
// Add registration call immediately after `super.onCreate()`.
|
|
110
|
-
const registration = ' BeaconPluginRegistry.register(BeaconGeoPlugin(this))';
|
|
111
|
-
if (!contents.includes('BeaconPluginRegistry.register(BeaconGeoPlugin(this))')) {
|
|
112
|
-
contents = contents.replace(/(super\.onCreate\(\)[ \t]*\n)/, `$1${registration}\n`);
|
|
113
|
-
}
|
|
114
|
-
return contents;
|
|
115
|
-
}
|
|
116
|
-
// ─── iOS plugin steps ────────────────────────────────────────────────────────
|
|
117
|
-
const withBeaconIOSBGLocation = (config) => {
|
|
118
|
-
// Step 1 – write BeaconGeoPlugin.swift and add it to the Xcode project.
|
|
119
|
-
config = (0, config_plugins_1.withXcodeProject)(config, (config) => {
|
|
120
|
-
var _a;
|
|
121
|
-
const xcodeProject = config.modResults;
|
|
122
|
-
const { projectName, platformProjectRoot } = config.modRequest;
|
|
123
|
-
if (!projectName || !platformProjectRoot)
|
|
124
|
-
return config;
|
|
125
|
-
const swiftFilePath = path.join(platformProjectRoot, projectName, 'BeaconGeoPlugin.swift');
|
|
126
|
-
fs.writeFileSync(swiftFilePath, IOS_PLUGIN_SWIFT);
|
|
127
|
-
if (!isFileInXcodeProject(xcodeProject, 'BeaconGeoPlugin.swift')) {
|
|
128
|
-
const groupKey = (_a = findPBXGroupKeyByName(xcodeProject, projectName)) !== null && _a !== void 0 ? _a : undefined;
|
|
129
|
-
xcodeProject.addSourceFile('BeaconGeoPlugin.swift', null, groupKey !== null && groupKey !== void 0 ? groupKey : undefined);
|
|
130
|
-
}
|
|
131
|
-
return config;
|
|
132
|
-
});
|
|
133
|
-
// Step 2 – patch AppDelegate.swift to register the plugin before super.
|
|
134
|
-
config = (0, config_plugins_1.withAppDelegate)(config, (config) => {
|
|
135
|
-
if (config.modResults.language === 'swift') {
|
|
136
|
-
config.modResults.contents = modifySwiftAppDelegate(config.modResults.contents);
|
|
137
|
-
}
|
|
138
|
-
else {
|
|
139
|
-
console.warn('[expo-beacon] withBeaconBGLocation: AppDelegate is not Swift — ' +
|
|
140
|
-
'please add BeaconLifecycleRegistry.register(BeaconGeoPlugin()) manually.');
|
|
141
|
-
}
|
|
142
|
-
return config;
|
|
143
|
-
});
|
|
144
|
-
return config;
|
|
145
|
-
};
|
|
146
|
-
// ─── Android plugin steps ─────────────────────────────────────────────────────
|
|
147
|
-
const withBeaconAndroidBGLocation = (config) => {
|
|
148
|
-
// Step 1 – write BeaconGeoPlugin.kt into the app source tree.
|
|
149
|
-
config = (0, config_plugins_1.withDangerousMod)(config, [
|
|
150
|
-
'android',
|
|
151
|
-
(config) => {
|
|
152
|
-
var _a;
|
|
153
|
-
const pkgName = (_a = config.android) === null || _a === void 0 ? void 0 : _a.package;
|
|
154
|
-
if (!pkgName) {
|
|
155
|
-
console.warn('[expo-beacon] android.package not set — BeaconGeoPlugin.kt was not written.');
|
|
156
|
-
return config;
|
|
157
|
-
}
|
|
158
|
-
const pkgPath = pkgName.replace(/\./g, '/');
|
|
159
|
-
const outputPath = path.join(config.modRequest.platformProjectRoot, 'app/src/main/java', pkgPath, 'BeaconGeoPlugin.kt');
|
|
160
|
-
fs.writeFileSync(outputPath, getAndroidPluginKotlin(pkgName));
|
|
161
|
-
return config;
|
|
162
|
-
},
|
|
163
|
-
]);
|
|
164
|
-
// Step 2 – patch MainApplication (Kotlin or Java) to call register().
|
|
165
|
-
config = (0, config_plugins_1.withDangerousMod)(config, [
|
|
166
|
-
'android',
|
|
167
|
-
(config) => {
|
|
168
|
-
var _a;
|
|
169
|
-
const pkgName = (_a = config.android) === null || _a === void 0 ? void 0 : _a.package;
|
|
170
|
-
if (!pkgName)
|
|
171
|
-
return config;
|
|
172
|
-
const pkgPath = pkgName.replace(/\./g, '/');
|
|
173
|
-
const javaRoot = path.join(config.modRequest.platformProjectRoot, 'app/src/main/java', pkgPath);
|
|
174
|
-
// Support both Kotlin and Java MainApplication.
|
|
175
|
-
const mainAppPath = [
|
|
176
|
-
path.join(javaRoot, 'MainApplication.kt'),
|
|
177
|
-
path.join(javaRoot, 'MainApplication.java'),
|
|
178
|
-
].find(fs.existsSync);
|
|
179
|
-
if (!mainAppPath) {
|
|
180
|
-
console.warn('[expo-beacon] MainApplication.kt / .java not found — ' +
|
|
181
|
-
'please add BeaconPluginRegistry.register(BeaconGeoPlugin(this)) manually.');
|
|
182
|
-
return config;
|
|
183
|
-
}
|
|
184
|
-
const original = fs.readFileSync(mainAppPath, 'utf-8');
|
|
185
|
-
fs.writeFileSync(mainAppPath, modifyMainApplication(original));
|
|
186
|
-
return config;
|
|
187
|
-
},
|
|
188
|
-
]);
|
|
189
|
-
return config;
|
|
190
|
-
};
|
|
191
|
-
// ─── Combined plugin ─────────────────────────────────────────────────────────
|
|
192
|
-
const withBeaconBGLocation = (config) => {
|
|
193
|
-
config = withBeaconIOSBGLocation(config);
|
|
194
|
-
config = withBeaconAndroidBGLocation(config);
|
|
195
|
-
return config;
|
|
196
|
-
};
|
|
197
|
-
exports.default = (0, config_plugins_1.createRunOncePlugin)(withBeaconBGLocation, 'expo-beacon-bglocation', '1.0.0');
|