From d9585c40e7f3b6de8b5f0c37e27edec49d565aa8 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 25 Sep 2026 08:13:12 +0000 Subject: Add single videos, make the whole episode row tappable, stamp the build Sharing a YouTube video now adds that one video rather than subscribing to its channel -- sharing something interesting is not a request to follow everything the channel ever posts. They land in one "Saved videos" container instead of a subscription each, which would otherwise fill the library with entries that will never publish again. Title, artwork and duration come off the watch page we already fetch, so adding needs no extractor. Only the episode title was tappable, which is too fine a target: Peter tapped the row, nothing happened, and reasonably concluded the details screen wasn't there. The whole row opens it now. Settings shows the commit and build time. A cached browser download and a failed publish look identical from the outside, and "is this the new build?" had no answer that did not amount to trusting me. publish-apk writes a companion .txt with the hash for the same reason. Metadata is entity-decoded. A YouTube thumbnail URL carries query parameters and the raw attribute encodes the separators as &, so the artwork simply failed to load -- spotted in the real resolved output rather than by a test. YouTube URL handling moved to its own YouTubeUrls object. Channel, playlist, handle and watch URLs each need different treatment and two only resolve by reading the page; that is its own concern, not a corner of the general resolver. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B --- app/build.gradle.kts | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'app/build.gradle.kts') diff --git a/app/build.gradle.kts b/app/build.gradle.kts index a81df9b..558e1dc 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,3 +1,23 @@ +import java.io.ByteArrayOutputStream +import java.time.Instant +import java.time.ZoneOffset +import java.time.format.DateTimeFormatter + +/** + * The commit this APK was built from. + * + * Exists so "which build am I running?" is answerable from the phone rather than by trusting + * that a publish worked -- a cached download looks identical to a failed publish. + */ +fun gitDescribe(): String = try { + val out = ByteArrayOutputStream() + providers.exec { + commandLine("git", "describe", "--always", "--dirty", "--abbrev=8") + }.standardOutput.asText.get().trim().ifEmpty { "unknown" } +} catch (e: Exception) { + "unknown" +} + plugins { id("com.android.application") id("org.jetbrains.kotlin.android") @@ -29,6 +49,14 @@ android { versionName = "1.0" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + buildConfigField("String", "GIT_COMMIT", "\"${gitDescribe()}\"") + buildConfigField( + "String", + "BUILD_TIME", + "\"${DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm") + .withZone(ZoneOffset.UTC).format(Instant.now())}\"", + ) + ndk { // CPython ships as native code, so every ABI included multiplies the APK size. // arm64 is the phone; x86_64 is the emulator. @@ -74,6 +102,7 @@ android { buildFeatures { compose = true + buildConfig = true } compileOptions { -- cgit v1.2.3