Files
Felitendo 8b06b305f5 feat: give the manager the island the app has
FTStore Manager puts an app on a device through the same three stages FTStore
does, and had nothing to show for any of it once the screen was off. It has a
Live Activity now: the same widget the app carries, embedded as its own
extension under its own identifier, naming the app, filling a bar while the
bytes arrive, adding the rate and the time left, then Preparing and Installing.

It is the app's island with the pause button taken out. This download manager
has no pause and no screen to offer one from, so there are no intents to compile
into the extension and no paused state in the payload. The island is read-only
on every version rather than only on the older ones.

It ends when the installer answers, which is the part the app had to learn the
hard way. Open launches what was just installed and leaves the sheet standing
behind it, so ending on dismissal left the island describing an install that had
finished, until somebody came back and closed a receipt they were done with.
Dismissal still ends it, which is what covers a flow that never gets an answer
at all.

A dropped connection is now one of those answers. It used to remove the download
and tell nobody, leaving the flow spinning with no way to find out; that was
merely invisible before and would now be an island counting bytes that stopped
arriving.

None of this is visible from a build: an IPA whose extension is missing, misnamed
or misfiled installs, runs, and simply shows no island. Both of the Manager's
release workflows therefore run the same check the app's do against the built
IPA, and the ad-hoc signing step seals the nested extension. Two products now
build an extension of the same name out of projects that share their
identifiers, so the separate derived data paths carry more weight than before,
and the notes that explain them say so.
2026-09-01 08:35:02 +02:00

85 lines
3.2 KiB
Makefile

NAME := FTStore
SCHEME := FTStore
PLATFORMS := iphoneos maccatalyst
# Derived data is keyed on the product directory, never on $(NAME) alone: this
# tree is a fork of ios/, down to the pbxproj GUIDs Xcode's build database is
# keyed on, so a shared $(TMPDIR)/FTStore made the two builds indistinguishable
# to it. See the longer note in ios/Makefile — that side is the one that lost
# its Live Activity extension to this build's stale-file sweep, back when this
# build had none. Both products carry an FTStoreActivity now, so they would
# overwrite each other's rather than one deleting the other.
TMP := $(TMPDIR)/$(NAME)-$(notdir $(CURDIR))
CERT_JSON_URL := https://backloop.dev/pack.json
.PHONY: all clean deps $(PLATFORMS)
all: $(PLATFORMS)
clean:
rm -rf $(TMP)
rm -rf packages
rm -rf Payload
deps:
rm -rf deps || true
mkdir -p deps
curl -fsSL "$(CERT_JSON_URL)" -o cert.json
# `.ca` too: iOS refuses a chain it cannot complete, and the leaf on its own
# is one of the ways a Server install sits on "Ready" until it is dismissed.
# `-j` because the key is split across two fields to get it past secret
# scanning, and the halves join with nothing between them; the newline `-r`
# adds lands mid-line and corrupts the PEM.
jq -r '.cert, .ca' cert.json > deps/server.crt
jq -rj '.key1, .key2' cert.json > deps/server.pem
jq -r '.info.domains.commonName' cert.json > deps/commonName.txt
# `Package.resolved` is the build, and the flag below is what makes that true.
#
# Nothing here changed and the build broke anyway: BitByteData published 2.1.0,
# which raises its own floor to iOS 17, and SWCompression asks for it with an
# open `from: "2.0.0"`. Xcode resolved past the committed pin of 2.0.4, took the
# new one, and then refused the graph it had just built — SWCompression's own
# manifest says iOS 11, so a dependency needing 17 cannot go under it. The app's
# deployment target is not part of that arithmetic and raising it fixes nothing.
#
# `-onlyUsePackageVersionsFromResolvedFile` forbids the drift instead of
# reacting to it: every version comes from the checked-in file, and a dependency
# missing from it fails the build rather than being invented. The cost is that
# adding or moving a package means resolving it in Xcode and committing the
# result, which is the point.
$(PLATFORMS): deps
rm -rf _build
@if [ "$@" = "iphoneos" ]; then \
DEST="generic/platform=iOS"; \
else \
DEST="generic/platform=macOS,variant=Mac Catalyst"; \
fi; \
xcodebuild \
-project FTStore.xcodeproj \
-scheme $(SCHEME) \
-configuration Release \
-destination "$$DEST" \
-derivedDataPath $(TMP)/$@ \
-skipPackagePluginValidation \
-onlyUsePackageVersionsFromResolvedFile \
CODE_SIGNING_ALLOWED=NO \
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES=NO
mkdir -p _build/Payload
cp -R _build/Applications/*.app _build/Payload/FTStore.app
chmod -R 0755 _build/Payload/FTStore.app
codesign --force --deep --sign - --timestamp=none _build/Payload/FTStore.app
cp deps/* _build/Payload/FTStore.app/ || true
mkdir -p packages
@if [ "$@" = "iphoneos" ]; then \
ditto -c -k --sequesterRsrc --keepParent _build/Payload "packages/FTStore-Manager.ipa"; \
else \
ditto -c -k --sequesterRsrc --keepParent _build/Payload/FTStore.app "packages/FTStore_Catalyst.zip"; \
fi