Infotify 3.0 — Compose rewrite, proxied API, site and store assets - #16
Merged
Merged
Conversation
The build had drifted into a state that could not compile: the Kotlin toolchain
was declared as 2.0.20 in the root file, 2.4.10 for two compiler plugins and
2.2.10 for the standard library. `ksp` was used for Room without the plugin ever
being applied, and turbine had been dropped while a test still imported it.
Version catalog first, because inline literals are what allowed that drift.
gradle/libs.versions.toml is now the only place a version is written; there is
not one version literal left in any build file except versionName. The three
Kotlin compiler plugins — Compose, serialization, KSP — are pinned together on
purpose, since they must track the Kotlin the build uses rather than float.
AGP 8.9.3 -> 9.2.1 (the newest the user's Android Studio supports), Gradle
8.14.5 -> 9.7.1, JDK 17. That upgrade was not optional: Hilt 2.60.1 refuses any
AGP below 9.0.0, and compileSdk 37 needs it too.
AGP 9 brings built-in Kotlin, so:
- the kotlin-android plugin is gone; AGP compiles Kotlin itself
- kotlin-kapt is incompatible with it, so Room and Hilt both moved to KSP
- android.kotlinOptions{} no longer exists; jvmTarget now follows
compileOptions.targetCompatibility
- the Groovy space-assignment DSL is replaced by explicit assignment
Kotlin 2.3.21 rather than 2.4.10: KSP is only published up to 2.3.11, so 2.4
would have meant keeping kapt. Given the goal was to reach KSP, Kotlin gives way.
Removed as unused — each checked against the sources, not assumed:
appcompat and material (no View-system widget or theme remains), lifecycle-process
(ProcessLifecycleOwner went with the old Application class), mockk (the tests use
hand-written fakes), and espresso, test-ext-junit and compose ui-test (there are
no androidTest sources at all).
Two fixes the upgrade forced:
- ic_notification.xml referenced ?attr/colorControlNormal, which came from
AppCompat and stopped resolving once that was dropped. Notification icons are
tinted by the system anyway, so the attribute was doing nothing.
- RelativeTime used LocalContext.current.getString, which the newer Compose lint
rejects as not configuration-aware: a locale change would have left stale text
on screen. It uses stringResource now.
ktlint moved from the abandoned com.pinterest:ktlint 0.50 to ktlint-cli 1.8.0,
lost its own repositories block (repositories are centralised in settings.gradle),
and uses mainClass instead of main, which Gradle 9 removed.
Verified: assembleDebug, 38 unit tests, lintDebug and assembleReleaseTest all
green. The R8 APK is 2.66 MB, down from 3.47 MB.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…p a dead thumbnail The site had no icon at all, and its screenshots were visibly wide. The distortion was baked into the image files, not the CSS: the pair was 620x1217 for a 1080x2220 screen, a 4.7% horizontal stretch that no stylesheet could undo. Retaken from the app and resized to 620x1274, which is the device ratio to four decimal places. The markup's width/height attributes and the CSS aspect-ratio were updated to match, so the reserved box and the image agree. Favicons are generated from the same geometry as the launcher icon — ink ground, paper stem, ember dot — as favicon.ico, an SVG for modern browsers, and a 180px apple-touch-icon, all linked from the three pages. One of the old screenshots showed a card with an empty grey thumbnail. Chasing it turned out to be worth doing: list cards kept their 96dp placeholder when an image failed, while the featured card already dropped its own. They now behave the same, and the headline takes the full width instead. Publishers' image hosts fail often enough that this is a common state, not an edge case. Worth recording, since it is easy to misread: a grey box is also the *loading* placeholder. Coil reports Error, not Loading, to onState, so a slow image looks exactly like a failed one for as long as it takes. The screenshot that prompted this was taken 25s in on an emulator with slow reach to publisher CDNs; the images did eventually arrive. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The screenshots stayed visibly wide after the files were corrected, and the reason was mine: .phone img carried `aspect-ratio: 620 / 1274`. A declared ratio overrides the file's own, so the box was fixed and whatever image landed in it was squashed to fit. I had added it to reserve space during loading; it was the fixed height causing the very problem it sat next to. Removed. `width: 100%` with `height: auto` and nothing else, so the file's intrinsic ratio always wins. The width and height attributes in the markup reserve the space instead, which is what they are for. Two compounding causes fixed with it: - The image filenames never changed, so browsers kept serving the old 620x1217 files against the new declared ratio — the fix looked like no fix at all. Assets are versioned in the filename now (for-you-2.png, explore-2.png). - HTML was cacheable, so a stale page kept pointing at the old filenames. .htaccess now sends no-cache for HTML and a year for versioned assets. Also added the phone frame that was asked for: an ink bezel with the screen inset, a speaker slot and a side button, drawn entirely in CSS. Nothing is baked into the PNGs, so the screenshots stay honest captures and can be replaced without redrawing any chrome. Verified against what the server actually returns: the image is 620x1274, the markup declares the same, the stylesheet contains no aspect-ratio declaration, and the frame's pseudo-elements are present. I could not view the rendered page — the browser pane refuses this origin by policy — so this is verified by measurement, not by eye. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The listing had an icon and a feature graphic and nothing else. This adds the eight
phone screenshots Play shows in the carousel, and the script that produces all of it,
so a capture can be replaced without anyone reopening an image editor.
The icon changes. It was a separate drawing from the launcher icon — stem 15px off
its axis and 50px too tall — so the tile in the store and the tile on the home screen
were not the same mark. generate.py now renders the geometry straight out of
ic_launcher_foreground.xml, and both come from one source.
The captures are honest: the R8-minified releaseTest build on a Pixel 3a emulator
against the live proxy, with SystemUI demo mode so the status bar carries no real
device state. The phone chassis is drawn around each PNG rather than baked in, and
the phone's width is fixed while its height follows the file's own ratio — the same
mistake that stretched the website screenshots cannot happen here.
Two things are deliberately left open, both recorded in playstore/README.md: there
are no tablet screenshots, and screenshot-2 shows one empty grey thumbnail. That grey
box is the app's real behaviour today — a publisher image that never resolves leaves
the placeholder in place instead of collapsing as ArticleCard intends, because Coil
reports no Error state for it. Seen only on this emulator so far, whose clock is
visibly broken ("time of day goes back"), which is enough to stop OkHttp's timeouts
firing — so it needs confirming on a real device before it is treated as an app bug.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The live listing still describes NewsAPI and seven languages, and points its privacy policy at the GitHub repository. This is the replacement text for the English and French listings, with every claim taken from the source rather than from memory: fifteen topics capped at five (Topic.MAX_SELECTED), four regions, nine languages, three non-sensitive permissions, and no analytics or advertising library in the app. Every field is inside its Play limit — names 28/30, short descriptions 66 and 60 of 80, full descriptions 1880 and 2144 of 4000. The data-safety section records one open question rather than answering it: the API keeps a rate-limit counter per hashed IP for under a day, which is not "ephemeral" by Play's definition, and Play has no IP category to declare it under. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The two images in the README had been broken since the website fix: renaming site/img/for-you.png to for-you-2.png for cache busting left the README pointing at files that no longer exist, so GitHub was rendering two dead images rather than the stretched ones they replaced. They now use the Play Store tiles, which are captures of the R8-minified build against the live API, and neither carries an unresolved thumbnail. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Brings
masterup to date with the six commits already onmain.masteris a strictancestor of
main, so this is a fast-forward — no history is rewritten and nothing isdropped.
What is in it
a real state machine; single Activity, typed Navigation Compose routes, Room v3 with
migrations that preserve existing bookmarks.
infotify-api.nativia.co, a caching PHP proxy that holds the key server-side. This wasnot optional — NewsData.io's free tier is 200 credits/day for the whole app, not per user.
catalog as the single source of versions,
targetSdk37, and every unused dependencyremoved after checking the sources rather than assuming.
infotify.nativia.co, with privacy and support pages the Playlisting can point at.
that generates them from real captures of the R8-minified build.
Known, and deliberately left open
tablet-ready.
screenshot-2-for-you.pngshows one unresolved thumbnail. That is the app's real currentbehaviour: a publisher image that never resolves leaves the placeholder in place instead
of collapsing as
ArticleCardintends, because Coil reports noErrorstate for it. Seenonly on an emulator whose clock is visibly broken, which is enough to stop OkHttp's
timeouts firing — it needs confirming on a real device before it is treated as an app bug.
releaseTest, by design.🤖 Generated with Claude Code