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.
85 lines
3.2 KiB
Makefile
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
|