vxrn 2.0.0-beta.132.1 → 2.0.0-beta.133.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.
@@ -335,7 +335,7 @@ ${renderPlistValue(value, indent)}`).join("\n");
335
335
  function appEntitlements(app) {
336
336
  const modeled = {};
337
337
  if (app.notifications?.push === true || app.ios?.widgets?.pushNotifications) {
338
- modeled["aps-environment"] = notificationsHost.apsEnvironment;
338
+ modeled["aps-environment"] = app.notifications?.apsEnvironment ?? notificationsHost.apsEnvironment;
339
339
  }
340
340
  if (app.ios?.widgets) {
341
341
  modeled["com.apple.security.application-groups"] = [app.ios.widgets.appGroup];
@@ -1098,6 +1098,52 @@ ${adaptiveIcon.monochrome ? " <monochrome android:drawable=\"@mipmap/ic_launc
1098
1098
  FSExtra.writeFileSync(path.join(anydpi, filename), adaptiveXml);
1099
1099
  }
1100
1100
  }
1101
+ const IOS_DARK_APPEARANCE = [{
1102
+ appearance: "luminosity",
1103
+ value: "dark"
1104
+ }];
1105
+ function srgb(hex) {
1106
+ return {
1107
+ red: Number.parseInt(hex.slice(1, 3), 16) / 255,
1108
+ green: Number.parseInt(hex.slice(3, 5), 16) / 255,
1109
+ blue: Number.parseInt(hex.slice(5, 7), 16) / 255
1110
+ };
1111
+ }
1112
+ function xcodeColorSet(light, dark) {
1113
+ const entry = (hex) => {
1114
+ const { red, green, blue } = srgb(hex);
1115
+ return {
1116
+ color: {
1117
+ "color-space": "srgb",
1118
+ components: {
1119
+ red: red.toFixed(3),
1120
+ green: green.toFixed(3),
1121
+ blue: blue.toFixed(3),
1122
+ alpha: "1.000"
1123
+ }
1124
+ },
1125
+ idiom: "universal"
1126
+ };
1127
+ };
1128
+ return `${JSON.stringify({
1129
+ colors: [entry(light), ...dark ? [{
1130
+ appearances: IOS_DARK_APPEARANCE,
1131
+ ...entry(dark)
1132
+ }] : []],
1133
+ info: {
1134
+ author: "xcode",
1135
+ version: 1
1136
+ }
1137
+ }, null, 2)}
1138
+ `;
1139
+ }
1140
+ function generateAccentColor(args) {
1141
+ const accent = args.app.ios?.accentColor;
1142
+ if (!accent) return;
1143
+ const colorDir = path.join(args.dest, args.app.name, "Images.xcassets", "AccentColor.colorset");
1144
+ FSExtra.mkdirSync(colorDir, { recursive: true });
1145
+ FSExtra.writeFileSync(path.join(colorDir, "Contents.json"), xcodeColorSet(accent.light, accent.dark));
1146
+ }
1101
1147
  async function generateSplashScreen(args) {
1102
1148
  const { root, dest, platform, app } = args;
1103
1149
  if (!app.splash) return;
@@ -1107,7 +1153,9 @@ async function generateSplashScreen(args) {
1107
1153
  if (!FSExtra.existsSync(source)) {
1108
1154
  throw new Error(`[vxrn] native.app.splash source does not exist: ${source}`);
1109
1155
  }
1110
- const image = sharp(source).rotate();
1156
+ const { width: sourceWidth, format } = await sharp(source).metadata();
1157
+ const density = format === "svg" && sourceWidth && !cover ? Math.min(2400, Math.ceil(72 * 4 * (app.splash?.width ?? 200) / sourceWidth)) : void 0;
1158
+ const image = sharp(source, density ? { density } : {}).rotate();
1111
1159
  const prepared = await (cover ? image : image.trim({ background: backgroundColor })).png().toBuffer({ resolveWithObject: true });
1112
1160
  if (!prepared.info.width || !prepared.info.height) {
1113
1161
  throw new Error("[vxrn] native.app.splash source must be an image");
@@ -1121,64 +1169,63 @@ async function generateSplashScreen(args) {
1121
1169
  const artworkHeight = Number((artworkWidth * (metadata.height / metadata.width)).toFixed(3));
1122
1170
  if (platform === "ios") {
1123
1171
  const appDir = path.join(dest, app.name);
1124
- const splashDir = path.join(appDir, "Images.xcassets", "Splash.imageset");
1125
- FSExtra.mkdirSync(splashDir, { recursive: true });
1126
- const darkAppearance = [{
1127
- appearance: "luminosity",
1128
- value: "dark"
1129
- }];
1130
- await sharp(artwork).toFile(path.join(splashDir, "splash.png"));
1131
- if (darkArtwork) await sharp(darkArtwork).toFile(path.join(splashDir, "splash-dark.png"));
1132
- FSExtra.writeFileSync(path.join(splashDir, "Contents.json"), `${JSON.stringify({
1133
- images: [{
1134
- filename: "splash.png",
1135
- idiom: "universal",
1136
- scale: "1x"
1137
- }, ...darkArtwork ? [{
1138
- appearances: darkAppearance,
1139
- filename: "splash-dark.png",
1140
- idiom: "universal",
1141
- scale: "1x"
1142
- }] : []],
1143
- info: {
1144
- author: "xcode",
1145
- version: 1
1146
- }
1147
- }, null, 2)}
1172
+ const assets = path.join(appDir, "Images.xcassets");
1173
+ const writeImageSet = async (name, light, dark2, pointWidth) => {
1174
+ const dir = path.join(assets, `${name}.imageset`);
1175
+ FSExtra.mkdirSync(dir, { recursive: true });
1176
+ const scales = pointWidth === void 0 ? [1] : [
1177
+ 1,
1178
+ 2,
1179
+ 3
1180
+ ];
1181
+ const images = [];
1182
+ for (const [variant, suffix, appearances] of [[
1183
+ light,
1184
+ "",
1185
+ void 0
1186
+ ], [
1187
+ dark2,
1188
+ "-dark",
1189
+ IOS_DARK_APPEARANCE
1190
+ ]]) {
1191
+ if (!variant) continue;
1192
+ for (const scale of scales) {
1193
+ const filename = `${name.toLowerCase()}${suffix}${scale === 1 ? "" : `@${scale}x`}.png`;
1194
+ const output = sharp(variant);
1195
+ await (pointWidth === void 0 ? output : output.resize({ width: Math.round(pointWidth * scale) })).png().toFile(path.join(dir, filename));
1196
+ images.push({
1197
+ ...appearances ? { appearances } : {},
1198
+ filename,
1199
+ idiom: "universal",
1200
+ scale: `${scale}x`
1201
+ });
1202
+ }
1203
+ }
1204
+ FSExtra.writeFileSync(path.join(dir, "Contents.json"), `${JSON.stringify({
1205
+ images,
1206
+ info: {
1207
+ author: "xcode",
1208
+ version: 1
1209
+ }
1210
+ }, null, 2)}
1148
1211
  `);
1149
- const srgb = (hex) => ({
1150
- red: Number.parseInt(hex.slice(1, 3), 16) / 255,
1151
- green: Number.parseInt(hex.slice(3, 5), 16) / 255,
1152
- blue: Number.parseInt(hex.slice(5, 7), 16) / 255
1153
- });
1154
- const colorEntry = (hex) => {
1155
- const { red: red2, green: green2, blue: blue2 } = srgb(hex);
1156
- return {
1157
- color: {
1158
- "color-space": "srgb",
1159
- components: {
1160
- red: red2.toFixed(3),
1161
- green: green2.toFixed(3),
1162
- blue: blue2.toFixed(3),
1163
- alpha: "1.000"
1164
- }
1165
- },
1166
- idiom: "universal"
1167
- };
1168
1212
  };
1169
- const colorDir = path.join(appDir, "Images.xcassets", "SplashBackground.colorset");
1213
+ await writeImageSet("Splash", artwork, darkArtwork, cover ? void 0 : artworkWidth);
1214
+ const readBackground = (sourcePath) => {
1215
+ const source = path.resolve(root, sourcePath);
1216
+ if (!FSExtra.existsSync(source)) {
1217
+ throw new Error(`[vxrn] native.app.splash backgroundImage does not exist: ${source}`);
1218
+ }
1219
+ return sharp(source).rotate().png().toBuffer({ resolveWithObject: true });
1220
+ };
1221
+ const background = app.splash.backgroundImage ? await readBackground(app.splash.backgroundImage) : void 0;
1222
+ const darkBackground = dark?.backgroundImage ? (await readBackground(dark.backgroundImage)).data : void 0;
1223
+ if (background) {
1224
+ await writeImageSet("SplashBackgroundImage", background.data, darkBackground, void 0);
1225
+ }
1226
+ const colorDir = path.join(assets, "SplashBackground.colorset");
1170
1227
  FSExtra.mkdirSync(colorDir, { recursive: true });
1171
- FSExtra.writeFileSync(path.join(colorDir, "Contents.json"), `${JSON.stringify({
1172
- colors: [colorEntry(app.splash.backgroundColor), ...dark ? [{
1173
- appearances: darkAppearance,
1174
- ...colorEntry(dark.backgroundColor)
1175
- }] : []],
1176
- info: {
1177
- author: "xcode",
1178
- version: 1
1179
- }
1180
- }, null, 2)}
1181
- `);
1228
+ FSExtra.writeFileSync(path.join(colorDir, "Contents.json"), xcodeColorSet(app.splash.backgroundColor, dark?.backgroundColor));
1182
1229
  const { red, green, blue } = srgb(app.splash.backgroundColor);
1183
1230
  FSExtra.writeFileSync(path.join(appDir, "LaunchScreen.storyboard"), `<?xml version="1.0" encoding="UTF-8"?>
1184
1231
  <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15702" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="launch-controller">
@@ -1194,11 +1241,16 @@ async function generateSplashScreen(args) {
1194
1241
  <viewController id="launch-controller" sceneMemberID="viewController">
1195
1242
  <view key="view" contentMode="scaleToFill" id="launch-view">
1196
1243
  <rect key="frame" x="0.0" y="0.0" width="390" height="844"/>
1197
- <subviews>
1244
+ <subviews>${background ? `
1245
+ <imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" image="SplashBackgroundImage" translatesAutoresizingMaskIntoConstraints="NO" id="splash-background"/>` : ""}
1198
1246
  <imageView userInteractionEnabled="NO" contentMode="${cover ? "scaleAspectFill" : "scaleAspectFit"}" image="Splash" translatesAutoresizingMaskIntoConstraints="NO" id="splash-image"/>
1199
1247
  </subviews>
1200
1248
  <color key="backgroundColor" name="SplashBackground"/>
1201
- <constraints>
1249
+ <constraints>${background ? `
1250
+ <constraint firstItem="splash-background" firstAttribute="leading" secondItem="launch-view" secondAttribute="leading" id="splash-background-leading"/>
1251
+ <constraint firstItem="splash-background" firstAttribute="trailing" secondItem="launch-view" secondAttribute="trailing" id="splash-background-trailing"/>
1252
+ <constraint firstItem="splash-background" firstAttribute="top" secondItem="launch-view" secondAttribute="top" id="splash-background-top"/>
1253
+ <constraint firstItem="splash-background" firstAttribute="bottom" secondItem="launch-view" secondAttribute="bottom" id="splash-background-bottom"/>` : ""}
1202
1254
  ${cover ? ` <constraint firstItem="splash-image" firstAttribute="leading" secondItem="launch-view" secondAttribute="leading" id="splash-leading"/>
1203
1255
  <constraint firstItem="splash-image" firstAttribute="trailing" secondItem="launch-view" secondAttribute="trailing" id="splash-trailing"/>
1204
1256
  <constraint firstItem="splash-image" firstAttribute="top" secondItem="launch-view" secondAttribute="top" id="splash-top"/>
@@ -1214,7 +1266,8 @@ ${cover ? ` <constraint firstItem="splash-image" firstAttribute="le
1214
1266
  </scene>
1215
1267
  </scenes>
1216
1268
  <resources>
1217
- <image name="Splash" width="${metadata.width}" height="${metadata.height}"/>
1269
+ <image name="Splash" width="${cover ? metadata.width : artworkWidth}" height="${cover ? metadata.height : artworkHeight}"/>${background ? `
1270
+ <image name="SplashBackgroundImage" width="${background.info.width}" height="${background.info.height}"/>` : ""}
1218
1271
  <namedColor name="SplashBackground">
1219
1272
  <color red="${red}" green="${green}" blue="${blue}" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
1220
1273
  </namedColor>
@@ -1334,6 +1387,9 @@ ${schemes.map((scheme) => ` <string>${scheme}</string>`).join("\n")}
1334
1387
  stamps.push(` <key>ITSAppUsesNonExemptEncryption</key>
1335
1388
  <${app.ios.usesNonExemptEncryption ? "true" : "false"}/>`);
1336
1389
  }
1390
+ if (app.ios?.accentColor) {
1391
+ stamps.push(" <key>NSAccentColorName</key>\n <string>AccentColor</string>");
1392
+ }
1337
1393
  if (app.ios?.fileSharing) {
1338
1394
  stamps.push(` <key>UIFileSharingEnabled</key>
1339
1395
  <true/>
@@ -1797,6 +1853,10 @@ const generateForPlatform = async (root, platform, app, outDir = path.resolve(ro
1797
1853
  platform,
1798
1854
  app
1799
1855
  });
1856
+ if (platform === "ios") generateAccentColor({
1857
+ dest,
1858
+ app
1859
+ });
1800
1860
  copyAppResources({
1801
1861
  root,
1802
1862
  dest,