| author | |
| committer | |
| log | bdf5aed665a91f2e1755e6a8ef72cd29627fa937 |
| tree | 98b44932511d2192b2e75fd429a811dff9d2921b |
| parent | 0b62e2eb116abaaaafcb839c24accbbf5aba6a3c |
| signature | Signed by PGP key B5690EEEBB952194 |
4 files changed, 29 insertions(+), 12 deletions(-)
apps/mobile/app.config.ts+6-3| ... | ... | @@ -159,6 +159,12 @@ const config: ExpoConfig = { |
| 159 | 159 | }, |
| 160 | 160 | ], |
| 161 | 161 | "./plugins/withIosCocoaPodsUuidCache.cjs", |
| 162 | // Must be listed BEFORE expo-widgets: same-type mods run last-registered- | |
| 163 | // first, so registering earlier makes this plugin's mods run AFTER | |
| 164 | // expo-widgets' — its dangerous mod wipes ios/ExpoWidgetsTarget/ (which | |
| 165 | // would delete the asset catalog) and its xcodeproj mod creates the widget | |
| 166 | // target (which must exist before the compile phase can be attached). | |
| 167 | "./plugins/withWidgetLogoAsset.cjs", | |
| 162 | 168 | [ |
| 163 | 169 | "expo-widgets", |
| 164 | 170 | { |
| ... | ... | @@ -178,9 +184,6 @@ const config: ExpoConfig = { |
| 178 | 184 | ], |
| 179 | 185 | }, |
| 180 | 186 | ], |
| 181 | // Must run after expo-widgets so the widget target exists when it wires in | |
| 182 | // the branded logo asset catalog. | |
| 183 | "./plugins/withWidgetLogoAsset.cjs", | |
| 184 | 187 | "./plugins/withIosSceneLifecycle.cjs", |
| 185 | 188 | "./plugins/withAndroidCleartextTraffic.cjs", |
| 186 | 189 | ], |
apps/mobile/plugins/lib/addWidgetAssetCatalog.cjs+13-5| ... | ... | @@ -9,8 +9,10 @@ |
| 9 | 9 | // drops the compiled Assets.car into the extension bundle. Marked |
| 10 | 10 | // alwaysOutOfDate so the build system always runs it. |
| 11 | 11 | // |
| 12 | // Idempotent across re-runs. Returns true when it added the phase, false when it | |
| 13 | // was already present or the target was not found. | |
| 12 | // Idempotent across re-runs. Returns true when it added the phase, false when | |
| 13 | // it was already present. Throws when the target does not exist — that means | |
| 14 | // this ran before expo-widgets created the target (plugin ordering bug) and | |
| 15 | // silently skipping would ship a widget without its assets. | |
| 14 | 16 | |
| 15 | 17 | const PHASE_NAME = "Compile Widget Assets"; |
| 16 | 18 | |
| ... | ... | @@ -20,8 +22,8 @@ const ACTOOL_SCRIPT = [ |
| 20 | 22 | "set -e", |
| 21 | 23 | 'CATALOG="${SRCROOT}/ExpoWidgetsTarget/Assets.xcassets"', |
| 22 | 24 | 'if [ ! -d "$CATALOG" ]; then', |
| 23 | ' echo "warning: widget asset catalog not found at $CATALOG"', | |
| 24 | " exit 0", | |
| 25 | ' echo "error: widget asset catalog not found at $CATALOG (expo-widgets wiped it? check plugin ordering in app.config.ts)"', | |
| 26 | " exit 1", | |
| 25 | 27 | "fi", |
| 26 | 28 | 'DEST="${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"', |
| 27 | 29 | 'mkdir -p "$DEST"', |
| ... | ... | @@ -51,7 +53,13 @@ function findByName(map, name) { |
| 51 | 53 | function addWidgetAssetCatalog(proj, opts) { |
| 52 | 54 | const objects = proj.hash.project.objects; |
| 53 | 55 | const target = findByName(objects.PBXNativeTarget, opts.targetName); |
| 54 | if (!target) return false; | |
| 56 | if (!target) { | |
| 57 | throw new Error( | |
| 58 | `addWidgetAssetCatalog: target "${opts.targetName}" not found — ` + | |
| 59 | "withWidgetLogoAsset must be registered before expo-widgets so its " + | |
| 60 | "xcodeproj mod runs after the widget target is created.", | |
| 61 | ); | |
| 62 | } | |
| 55 | 63 | |
| 56 | 64 | const phases = target.value.buildPhases || []; |
| 57 | 65 | const existing = objects.PBXShellScriptBuildPhase || {}; |
apps/mobile/plugins/withWidgetLogoAsset.cjs+9-3| ... | ... | @@ -5,9 +5,15 @@ |
| 5 | 5 | // expo-widgets generates ExpoWidgetsTarget without a Resources build phase and |
| 6 | 6 | // has no asset support, so this plugin (a) writes an SVG template image set into |
| 7 | 7 | // the generated widget asset catalog and (b) wires that catalog into the widget |
| 8 | // target with a dedicated Resources build phase. Both steps are idempotent and | |
| 9 | // survive `expo prebuild --clean`. Must be listed AFTER "expo-widgets" in the | |
| 10 | // plugins array so the widget target exists when this runs. | |
| 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. | |
| 11 | 17 | |
| 12 | 18 | const path = require("path"); |
| 13 | 19 | const fs = require("fs"); |
apps/mobile/scripts/wire-widget-asset-catalog.cjs+1-1| ... | ... | @@ -26,5 +26,5 @@ if (added) { |
| 26 | 26 | fs.writeFileSync(pbxprojPath, proj.writeSync()); |
| 27 | 27 | console.log("Added widget asset-compile phase to ExpoWidgetsTarget."); |
| 28 | 28 | } else { |
| 29 | console.log("No change: phase already present or target not found."); | |
| 29 | console.log("No change: phase already present."); | |
| 30 | 30 | } |