From f202c603259c40c4d21a4385c9f69a3efca87acc Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Sat, 25 Jul 2026 00:55:59 +0000 Subject: Text-only bottom bar, re-extract action, fix YouTube thumbnails, verify Stash creds before saving - Bottom bar: Previous/Keep unread/Next are now plain text labels, no icons - Add "Re-download and re-extract" to the overflow menu (ReaderScreen and LinkReaderScreen) to force a fresh fetch + Readability pass on demand, overwriting whatever's cached - Fix a real compile bug in the previous commit's reader-mode-off handler (passed null into a non-null setExtractedContent) via a proper clearExtractedContent() DAO query - YouTube embeds: fixed the broken-image-glyph bug two ways -- (1) an 11-char video-ID regex was accidentally matching a playlist embed's literal "videoseries" placeholder path, building a thumbnail URL for a video that doesn't exist, and (2) Readability's link-density cleanup was discarding the replacement entirely (a bare reads as an ad/share unit). Restructured as a
/
pair -- the same shape a normal captioned photo takes -- confirmed live this survives extraction intact - Stash settings: API key field is now a password field with a show/hide toggle, and "Verify and save" makes a real authenticated request before persisting anything, showing why it failed instead of silently saving bad credentials Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01EZ7ikw2ukGJFTHE3bJS7zL --- .../java/org/terst/feedreader/ui/ReaderScreen.kt | 49 ++++++++++++++-------- 1 file changed, 31 insertions(+), 18 deletions(-) (limited to 'app/src/main/java/org/terst/feedreader/ui/ReaderScreen.kt') diff --git a/app/src/main/java/org/terst/feedreader/ui/ReaderScreen.kt b/app/src/main/java/org/terst/feedreader/ui/ReaderScreen.kt index b7f6018..06227b7 100644 --- a/app/src/main/java/org/terst/feedreader/ui/ReaderScreen.kt +++ b/app/src/main/java/org/terst/feedreader/ui/ReaderScreen.kt @@ -24,10 +24,7 @@ import androidx.compose.material.icons.filled.BookmarkBorder import androidx.compose.material.icons.filled.CloudDone import androidx.compose.material.icons.filled.CloudUpload import androidx.compose.material.icons.filled.MoreVert -import androidx.compose.material.icons.filled.NavigateBefore -import androidx.compose.material.icons.filled.NavigateNext import androidx.compose.material.icons.filled.OpenInBrowser -import androidx.compose.material.icons.filled.SkipNext import androidx.compose.material.icons.outlined.Article import androidx.compose.material3.AlertDialog import androidx.compose.material3.BottomAppBar @@ -252,7 +249,7 @@ private fun ReaderContent( } else { isReaderMode = false readerContent = null - db.articleDao().setExtractedContent(articleId, null) + db.articleDao().clearExtractedContent(articleId) snackbarHostState.showSnackbar("Reader mode disabled for $feedLabel") } } @@ -393,6 +390,32 @@ private fun ReaderContent( onOpenBrowser(a.link) } ) + // Forces a fresh fetch + Readability pass, overwriting whatever's + // cached -- for when extraction came back thin, stale, or broken + // (e.g. a YouTube thumbnail that failed to resolve) and simply hasn't + // been retried since whatever caused that. + DropdownMenuItem( + enabled = !isExtracting, + text = { Text("Re-download and re-extract") }, + onClick = { + moreMenuExpanded = false + val a = currentArticle ?: return@DropdownMenuItem + scope.launch { + isExtracting = true + val extracted = ReaderExtractor.extract(context, a.link) + isExtracting = false + val content = extracted?.content + if (content != null) { + readerContent = content + isReaderMode = true + db.articleDao().setExtractedContent(a.id, content) + snackbarHostState.showSnackbar("Re-extracted") + } else { + snackbarHostState.showSnackbar("Re-extraction failed") + } + } + } + ) DropdownMenuItem( text = { Text("Report bug") }, onClick = { @@ -406,26 +429,16 @@ private fun ReaderContent( }, bottomBar = { BottomAppBar { - TextButton( - onClick = onPrevious, - enabled = hasPrevious, - modifier = Modifier.weight(1f) - ) { - Icon(Icons.Default.NavigateBefore, contentDescription = null) + TextButton(onClick = onPrevious, enabled = hasPrevious, modifier = Modifier.weight(1f)) { Text("Previous") } // Advances like Next, but skips the implicit "mark read" that moving on // normally carries -- for "I looked, but I'm not done with this one yet." - IconButton(onClick = onNextKeepUnread, enabled = hasNext) { - Icon(Icons.Default.SkipNext, contentDescription = "Next, keep unread") + TextButton(onClick = onNextKeepUnread, enabled = hasNext, modifier = Modifier.weight(1f)) { + Text("Keep unread") } - TextButton( - onClick = onNext, - enabled = hasNext, - modifier = Modifier.weight(1f) - ) { + TextButton(onClick = onNext, enabled = hasNext, modifier = Modifier.weight(1f)) { Text("Next") - Icon(Icons.Default.NavigateNext, contentDescription = null) } } }, -- cgit v1.2.3