vxrn 2.13.2 → 2.13.4

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.
@@ -3,7 +3,7 @@ import { createHash } from "node:crypto";
3
3
  import module from "node:module";
4
4
  import path from "node:path";
5
5
  import { pathToFileURL } from "node:url";
6
- import { androidIconSuffix, appIconPreviewResources, iosUsageDescriptions, validateNativeApp } from "@vxrn/utils/nativeAppManifest";
6
+ import { androidAppPermissions, androidIconSuffix, appIconPreviewResources, iosUsageDescriptions, validateNativeApp } from "@vxrn/utils/nativeAppManifest";
7
7
  import FSExtra from "fs-extra";
8
8
  import sharp from "sharp";
9
9
  import { swiftPackageDirectories } from "../utils/swiftPackageId.mjs";
@@ -1731,58 +1731,37 @@ ${phoneOrientations.map((orientation) => ` <string>${orientation}</string>`).jo
1731
1731
  ${anchor}`);
1732
1732
  }
1733
1733
  }
1734
- if (platform === "android" && relativePath === "app/src/main/AndroidManifest.xml" && (app.imagePicker?.camera !== void 0 || app.speech !== void 0)) {
1735
- const anchor = "<uses-permission android:name=\"android.permission.INTERNET\" />";
1736
- if (!rendered.includes(anchor)) {
1737
- throw new Error("[vxrn] cannot stamp the camera or microphone permission: expected the INTERNET permission in app/src/main/AndroidManifest.xml");
1738
- }
1739
- const stamps = [];
1740
- if (app.imagePicker?.camera !== void 0) {
1741
- stamps.push(" <uses-permission android:name=\"android.permission.CAMERA\" />");
1734
+ if (platform === "android" && relativePath === "app/src/main/AndroidManifest.xml") {
1735
+ const permissions = androidAppPermissions(app);
1736
+ if (permissions.size || app.android?.blockedPermissions?.length) {
1737
+ const anchor = "<uses-permission android:name=\"android.permission.INTERNET\" />";
1738
+ if (!rendered.includes(anchor)) {
1739
+ const feature = app.imagePicker?.camera !== void 0 || app.speech !== void 0 ? "the camera or microphone permission" : app.notifications !== void 0 ? "notification permissions" : "permissions";
1740
+ throw new Error(`[vxrn] cannot stamp ${feature}: expected the INTERNET permission in app/src/main/AndroidManifest.xml`);
1741
+ }
1742
+ const blocked = new Set((app.android?.blockedPermissions ?? []).map((name) => name.includes(".") ? name : `android.permission.${name}`));
1743
+ const lines = [...[...permissions].filter(([name]) => !blocked.has(name)).map(([name, maxSdk]) => ` <uses-permission android:name="${name}"${maxSdk === void 0 ? "" : ` android:maxSdkVersion="${maxSdk}"`} />`), ...(app.android?.blockedPermissions ?? []).map((name) => ` <uses-permission android:name="${name.includes(".") ? name : `android.permission.${name}`}" tools:node="remove" />`)];
1744
+ rendered = rendered.replace(anchor, `${anchor}
1745
+ ${lines.join("\n")}`);
1746
+ if (app.android?.blockedPermissions?.length && !rendered.includes("xmlns:tools=")) {
1747
+ rendered = rendered.replace("xmlns:android=\"http://schemas.android.com/apk/res/android\"", "xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmlns:tools=\"http://schemas.android.com/tools\"");
1748
+ }
1742
1749
  }
1743
1750
  if (app.speech !== void 0) {
1744
- stamps.push(" <uses-permission android:name=\"android.permission.RECORD_AUDIO\" />", " <queries>\n <intent>\n <action android:name=\"android.speech.RecognitionService\" />\n </intent>\n </queries>");
1745
- }
1746
- rendered = rendered.replace(anchor, `${anchor}
1747
- ${stamps.join("\n")}`);
1748
- }
1749
- if (platform === "android" && relativePath === "app/src/main/AndroidManifest.xml" && app.location !== void 0) {
1750
- const anchor = "<uses-permission android:name=\"android.permission.INTERNET\" />";
1751
- if (!rendered.includes(anchor)) {
1752
- throw new Error("[vxrn] cannot stamp location permissions: expected the INTERNET permission in app/src/main/AndroidManifest.xml");
1753
- }
1754
- const stamps = [" <uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\" />", " <uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\" />"];
1755
- if (app.location.background) {
1756
- stamps.push(" <uses-permission android:name=\"android.permission.ACCESS_BACKGROUND_LOCATION\" />");
1757
- }
1758
- rendered = rendered.replace(anchor, `${anchor}
1759
- ${stamps.join("\n")}`);
1760
- }
1761
- if (platform === "android" && relativePath === "app/src/main/AndroidManifest.xml" && app.pedometer !== void 0) {
1762
- const anchor = "<uses-permission android:name=\"android.permission.INTERNET\" />";
1763
- if (!rendered.includes(anchor)) {
1764
- throw new Error("[vxrn] cannot stamp the pedometer permission: expected the INTERNET permission in app/src/main/AndroidManifest.xml");
1765
- }
1766
- rendered = rendered.replace(anchor, `${anchor}
1767
- <uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />`);
1768
- }
1769
- if (platform === "android" && relativePath === "app/src/main/AndroidManifest.xml" && app.brightness === true) {
1770
- const anchor = "<uses-permission android:name=\"android.permission.INTERNET\" />";
1771
- if (!rendered.includes(anchor)) {
1772
- throw new Error("[vxrn] cannot stamp the brightness permission: expected the INTERNET permission in app/src/main/AndroidManifest.xml");
1751
+ const anchor = "<uses-permission android:name=\"android.permission.INTERNET\" />";
1752
+ rendered = rendered.replace(anchor, `${anchor}
1753
+ <queries>
1754
+ <intent>
1755
+ <action android:name="android.speech.RecognitionService" />
1756
+ </intent>
1757
+ </queries>`);
1773
1758
  }
1774
- rendered = rendered.replace(anchor, `${anchor}
1775
- <uses-permission android:name="android.permission.WRITE_SETTINGS" />`);
1776
1759
  }
1777
1760
  if (platform === "android" && relativePath === "app/src/main/AndroidManifest.xml" && app.notifications !== void 0) {
1778
1761
  const anchor = "<uses-permission android:name=\"android.permission.INTERNET\" />";
1779
1762
  if (!rendered.includes(anchor)) {
1780
1763
  throw new Error("[vxrn] cannot stamp notification permissions: expected the INTERNET permission in app/src/main/AndroidManifest.xml");
1781
1764
  }
1782
- rendered = rendered.replace(anchor, [anchor, ...notificationsHost.androidPermissions.map((permission) => ` <uses-permission android:name="${permission}" />`)].join("\n"));
1783
- if (!rendered.includes(notificationsHost.androidPermissions[0])) {
1784
- throw new Error("[vxrn] failed to stamp notification permissions into app manifest");
1785
- }
1786
1765
  rendered = rendered.replace(" </activity>\n </application>", ` </activity>
1787
1766
  <receiver android:name="${notificationsHost.receiver}" android:exported="false">
1788
1767
  <intent-filter>
@@ -1815,37 +1794,6 @@ ${stamps.join("\n")}`);
1815
1794
  if (!rendered.includes(anchor)) {
1816
1795
  throw new Error("[vxrn] cannot stamp media permissions: expected the INTERNET permission in app/src/main/AndroidManifest.xml");
1817
1796
  }
1818
- const stamps = [];
1819
- if (app.audio?.microphone !== void 0 && !rendered.includes("android.permission.RECORD_AUDIO")) {
1820
- stamps.push(" <uses-permission android:name=\"android.permission.RECORD_AUDIO\" />");
1821
- }
1822
- if (app.photoLibrary?.readWrite !== void 0) {
1823
- stamps.push(" <uses-permission android:name=\"android.permission.READ_MEDIA_IMAGES\" />", " <uses-permission android:name=\"android.permission.READ_MEDIA_VIDEO\" />", " <uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\" android:maxSdkVersion=\"32\" />");
1824
- }
1825
- if (app.photoLibrary?.addOnly !== void 0) {
1826
- stamps.push(" <uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" android:maxSdkVersion=\"28\" />");
1827
- }
1828
- if (app.contacts !== void 0) {
1829
- stamps.push(" <uses-permission android:name=\"android.permission.READ_CONTACTS\" />", " <uses-permission android:name=\"android.permission.WRITE_CONTACTS\" />");
1830
- }
1831
- if (app.calendar?.usage !== void 0) {
1832
- stamps.push(" <uses-permission android:name=\"android.permission.READ_CALENDAR\" />", " <uses-permission android:name=\"android.permission.WRITE_CALENDAR\" />");
1833
- }
1834
- if (app.calendar?.remindersUsage !== void 0) {
1835
- if (!rendered.includes("android.permission.POST_NOTIFICATIONS")) {
1836
- stamps.push(" <uses-permission android:name=\"android.permission.POST_NOTIFICATIONS\" />");
1837
- }
1838
- if (!rendered.includes("android.permission.RECEIVE_BOOT_COMPLETED")) {
1839
- stamps.push(" <uses-permission android:name=\"android.permission.RECEIVE_BOOT_COMPLETED\" />");
1840
- }
1841
- }
1842
- if (app.audio?.background === true) {
1843
- stamps.push(" <uses-permission android:name=\"android.permission.FOREGROUND_SERVICE\" />", " <uses-permission android:name=\"android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK\" />");
1844
- }
1845
- if (stamps.length) {
1846
- rendered = rendered.replace(anchor, `${anchor}
1847
- ${stamps.join("\n")}`);
1848
- }
1849
1797
  const appStamps = [];
1850
1798
  if (app.calendar?.remindersUsage !== void 0) {
1851
1799
  appStamps.push(" <meta-data android:name=\"one.calendar.reminders\" android:value=\"true\" />");
@@ -1933,19 +1881,6 @@ ${line}
1933
1881
  }
1934
1882
  rendered = rendered.replace(dayNight, app.userInterfaceStyle === "light" ? "parent=\"Theme.AppCompat.Light.NoActionBar\"" : "parent=\"Theme.AppCompat.NoActionBar\"");
1935
1883
  }
1936
- if (platform === "android" && relativePath === "app/src/main/AndroidManifest.xml" && (app.android?.permissions?.length || app.android?.blockedPermissions?.length)) {
1937
- const anchor = "<uses-permission android:name=\"android.permission.INTERNET\" />";
1938
- if (!rendered.includes(anchor)) {
1939
- throw new Error("[vxrn] cannot stamp permissions: expected the INTERNET permission in app/src/main/AndroidManifest.xml");
1940
- }
1941
- const permissionName = (name) => name.includes(".") ? name : `android.permission.${name}`;
1942
- const lines = [...(app.android?.permissions ?? []).map((name) => ` <uses-permission android:name="${permissionName(name)}" />`), ...(app.android?.blockedPermissions ?? []).map((name) => ` <uses-permission android:name="${permissionName(name)}" tools:node="remove" />`)];
1943
- rendered = rendered.replace(anchor, `${anchor}
1944
- ${lines.join("\n")}`);
1945
- if (app.android?.blockedPermissions?.length && !rendered.includes("xmlns:tools=")) {
1946
- rendered = rendered.replace("xmlns:android=\"http://schemas.android.com/apk/res/android\"", "xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmlns:tools=\"http://schemas.android.com/tools\"");
1947
- }
1948
- }
1949
1884
  if (platform === "android" && relativePath === "app/src/main/AndroidManifest.xml" && app.android?.appLinks?.length) {
1950
1885
  rendered = rendered.replace(" </activity>", ` <intent-filter android:autoVerify="true">
1951
1886
  <action android:name="android.intent.action.VIEW" />