straw/strawApp/proguard-rules.pro
Kayos aead95f1bc vc=59 cont: wire bg subs refresh + R8 keep + Settings UI
Bundling the background-refresh worker (originally planned as
vc=60) into the same release as cache controls — they're both
storage-and-refresh user-facing knobs, ships cleaner together.

- StrawApp.onCreate calls FeedRefreshScheduler.applyFromSettings
- R8 keep rule for FeedRefreshWorker (same reason as
  UpdateCheckWorker — WorkManager instantiates via reflection)
- Settings UI: 'Auto-refresh subs' toggle (default off) +
  interval chip-row (30min / 1h / 6h) shown when enabled. Lives
  in the existing Local cache section since it's the same
  storage-and-refresh theme.

Worker calls uniffi.strawcore.subscriptionFeed which fans out 50
parallel RSS fetches in Rust — 50 subs refreshes in ~1-2s in the
background. Writes per-channel into FeedCacheStore so next cold
open of Subs paints instantly.
2026-05-26 11:38:04 -07:00

90 lines
4.1 KiB
Prolog

# SPDX-FileCopyrightText: 2026 Sulkta-Coop
# SPDX-License-Identifier: GPL-3.0-or-later
#
# R8 keep rules for the Straw app module. The legacy `app/proguard-rules.pro`
# is for the upstream NewPipe module different namespaces, different
# rules. This file is OURS.
#
# AGP's getDefaultProguardFile("proguard-android-optimize.txt") handles
# the Android framework + AndroidX + Compose runtime defaults via
# consumer rules shipped with each library. We only need to spell out
# what those defaults can't see:
#
# * UniFFI bindings reflective FFI dispatch from generated code.
# * JNA reflects on every class extending com.sun.jna.Library
# (that's how the loadLibrary glue works).
# * Our kotlinx-serialization @Serializable types — their generated
# $$serializer companions get tree-shaken without explicit keeps.
# * Media3 session metadata Parcelables.
# -- UniFFI -------------------------------------------------------------
# Generated bindings live under uniffi.strawcore.*. The Rust side calls
# them via JNI symbol name; if R8 renames the class or methods, every
# extractor call NPEs.
-keep class uniffi.strawcore.** { *; }
-keep class uniffi.** { *; }
# -- JNA ---------------------------------------------------------------
# JNA looks up Library subclasses by Class.forName + reflection at
# load time. Anything that extends Library or has @FieldOrder must
# survive.
-keep class * extends com.sun.jna.Library { *; }
-keep class com.sun.jna.** { *; }
-dontwarn com.sun.jna.**
# -- kotlinx-serialization ---------------------------------------------
# Every @Serializable type gets a synthetic Companion + $$serializer
# class. R8 will strip the $$serializer if nothing visibly calls it
# (the lookup goes through reflection on the Companion).
-keepattributes *Annotation*, InnerClasses
-dontwarn kotlinx.serialization.**
-keep,includedescriptorclasses class com.sulkta.straw.**$$serializer { *; }
-keepclassmembers class com.sulkta.straw.** {
*** Companion;
}
-keepclasseswithmembers class com.sulkta.straw.** {
kotlinx.serialization.KSerializer serializer(...);
}
# Same dance for our top-level @Serializable types defined outside
# `com.sulkta.straw.**` (Rust DTOs, etc.). Belt + suspenders.
-keepclassmembers @kotlinx.serialization.Serializable class * {
static **$Companion Companion;
public static <1>$Companion Companion;
}
-keepclasseswithmembers @kotlinx.serialization.Serializable class * {
kotlinx.serialization.KSerializer serializer(...);
}
-keep class **$$serializer { *; }
# -- Media3 / ExoPlayer ------------------------------------------------
# Most of Media3 ships consumer rules but session-related Parcelables
# are reflectively reconstructed across process boundaries (the
# MediaController talks to PlaybackService via Binder). Keep their
# field names.
-keep class androidx.media3.session.** { *; }
-keep class androidx.media3.common.MediaItem { *; }
-keep class androidx.media3.common.MediaItem$* { *; }
-keep class androidx.media3.common.MediaMetadata { *; }
# -- Strawcore exceptions / DTOs reflected by UniFFI --------------------
# StrawcoreError is a sealed Throwable hierarchy exposed via UniFFI.
# Keep all subclasses + their fields so the Kotlin pattern-match works
# after minification.
-keep class com.sulkta.straw.feature.player.** { *; }
# -- Reflection-via-Class.forName paths from Compose --------------------
# Compose's runtime does some Class.forName for its own bootstrap; the
# AGP consumer rules cover this, but documenting the dependency here
# so a future bump doesn't surprise us.
-keep class androidx.compose.runtime.** { *; }
# -- WorkManager Worker classes ----------------------------------------
# WorkManager instantiates Worker subclasses by class name via
# reflection (`Class.forName(workerSpec.workerClassName)`). If R8
# renames our UpdateCheckWorker the scheduler enqueues it but the
# instantiation fails silently and no checks ever run.
-keep class com.sulkta.straw.feature.update.UpdateCheckWorker { *; }
-keep class com.sulkta.straw.feature.feed.FeedRefreshWorker { *; }
-keep class * extends androidx.work.ListenableWorker { *; }