Repository navigation
Claude/commercial mute detector c7sooi - #4
Merged
Merged
Conversation
The first real run picked a persistent news graphic rather than the bug and there was no way to know. Camera setup is now a screen: the live picture with the found TV in green and the logo box in yellow, a magnified crop of that box, a live match score (PRESENT/absent), Watch 45 s for the automatic finder, and drag-to-draw to override it. Save & start writes the template and starts the service; AdHush pauses while the screen is open. Hand-held at eight feet: the screen is re-found every frame and each edge refined at full resolution (the coarse box was only good to 8 px, most of a small logo), capture is 1280 x 720, frames come out upright, a blur guard makes a smeared frame inert rather than "absent", and absence must last 2.5 s. LogoFinder exposes the screen, a stability map and a template for any box; LogoTemplate carries the screen's edge level for the guard. Tests cover rotation, a wandering screen, a blurred frame and a hand-drawn box. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
Offline speech recognition on the phone (Vosk small English model, downloaded once) turns the microphone into words with media-time stamps. Commercials are found by repetition: RepeatLearner indexes every 4-word key with its time; a key heard again at least two minutes later starts a run, agreeing words extend it (single slips allowed), runs of ten or more words become scripts, and every later airing folds into the same one. It runs every ten minutes and on the Learn scripts now button. Teach-mode windows are saved as scripts directly. Live matching aligns the last four words against the scripts the way the audio matcher aligns chroma blocks, so a misheard word breaks keys but not the alignment; three aligned hits confirm; only aligned hits extend the 8 s grace. Legal and sales boilerplate holds the duck on its own. The detector carries three default weights so a known script mutes alone. Tests: an hour of synthetic transcript with two spots airing at intervals yields exactly those two scripts with the airings folded; live matching with 15% word errors fires within 7 s, holds through, releases within grace; boilerplate and teach-mode windows; the store round-trip; and the engine ducking on a script and restoring after. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
…al UI The service installed a default uncaught-exception handler that restored the volume and killed the process, so any error anywhere made the app disappear with nothing recorded. AdHushApp now installs an app-wide handler that writes the stack trace to a rolling log file, restores the set through the service's hook, and delegates to Android's handler so the crash is reported. AppLog collects every status line and caught error; the Log tab shows the tail and Share error log hands the file out through FileProvider. Two likely causes of the reported vanish are fixed in the speech path: the 40 MB model was loaded on the main thread inside the service start, which can stall it long enough for Android to kill the app; it now loads on the io executor and attaches when ready. SpeechSource.close waits for the block being processed before closing the native recogniser. The interface is rebuilt on Material 3: a top bar carrying the live status, four tabs (Home, TV, Senses, Log), cards, labelled text fields with a password toggle, switches, one primary action per card. Every view id and every function is unchanged. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
…aptions, colour setup, help Fixes the 0.13 log: the camera's logo detector ducked the set again seconds after every "Not an ad" because it called the bug gone without ever having seen it. The bug must now be sighted before its absence counts; "Not an ad" and "Show's back" reach every detector and open a one-minute quiet period; the logo box is slid over a search window so a hand-held frame follows the bug; a TV that runs off the edge of the picture is "whole TV not in view" and never a duck. A blank TV address refuses to start instead of dialling ":10002"; the speech feed no longer throws after close. Adds the Methods page with all six methods as switches (at least one must be on), on-screen captions as the sixth method (on-device text recognition of the caption band, fed to the transcript matcher), running indicators (chips, dots, tinted buttons, green Running / red Stop), a Test mode card on Home, a Help page and info buttons explaining the bug, scripts, ducking and each method, a splash screen, and camera setup in colour with pinch zoom and a whole-TV warning. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
… package Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
android:padding overrides android:paddingBottom on the same view, so the room left under every page was ignored and the tab bar covered the last content. Pad each side explicitly and let the scroll views scroll past the padding. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
…wrong password; no FGS crash before the mic is allowed Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
Inert votes and a present-mass fusion normaliser; the user's word reaches the detectors; the logo detector requires a sighting, slides a search window and goes stale without frames; the camera drops partial screens; teach mode with "Show's back" and a quiet period after "Not an ad"; network_ip keeps one connection, names a busy set, and ducks the volume through the profile's VOLM commands with crash recovery. Listener example config, ADR 0014, and a beginner's guide for a Pi on a shelf. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
The Sharp RS-232C controller gains duck_level / normal_volume / duck_state_file with crash recovery and restore-on-close. The listener config defaults to the cable, with Wi-Fi as the documented alternative. The beginner's guide and its NESPi 4 PDF are rewritten for the cable (parts, wiring diagram, dialout group, port discovery, error messages). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
…er as a camera target, a better speech model JudgeDetector (core) collects words from speech and captions and asks a TranscriptJudge on a cadence — tie-breaker by default — holding a COMMERCIAL answer as a logo-weight vote and saving confident answers as scripts. ClaudeJudge uses the Anthropic Java SDK (Haiku 4.5 default, cached instruction, text only); LocalJudge runs Qwen2.5-0.5B through MediaPipe LLM Inference from a resumable one-time download. LogoFinder.bandResult finds a news channel's lower-third band and the logo detector watches it under the name ticker_absence. Methods page gains cards 7 and 8, the camera target and speech model choices, help topics and warnings. ADR 0015. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
…lus guide Borrowed from admuffs (ADR 0016): the engine tells room-microphone detectors about every duck. The loudness detector freezes its vote for one window, measures how far the room dropped and judges the ducked ad on the original scale, so a ducked commercial no longer reads as "programme resumed" and the set is not ducked again and again. When the ducked set is buried under the room (near the silence gate, or flat fan noise by the silence detector's own spectral-flatness test) loudness and silence go inert and the other methods carry the unmute. Python listener and Kotlin core alike, with replay tests for both cases. Android: method 8 offers Qwen 2.5 0.5B, Qwen 2.5 1.5B and Qwen 3 4B, each in its own file, chosen under Methods. docs/print gains the Local AI guide for the OnePlus Ace 6 Ultra (HTML source and PDF). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
… on it ADR 0017. Method 9, the break clock, learns which minutes of the hour the breaks land on from every confirmed break and votes once a minute has been watched in three hours; a default-weight vote that tips the balance and never ducks alone. Kotlin and Python, with a shared TSV format. Timed manual ducks (30/60/90/120 s) turn the set down from any state, including the recovery pause, and back up on their own; nothing is learned. Android Home and remote, the web page, and a duck_for IPC command. The remote: every Sharp handset key through the control port (RCKY), on an Android screen that also carries Start, Stop, Is an ad, Show's back, Not an ad and the timed ducks, and on the web page; send_key on controllers, a remote IPC command, and a commands.remote_key template in the Sharp profile. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
…een phones ADR 0018. On Android 10+ the phone can hear its own playback through Android's playback capture: play a channel's live stream (MS NOW, Xfinity Stream, any web player) and the engine runs without a TV, fingerprints on, speech and the AI judges as configured, learning every break it ends into the same ads.tsv and scripts.tsv the TV mode reads. The notification counts the breaks; a player that blocks capture is reported as silence. Share this phone's memory / Import memory from a file zip and merge the breaks, scripts and break clock between phones without doubling what is known. The stream-learning guide (HTML + PDF) is in docs/print. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
ADR 0019. One-file PyInstaller binaries of the core for Windows x64 (with a windowless adhushw.exe for the logon task), macOS arm64, Linux x64 and Linux arm64, each smoke-tested on its own runner (--version, init, doctor, an offline replay) before publishing; a Raspberry Pi bundle with the arm64 binary, the listener config and the PDF guides; the APK, the web app (the iOS install, as a PWA) and the wheel as before. The web front end, the device profiles and the example configs travel inside the binary (util/resources.bundled); `adhush init` writes a starter config and the profile library next to it. Release notes carry a per-platform download table; the README and docs/release.md match. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
…ing directory Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
…able countdown (ADR 0020) Method 10, break jingles: the channel's sting into and out of every break is learned from the breaks the other methods end (three breaks opened by the same three seconds promote it) and then ducks alone the moment it is heard; a closer heard while ducked is the programme coming back. Kotlin core and Python (`jingle` detector, on in the listener example); the detector is inert until it has a promoted opener so a learner never dilutes the fusion normaliser; `jingles.tsv` travels with the shared memory. The ad badge during Android stream learning: ML Kit reads the player's corners once a second; "Ad", "Ad 1 of 3", "AD 0:15" or "Your video will resume" votes like the channel bug, and its absence while scanning is programme evidence. Learned break lengths: the break clock keeps a 30-s histogram of how long this channel's breaks run (clock.tsv v2); a mute's ceiling becomes p90 + 30 s once five breaks are known, and the status shows "about m:ss left" during an automatic duck. Manual ducks now run 30 s to 300 s in 30-s steps everywhere (phone Home, the remote, the web page, IPC duck_for), with a +30 s button and notification action that extends a running duck (or holds an automatic one as a timed duck); the status line counts down. A remote icon sits in the toolbar of every phone screen. Replay and CLI flow tests point the jingle and clock stores at temp files; data/clock.tsv and data/jingles.tsv are gitignored. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
…s (ADR 0021) aspect_change (Python, HDMI and screen capture): dark, flat bars at the frame's edges give the active picture's aspect ratio; the programme's shape is a rolling mode that freezes while the picture is changed, and a spot that arrives pillarboxed or letterboxed votes 1.0 for as long as it holds the other shape. Inert unless changed, so it never dilutes the detectors that do see something; default weight, never alone; a change longer than any break restarts the baseline. Synthetic fixtures gain an ad_43 kind for its ground truth. On by default and in the HDMI example configs. Crest factor inside loudness (Python and Kotlin): each block's peak-to-RMS ratio rides in the short-term window against a baseline taken and updated exactly when the loudness baseline is; a drop of crest_drop_db (4 dB) x 1.4 adds up to half a vote, so a spot compressed flat shows even when it is no louder, and a music bed cannot mute by itself. The conformance fixture is regenerated (unchanged: steady tones have a constant crest). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
… backlog (ADR 0022) SetupWizardActivity: seven steps, offered once on first run and always on the Home page. It asks how the phone reaches the TV (and asks a networked Sharp its volume), where the phone sits, the channel, ticker and captions; listens to fifteen seconds of the show and ten of the room with the set muted (dBFS, flatness, crest per block; numbers only); looks through the camera for eight seconds for a whole, lit screen and how wide it is; then suggests every method, the duck level (ADR 0016's posture as numbers), the camera target and zoom, and the local AI size from the phone's memory, each with its reason. Apply and review writes Settings and opens the Methods page (MainActivity.EXTRA_PAGE; a running instance reloads in onNewIntent). Wording audit: every count of the phone's methods says ten (Help "Choosing methods" said eight and left the clock and the jingle out of its weak/strong lists; the Help header said six; the Android README's screens section said six; the local-AI print guide said eight, PDF regenerated). docs/ideas-backlog.md ranks fourteen ideas from comskip, MythTV, the ATSC A/335 and DVB-TA watermark specs, patents and peer projects. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
…ut, and three feeds (ADR 0023, 0024) ADR 0023, all inert until they have evidence and all in the default set: rating_bug (the parental-rating box after a break is positive programme evidence; Python HDMI path and the phone camera via the logo detector's screen box); ad_units (separators on the 15-second ad-unit grid hold a mute through a pod; both cores, on the phone riding on Quiet gaps); uniform separators in black_frame (a white flash or colour card counts like black, spread measured on strided raw pixels); cutscene (captured intro/outro frames, `adhush cutscene add`, phash + thumbnail correlation; "in" ducks alone, "out" is the show back); stereo_width (the mono/stereo switch, measured by hdmi_uvc, line_in and ts_stream before their downmix, AudioEvent.width); watermark (ATSC A/335 / DVB-TA presence lost when a local spot replaces the marked picture; experimental, written from the spec's shape). ADR 0024: schedule (XMLTV via util/xmltv; a grace window after a start dilutes mutes, ad_free channels never mute); ts_stream capture (HTTP or UDP transport stream fanned out to two ffmpegs and util/mpegts, which follows PAT -> PMT to the SCTE-35 PID and parses splice_insert and segmentation descriptors) with scte35 votes from the out cue to the in cue; crowd (an opt-in shared feed with k-anonymous channel hashes, `adhush crowd serve`, polled off the decision thread, this device's own breaks reported). Programme evidence now comes from any detector with program_present (base property, Python and Kotlin); wall time ticks every detector; cues are a third event type pumped by run_live. Detectors that identify a break outright (jingle, cutscene, scte35, crowd) carry three default weights unless a profile says otherwise. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
…s on every branch The v0.24.0 release built all four binaries and then refused to publish: `mypy src` under strict mode cannot find Pillow, which `adhush cutscene add --image` imports optionally inside a try/except and which CI does not install. This machine has Pillow with its type information, so the local run passed and the drift only appeared at the tag. A mypy override ignores the missing import; verified by hiding Pillow from site-packages and re-running, which is exactly CI's situation. The reason it surfaced so late: ci.yml ran only on main and pull requests, and all this work lives on a long-lived branch with no pull request, so the Python checks had never run in a clean environment until the release job ran them. It now runs on every branch push. No detector or behaviour changes; 0.24.0's version strings stand. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
…ed, each tried and reported The TV step no longer trusts a typed address alone. Find my TV tries all three paths: the Wi-Fi (the typed address, else a scan of the phone's own /24 on the Sharp control port with a 300 ms connect on 32 threads and a VOLM? to every listener until one answers as a Sharp; the found address is saved), the serial cable (adapter present, USB permission asked for through the same broadcast the Home page uses and the cable retried when granted, then VOLM? over the cable), and the infrared blaster (present, MUTE fired twice two seconds apart, then a Yes/No from the owner since infrared is one-way). The first that worked is chosen, network before cable before blaster, and the radio group still lets the owner override. The plan names how the TV was reached. ACCESS_NETWORK_STATE for the phone's own Wi-Fi address. ADR 0022 amended. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
… proves each way in (ADR 0025) Core: VolumeDevice and LevelController (the Sharp controller made general; SharpIpClient implements the interface, SharpController is the level controller with the Sharp client underneath). Drivers, pure JVM: Sony Bravia JSON-RPC (pre-shared key), LG webOS SSAP over a WebSocket (allow once, client key kept), UPnP RenderingControl for any DLNA set, Samsung's remote channel over a WebSocket (allow once, token kept), Roku ECP, Vizio SmartCast (PIN once, token kept). MiniHttp and a hundred-line MiniWebSocket, tested against a loopback server. Infrared encoders for NEC, Samsung, Sony SIRC-12, RC-5 and Panasonic with a code table for seven brands. TvFinder: one SSDP search, then each brand's key-free question on every address, exact-volume paths ordered first. App: the wizard's Find my TV lists every set found and proves the paths in order — exact ones by reading the volume, key-only ones by firing MUTE twice and asking — then the serial cable, then infrared brand by brand. The service builds a level or step controller per path; the remote works over Roku, Samsung and Vizio; the TV page's fourth radio carries what the wizard found; tokens live in the encrypted settings; cleartext HTTP is allowed for the sets on the LAN. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
…, Philips JointSpace (ADR 0026)
Core, pure JVM and unit-tested: MiniProto (a fifty-line protocol-buffers
codec), ClientIdentity (a self-signed client certificate via BouncyCastle,
kept as a PKCS#12 blob), AndroidTvRemote (pairing on 6467 with the
six-character code hashed with both RSA keys; the session on 6466 answers
configure and pings and reads the set's volume reports, so the level is
known and set by stepping), MiniMqtt (MQTT 3.1.1 in a hundred lines,
tested against a loopback broker), HisenseVidaa (service credentials,
gettvstate, the four-digit code, getvolume/changevolume/sendkey), Digest
(RFC 2617, checked against its example) and PhilipsJointSpace (version 1
plain, version 6 with digest auth and the signed PIN grant). TvFinder
probes the three ports.
App: three more level controllers, remote keys over all three, settings
for the identity, client id and paired credentials, and the wizard's
Find my TV shows one code row when a set asks for a code and waits for
it on the path's own thread.
A Kotlin trap fixed and noted: inside Socket().apply { } the name `port`
is the socket's own; the MQTT client connected to port 0 until the
loopback test caught it.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
The three bcpkix/bcutil/bcprov jars each ship META-INF/versions/9/OSGI-INF/MANIFEST.MF and the debug APK's resource merge refuses the duplicate; the core tests were green. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
The whole picture in one page: both implementations, the release table, the quick start with every CLI command, how fusion decides, all seventeen Python detectors and the ten phone methods, every control path on both sides with the wizard's brand table, the capture paths, five design goals, and a map of the documentation. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
Jingle detector (both cores): a learned sting is also recognised transposed by up to two semitones (the chroma bits rotate) and stretched by up to ten per cent in tempo, docked a small penalty, so a channel's per-show re-cuts count for the sting they resemble; the vote reason names the variant. Every jingle remembers the local hours it opened breaks in; at one of those hours it is trusted a break early and matched a little more loosely. jingles.tsv becomes v2 with an hours column; v1 files load unchanged, and the Android memory merge carries the hours. New default-weight detector `stinger` (detect/stinger.py, Stinger.kt): a short noisy burst over the two-second bed, then the level moves. Inert until it fires, decays over 2.5 s, ignores our own duck. On by default in the Python core; on the phone it rides on the Loudness method. Engine passes the break's wall-clock start to the jingle detector and ticks it with the wall clock. Tests for families, tempo, hours, the TSV round-trip and the stinger in both cores; replay pins and the Android method-toggle test updated. Docs: ADR 0027, changelog, release notes, roadmap phase 19, READMEs, Help topic, example configs; version 0.28.0. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
…zard button, a real remote Both cores (ADR 0027, amended): a break shorter than 20 s teaches the jingle learner nothing; two hearings of a sting within half an hour count once (each jingle keeps the wall time of its last counted hit, TSV column 9); a taught break under 30 s is a slip of the finger and one over six minutes is cut there; a remembered break whose duck ends within ten seconds on programme evidence is a false match, two of which forget the record. Tests for each rule in both cores. Android: one model download at a time, and a finished model is never deleted (a double press deleted it). Forget what it learned… (Methods page and the ⋮ menu) with a tick per kind of memory. Save to a file on the Log page through the system picker. The set-up wizard is a Home-page button beside Start, Stop, Test TV and Remote, labelled on its screen, and never opens by itself. Home page: side-by-side teach buttons, timed ducks as chips, test output only when there is some. The remote laid out like one: rockers either side of a D-pad, a number pad, transport and picture keys, 56 dp keys. Taller, rounder buttons and cards; dark mode colours. Version 0.28.1 (versionCode 29); changelog, ADR, release notes, READMEs, Help. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
…ht seconds The badge reader notices a picture that is black all over (a protected window mirrors as nothing); the service reports, on the Home card and the notification, digital silence from the first seconds (the player opted out of playback capture) and a blacked-out picture (Android's "content hidden from screenshare" flag), each with what to do instead: the channel's website in Chrome, or the microphone with the normal Start. A black picture with audio still heard is reported as well, since the AD badge cannot be read from it. Help and the README explain the message. Version 0.28.2 (versionCode 30). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
Feedback.kt: a button dips when pressed, turns green with a tick for a second and a half when what it asked for went through, red with a cross when it did not, then comes back as it was. The service broadcasts each control action's outcome (Is an ad, Show's back, Not an ad, the timed ducks, +30 s, every remote key) and the Home page and the remote flash the button that asked; local actions (Save, Test TV, downloads, share, import, forget, save the log) report their own. The teach buttons and the ducks are bright only when they would act right now. A Help topic explains the colours. Version 0.28.3 (versionCode 31). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
… resumable Feedback: the press animation is gone. A button that started a job (a model download, Test TV, an AI test, an import, saving the log) stays blue and disabled with the job's progress as its label until the job ends, so it cannot be pressed twice; then green with a tick or red with a cross and the label the outcome calls for. Downloads.kt: the bytes go to a .part file with the expected size kept beside it; a download that stops short throws with how far it got and the next press resumes; only a part of exactly the expected size is moved into place. LocalJudge keeps the installed size beside the model and counts it installed only when every byte is there; SpeechSource unpacks into a folder of its own and moves it into place whole. The buttons read Resume with the percentage; Delete partial model downloads in the ⋮ menu. Version 0.28.4 (versionCode 32). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
…mentions restored Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
…s text The Remote tab (RemotePanel, replacing RemoteActivity): AdHush's own controls on top, then the TV's remote drawn as one — a dark rounded body, power, input and mute, a number pad, the volume and channel rockers either side of a round D-pad with OK in the middle, menu, transport, the colour keys and the rest, every key a pill or circle with one line of white text. Tabs: Home, Remote, TV, Methods, Log; Help is the ? in the toolbar. Every button app-wide is one line tall with text that shrinks to fit (maxLines 1, autosize in the styles); shorter labels on the Log and memory buttons. Version 0.28.5 (versionCode 33). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BcfLmuUiHYY3PbRUskf3t4
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.
What changed
Why
Verification
make lint type testpasses