From e2f87ce940eba97356bac52b00a93f5dd1e64c50 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Sat, 23 May 2026 23:27:06 -0400 Subject: [PATCH] style(android): consolidate ResumeController.restore returns into runCatching MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit restore() had 3 explicit returns (row null + decode-failure + empty tracks) — over detekt's ReturnCount limit of 2. Folded the decode + empty-check into a single runCatching chain: runCatching { decode } .onFailure { dao.clear() side-effect } .getOrNull() ?.takeIf { tracks.isNotEmpty() } ?: return Two returns now (row missing + the chain result null). Cleaner read too — the side effect of dropping a corrupt row is right next to the decode it guards. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../minstrel/player/ResumeController.kt | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/android/app/src/main/java/com/fabledsword/minstrel/player/ResumeController.kt b/android/app/src/main/java/com/fabledsword/minstrel/player/ResumeController.kt index 18940a02..f4d48703 100644 --- a/android/app/src/main/java/com/fabledsword/minstrel/player/ResumeController.kt +++ b/android/app/src/main/java/com/fabledsword/minstrel/player/ResumeController.kt @@ -8,7 +8,6 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch -import kotlinx.serialization.SerializationException import kotlinx.serialization.json.Json import timber.log.Timber import javax.inject.Inject @@ -41,21 +40,25 @@ class ResumeController @Inject constructor( } suspend fun restore() { + // runCatching folds row-missing + decode-failure + empty-tracks into + // a single null-or-go-ahead expression so detekt's ReturnCount rule + // is satisfied. The .onFailure side effect drops a corrupted row + // rather than leaving a poison pill across launches. val row = dao.get() ?: return val payload = - try { - json.decodeFromString(row.json) - } catch (e: SerializationException) { - // Schema drift or corruption — drop the row and start clean - // rather than crashing or leaving a poison pill. - Timber.w(e, "ResumeController: dropping unreadable resume state") - dao.clear() - return - } - if (payload.tracks.isEmpty()) return + runCatching { json.decodeFromString(row.json) } + .onFailure { + Timber.w(it, "ResumeController: dropping unreadable resume state") + dao.clear() + } + .getOrNull() + ?.takeIf { it.tracks.isNotEmpty() } + ?: return playerController.setQueue( tracks = payload.tracks, - initialIndex = payload.queueIndex.coerceAtLeast(0).coerceAtMost(payload.tracks.lastIndex), + initialIndex = payload.queueIndex + .coerceAtLeast(0) + .coerceAtMost(payload.tracks.lastIndex), source = payload.source, ) // PositionMs not seeked yet — Player connection may still be