summaryrefslogtreecommitdiff
path: root/app/src
diff options
context:
space:
mode:
Diffstat (limited to 'app/src')
-rw-r--r--app/src/androidTest/java/org/terst/listen/data/MigrationTest.kt25
-rw-r--r--app/src/main/java/org/terst/listen/data/AppDatabase.kt24
-rw-r--r--app/src/main/java/org/terst/listen/data/Entities.kt12
-rw-r--r--app/src/main/java/org/terst/listen/ui/SkipSettings.kt6
-rw-r--r--app/src/test/java/org/terst/listen/playback/PlaybackAdvancerTest.kt5
-rw-r--r--app/src/test/java/org/terst/listen/playback/PlayheadPolicyTest.kt17
6 files changed, 71 insertions, 18 deletions
diff --git a/app/src/androidTest/java/org/terst/listen/data/MigrationTest.kt b/app/src/androidTest/java/org/terst/listen/data/MigrationTest.kt
index 181e853..cf691e0 100644
--- a/app/src/androidTest/java/org/terst/listen/data/MigrationTest.kt
+++ b/app/src/androidTest/java/org/terst/listen/data/MigrationTest.kt
@@ -197,4 +197,29 @@ class MigrationTest {
assertEquals(2, cursor.getInt(0))
}
}
+
+ /**
+ * Ad-chapter skipping was shipped off and Peter asked for it on after living with it, so
+ * existing shows have to move rather than only new ones picking up the new default.
+ */
+ @Test
+ fun migrates5To6TurningAdChapterSkippingOn() {
+ helper.createDatabase(name, 5).use { db ->
+ db.execSQL(
+ """INSERT INTO subscriptions
+ (id, feedUrl, kind, title, addedAtMs, skipIntroMs, skipOutroMs, dripEnabled,
+ dripIntervalMs, dripCount, dripOldestFirst, skipAdChapters)
+ VALUES ('s1', 'https://example.com/feed.xml', 'PODCAST', 'A Show', 1000, 0, 0,
+ 0, 86400000, 1, 1, 0)"""
+ )
+ }
+
+ val db = helper.runMigrationsAndValidate(name, 6, true, AppDatabase.MIGRATION_5_6)
+
+ db.query("SELECT skipAdChapters, title FROM subscriptions WHERE id = 's1'").use { cursor ->
+ cursor.moveToFirst()
+ assertEquals(1, cursor.getInt(0))
+ assertEquals("the show itself must survive the flip", "A Show", cursor.getString(1))
+ }
+ }
}
diff --git a/app/src/main/java/org/terst/listen/data/AppDatabase.kt b/app/src/main/java/org/terst/listen/data/AppDatabase.kt
index fe73ce0..4ff9f50 100644
--- a/app/src/main/java/org/terst/listen/data/AppDatabase.kt
+++ b/app/src/main/java/org/terst/listen/data/AppDatabase.kt
@@ -25,7 +25,7 @@ class Converters {
QueueEntity::class,
RuleEntity::class,
],
- version = 5,
+ version = 6,
exportSchema = true,
)
@TypeConverters(Converters::class)
@@ -141,6 +141,24 @@ abstract class AppDatabase : RoomDatabase() {
override fun onCreate(db: SupportSQLiteDatabase) = seedDefaultFilters(db)
}
+ /**
+ * Turns ad-chapter skipping on, which Peter asked for after living with it.
+ *
+ * It shipped off-by-default out of caution, since it is the one part of the skip
+ * feature that removes audio nobody has heard. In practice it only ever acts on
+ * chapters a publisher explicitly marked as not-content, and doing that automatically
+ * is the point.
+ *
+ * Only the stored rows move. The column's SQL default stays 0 because nothing inserts
+ * a subscription without it -- Room always writes every column -- so changing it would
+ * mean recreating the table for a value that is never read.
+ */
+ val MIGRATION_5_6 = object : Migration(5, 6) {
+ override fun migrate(db: SupportSQLiteDatabase) {
+ db.execSQL("UPDATE subscriptions SET skipAdChapters = 1")
+ }
+ }
+
fun get(context: Context): AppDatabase = instance ?: synchronized(this) {
instance ?: build(context.applicationContext).also { instance = it }
}
@@ -149,7 +167,9 @@ abstract class AppDatabase : RoomDatabase() {
Room.databaseBuilder(context, AppDatabase::class.java, "listen.db")
// Listed one by one rather than spread from an array: every migration here is a
// deliberate addition, and the list is the record of them.
- .addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5)
+ .addMigrations(
+ MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5, MIGRATION_5_6,
+ )
.addCallback(SEED_DEFAULT_FILTERS)
// No fallbackToDestructiveMigration. A listener's playback positions and play
// history are not reproducible from anywhere, so a missing migration must fail
diff --git a/app/src/main/java/org/terst/listen/data/Entities.kt b/app/src/main/java/org/terst/listen/data/Entities.kt
index ed80c4b..547a4ad 100644
--- a/app/src/main/java/org/terst/listen/data/Entities.kt
+++ b/app/src/main/java/org/terst/listen/data/Entities.kt
@@ -88,11 +88,15 @@ data class SubscriptionEntity(
/**
* Whether to pass over chapters the publisher marked `toc: false`.
*
- * Off by default and opt-in per show. Acting on someone else's metadata to remove audio a
- * listener has not heard is the one part of this feature that can eat an episode, so it is
- * never on unless asked for.
+ * On by default, at Peter's request after living with it off. Only ever acts on sections a
+ * publisher explicitly marked as not part of the episode -- never guessed from a title --
+ * and doing that without being asked each time is the point of the feature.
+ *
+ * The SQL default stays 0 while the Kotlin default is true: Room writes every column on
+ * insert, so the SQL one is only consulted by an ALTER TABLE that has already happened.
+ * Changing it would mean recreating the table for a value nothing reads.
*/
- @ColumnInfo(defaultValue = "0") val skipAdChapters: Boolean = false,
+ @ColumnInfo(defaultValue = "0") val skipAdChapters: Boolean = true,
)
/** One a day, the cadence a drip subscription is for. */
diff --git a/app/src/main/java/org/terst/listen/ui/SkipSettings.kt b/app/src/main/java/org/terst/listen/ui/SkipSettings.kt
index 7c6146c..106e3fd 100644
--- a/app/src/main/java/org/terst/listen/ui/SkipSettings.kt
+++ b/app/src/main/java/org/terst/listen/ui/SkipSettings.kt
@@ -66,9 +66,9 @@ fun SkipSettings(
Text("Skip marked breaks", Modifier.padding(start = 12.dp))
}
Text(
- "Only where the show publishes chapters and marks a section as not part of the " +
- "episode. Nothing is guessed from chapter titles, so a show discussing its own " +
- "sponsors keeps playing.",
+ "On by default. Only acts where the show publishes chapters and marks a section " +
+ "as not part of the episode -- nothing is guessed from chapter titles, so a " +
+ "show discussing its own sponsors keeps playing.",
style = MaterialTheme.typography.bodySmall,
)
}
diff --git a/app/src/test/java/org/terst/listen/playback/PlaybackAdvancerTest.kt b/app/src/test/java/org/terst/listen/playback/PlaybackAdvancerTest.kt
index e22be1e..171114d 100644
--- a/app/src/test/java/org/terst/listen/playback/PlaybackAdvancerTest.kt
+++ b/app/src/test/java/org/terst/listen/playback/PlaybackAdvancerTest.kt
@@ -49,6 +49,7 @@ class PlaybackAdvancerTest {
skipIntroMs: Long = 0,
playbackSpeed: Float? = null,
kind: SubscriptionKind = SubscriptionKind.PODCAST,
+ skipAdChapters: Boolean = true,
): SubscriptionEntity {
val entity = SubscriptionEntity(
id = id,
@@ -58,6 +59,7 @@ class PlaybackAdvancerTest {
addedAtMs = 0,
skipIntroMs = skipIntroMs,
playbackSpeed = playbackSpeed,
+ skipAdChapters = skipAdChapters,
)
subscriptions.insert(entity)
return entity
@@ -356,7 +358,8 @@ class PlaybackAdvancerTest {
),
) { now }
- show(id = "s1")
+ // Explicitly off, rather than leaning on a default that has since flipped to on.
+ show(id = "s1", skipAdChapters = false)
episode("a")
assertEquals(emptyList<Chapter>(), fetching.contextFor("a").chapters)
assertEquals(0, asked)
diff --git a/app/src/test/java/org/terst/listen/playback/PlayheadPolicyTest.kt b/app/src/test/java/org/terst/listen/playback/PlayheadPolicyTest.kt
index 1488559..d0a49f7 100644
--- a/app/src/test/java/org/terst/listen/playback/PlayheadPolicyTest.kt
+++ b/app/src/test/java/org/terst/listen/playback/PlayheadPolicyTest.kt
@@ -69,22 +69,23 @@ class PlayheadPolicyTest {
}
@Test
- fun `inside a marked break, on a show that opted in, it seeks past it`() {
+ fun `inside a marked break it seeks past it`() {
assertEquals(
TickAction.SeekTo(3 * minute),
- decide(
- show = show.copy(skipAdChapters = true),
- chapters = chapters,
- positionMs = 2 * minute + 5_000,
- ),
+ decide(show = show, chapters = chapters, positionMs = 2 * minute + 5_000),
)
}
+ /** Opted out explicitly: skipping is on by default, so this is the deliberate case. */
@Test
- fun `a show that did not opt in keeps playing the break`() {
+ fun `a show that opted out keeps playing the break`() {
assertEquals(
TickAction.Nothing,
- decide(show = show, chapters = chapters, positionMs = 2 * minute + 5_000),
+ decide(
+ show = show.copy(skipAdChapters = false),
+ chapters = chapters,
+ positionMs = 2 * minute + 5_000,
+ ),
)
}