Skip to content

Redraw the monochrome icon and the header ambiences, and compare the installed manager - #849

Merged
JingMatrix merged 4 commits into
masterfrom
ambience-cosmetics
Aug 3, 2026
Merged

Redraw the monochrome icon and the header ambiences, and compare the installed manager#849
JingMatrix merged 4 commits into
masterfrom
ambience-cosmetics

Conversation

@JingMatrix

Copy link
Copy Markdown
Owner

Four changes, three of them cosmetic.

The monochrome icon was a flat blob traced round the winged victory, so neither the themed launcher icon nor the status notification said what the statue is. It now carries the statue's own line work, punched out of the silhouette so it stays solid at 24dp.

The circuit ambience routes its board on a lattice rather than scribbling it: no two traces share a line, a blocked one steps aside and carries on rather than stopping mid-header, corners are mitred, and the signal is a swell of current with a proper head. A vertical drag sets its speed, as with the rain and the snow.

The code rain takes its glyph size from how many columns fit across the header — thirty to a hundred and twenty, eighty at rest — rather than a fraction of its height, and lanes are spread by golden ratio so the field stops clumping.

Last, parasitically the "Install as an app" row went green as soon as the package existed, even when that copy was a different build. Version codes cannot tell those apart, so it now compares the two APKs by digest and offers a reinstall.

The themed launcher icon and the daemon's status notification both drew a
flat blob traced from the outline of ic_winged_victory, which told you
nothing about what the statue is.

Take the silhouette of the two-tone drawing instead and punch the statue's
own modelling out of it with evenOdd, so the wing feathers and the drapery
folds read at launcher size while the shape stays solid in the status bar.
The line work is curated down to twenty-five strokes: the contour-hugging
ones are dropped, the rest are thinned by spacing rather than by length so
the wing keeps its feathers, and each is widened to survive 24dp. The whole
path has to stay under 32767 bytes, which is where the resource string pool
gives up and writes STRING_TOO_LARGE instead.

Geometry is fitted to ic_winged_victory's bounding box, so the themed layer
still registers with the coloured one under the shared 25% inset.
Every trace used to start at a random height and wander rightwards in steps
of a random size, blind to the others. Traces landed on top of one another,
doubled up along the same line, crowded one half of the header and left the
other empty, and a trace that met one already drawn simply stopped where it
stood, hanging in the middle of the picture.

Route them on a lattice instead. Lanes are evenly spaced, traces run along
them and step between neighbours at the columns, and every run a trace
occupies is claimed, so no two are ever drawn along the same line. A trace
that meets copper already laid steps aside — one lane out, then two, then
three — and carries on to the right-hand side, crossing what is in its way:
a board has layers, a crossing reads as one of them, and without them the
lattice reads as a set of ruled lines. A trace that has drifted a couple of
lanes from where it started prefers the step back, which keeps the
horizontal grain a board has, and three in ten stop on a land short of the
edge rather than running off it, so both kinds of ending are visible.
Corners are mitred into the two 45° elbows a real router leaves behind, and
the vias move onto those elbows, where a board actually puts them.

The signal is a swell of current rather than a dot: a tapering ribbon filled
with a gradient, widest and brightest under the head and drawn down to
nothing behind, breathing a tenth of its width as it travels. A chain of
segments would have done, but it beads visibly once the stroke is wider than
the step between samples, and the ribbon costs nothing per frame — the path
and its far edge are kept between them. The head is the rounded end of that
body, not a ball towing it.

Signals also run a third slower at rest, and a vertical drag now sets their
speed, the same gesture the code rain and the snow already use, with a
sideways one still re-routing the board.
The glyph was a fraction of the header's height multiplied by a zoom with
bounds of its own, and the column count was a fixed fifty-two regardless. So
the rain drew fifty-two streams at a size that fit thirty across, which is
thirty columns of overlapping glyphs however many are in the list, and the
pinch went on resizing after the field had stopped answering it.

Turn it round: the pinch sets how many columns fit over the width, and the
glyph size is worked back from that — a monospace glyph advances about six
tenths of its font size, and the font is drawn at four fifths of the cell.
Thirty across is now as large as a glyph may be and a hundred and twenty as
small, with eighty at rest, which is a limit that means the same thing on a
phone and on a tablet where a size in pixels would not. One column to each
lane that fits, so the field is exactly as dense as it says it is, and the
zoom bounds fall out of the counts instead of being chosen beside them.

Lanes are taken in golden-ratio steps rather than at random. Eighty random
numbers do not cover a width evenly — the widest bare gap is around a
fourteenth of the header, with doubled-up streams somewhere else to pay for
it — and at the far end of a zoom in, where thirty large glyphs carry the
whole field, that gap is most of what you see.

Columns are added and taken away between frames instead of the field being
rebuilt, so a pinch never blanks a stretch of the header: new streams arrive
from above the top edge, and the ones taken away are those that have already
fallen furthest. A tapped-in column is counted, so the next frame does not
quietly take it back off again.
Parasitically the manager is not a package: it runs inside the host, loaded
from the daemon's own APK. "Install as an app" puts a second copy of that
code on the device, and nothing keeps the two in step afterwards — the
module behind it is reflashed on every framework update, while the install
stays whatever it was. The row was a boolean and collapsed to a green check
the moment the package existed, so a copy from a build two months old looked
exactly like a copy of the build that is running.

The version code cannot separate them. It is `git rev-list --count
origin/master`, so a branch build and the official build at the same depth
wear the same number. Compare the bytes instead: the version code first
because it is free and a disagreement there is already the answer, and when
the numbers agree, SHA-256 the installed copy's own APK against the one the
daemon would install. Both are streamed a chunk at a time — the heap that
would otherwise hold twenty megabytes belongs to com.android.shell — and the
verdict is remembered against the installed copy's lastUpdateTime, so it
expires exactly when that copy is replaced and not before.

A comparison that could not be made is not a mismatch. A dead daemon, a
refused APK, an unreadable install: each leaves the card reading as it did
before there was anything to compare, because sending somebody to replace a
working copy on the strength of a check that never ran is the one outcome
worse than saying nothing. Only a completed comparison is remembered, so a
daemon that comes back is asked again.

Nothing new is needed to act on it: install() has always set
INSTALL_REPLACE_EXISTING, because a SHELL_UID session is not given it for
free. The row simply stays a button, labelled Reinstall — in every language,
since check_translations.py holds each locale to the English key set.
@JingMatrix JingMatrix linked an issue Aug 2, 2026 that may be closed by this pull request
@JingMatrix
JingMatrix merged commit 8d636c4 into master Aug 3, 2026
1 check passed
@JingMatrix
JingMatrix deleted the ambience-cosmetics branch August 7, 2026 19:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow hiding or changing the status bar icon

1 participant