PMA.SyncClient now speaks two transports, told apart by the URL:
/api/v1/repos/ means the Gitea contents API, anything else the old PHP
endpoint. The PHP path stays until the Windows side publishes to the repo
too - without it the migration would need both ends flipped at once, with
no way back.
Three things differ on the Gitea side and nothing else: the header is
"token <PAT>" not "Bearer" (swapping them gives a silent 401), the body is
JSON carrying base64 content, and the fingerprint comparison happens in the
client since the API has no If-None-Match. The body is re-downloaded, which
is cheap; the four-second key derivation is still avoided. The result's
ETag field carries the sha, so the caller cannot tell which transport
answered.
usesCleartextTraffic is replaced by a network config that permits cleartext
to 127.0.0.1 and localhost BY NAME and forbids it everywhere else. The
attribute drew no such line: a mistyped URL sent the bearer token over the
network in the clear with nothing to signal it. Now it fails immediately,
which is the behaviour worth having.
Verified in the built APK: res/xml/network_security_config.xml is present
and the manifest attribute resolves to a real resource id. NOT verified
against a real repo - that needs a private repo, a published
vault-sync.json and a token, none of which exist yet.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The padlock was drawn in thin blue strokes on slate: at 36 px the outline muddied and the shackle vanished. A filled white shield with a punched keyhole keeps its silhouette at every size, and says protection more plainly.
The keyhole is CUT OUT rather than painted, through an even-odd fill on a single path - painting it meant keeping two files agreeing on one colour, and any drift would have read as a smudge. The launch layer is the exception: it sits flat on the system background, where a cut-out would be a hole, so there the keyhole is painted and stays entirely inside the white shield.
The launch background takes the top of the app gradient instead of slate, so the launch screen dissolves into the first screen rather than cutting against it. No gradient inside the vectors: the aapt this chain uses does not know inline gradients.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Cyan came from the desktop app. On the phone the reference is the system: its global search and its own apps are blue, and an app should look like the place it runs.
Accent #3B82F6 on the same slate, with white on the accent since blue is darker than cyan. The launcher icon and the launch screen follow - a cyan padlock in front of a blue interface would have read as a different app.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The launcher icon and the launch screen are different resources. On Android 12+ the theme points windowSplashScreenAnimatedIcon at splash_vector, which was Delphi's logo, over a #FFF background - a white flash before a dark app, every single launch.
Same padlock, drawn at 288 units with its content inside the central 192 the system guarantees. splash_background goes slate, in the light variant too since the app has only one theme. For Android 11 and earlier, which have no SplashScreen API and merely paint windowBackground, splash_image_def composes the background and the logo itself.
One source for the vector, copied onto the density and night variants by repack: four identical files in the repo would eventually diverge.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The rule exists for screenshots dropped in the repo root during dev. Launcher icons are content: they regenerate from make-icons.ps1, but tracking them means not having to know that - nor depending on System.Drawing to build an APK.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Cyan on slate, the accent the desktop app already uses. Adaptive vectors for
Android 8+ - background covering the full 108 units since the launcher applies
its own mask, foreground kept inside the central 66 that no mask can crop -
plus a monochrome layer for Android 13 themed icons, where the keyhole has to
be a hole in the path rather than a shape in another colour.
PNGs for older launchers come from make-icons.ps1, same drawing, and carry
their own rounded square since nothing masks them.
They are copied over Delphi's in repack-apk.ps1, for the same reason as
libsk4d.so: the Android_LauncherIcon and Android_AdaptiveIcon properties ought
to be enough, and nothing deploys them here.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>