1"use strict";
2
3// Ships the knife silhouette to the Live Activity / widget extension.
4//
5// expo-widgets generates ExpoWidgetsTarget without a Resources build phase and
6// has no asset support, so this plugin (a) writes a template image set into
7// the generated widget asset catalog and (b) wires that catalog into the widget
8// target with an actool build phase.
9//
10// ORDERING: must be listed BEFORE "expo-widgets" in the plugins array. Expo
11// chains same-type mods so the last-registered runs FIRST; registering this
12// plugin earlier makes its mods run AFTER expo-widgets' mods. That matters
13// twice: expo-widgets' dangerous mod rmSync's ios/ExpoWidgetsTarget/ (deleting
14// any catalog written before it), and its xcodeproj mod is what creates the
15// widget target. Listed after expo-widgets, both steps silently no-op on a
16// fresh prebuild — which is how prod build 8 shipped without the logo.
17
18const path = require("path");
19const fs = require("fs");
20const { withDangerousMod, withXcodeProject } = require("expo/config-plugins");
21const { addWidgetAssetCatalog } = require("./lib/addWidgetAssetCatalog.cjs");
22
23const TARGET_NAME = "ExpoWidgetsTarget";
24const CATALOG_NAME = "Assets.xcassets";
25const IMAGE_SET = "KnifeMark.imageset";
26const IMAGE_NAME = "knife.png";
27
28const CATALOG_CONTENTS = JSON.stringify({ info: { author: "expo", version: 1 } }, null, 2) + "\n";
29const IMAGE_SET_CONTENTS =
30 JSON.stringify(
31 {
32 images: [{ idiom: "universal", filename: IMAGE_NAME }],
33 info: { author: "expo", version: 1 },
34 properties: {
35 "template-rendering-intent": "template",
36 },
37 },
38 null,
39 2,
40 ) + "\n";
41
42function withAssetFiles(config) {
43 return withDangerousMod(config, [
44 "ios",
45 (cfg) => {
46 const source = path.resolve(
47 cfg.modRequest.projectRoot,
48 "../../assets/knife/android-foreground.png",
49 );
50 const catalogDir = path.join(cfg.modRequest.platformProjectRoot, TARGET_NAME, CATALOG_NAME);
51 const imageSetDir = path.join(catalogDir, IMAGE_SET);
52 fs.mkdirSync(imageSetDir, { recursive: true });
53 fs.writeFileSync(path.join(catalogDir, "Contents.json"), CATALOG_CONTENTS);
54 fs.writeFileSync(path.join(imageSetDir, "Contents.json"), IMAGE_SET_CONTENTS);
55 fs.copyFileSync(source, path.join(imageSetDir, IMAGE_NAME));
56 return cfg;
57 },
58 ]);
59}
60
61function withAssetWiring(config) {
62 return withXcodeProject(config, (cfg) => {
63 addWidgetAssetCatalog(cfg.modResults, { targetName: TARGET_NAME });
64 return cfg;
65 });
66}
67
68module.exports = function withWidgetLogoAsset(config) {
69 return withAssetWiring(withAssetFiles(config));
70};