summaryrefslogtreecommitdiff
path: root/app/src/main/java/org/terst/feedreader/ui/LinkReaderScreen.kt
diff options
context:
space:
mode:
authorPeter Stone <thepeterstone@gmail.com>2026-07-24 03:28:31 +0000
committerPeter Stone <thepeterstone@gmail.com>2026-07-24 03:28:31 +0000
commit72f76cc41ae406e00a4dd9d448e2b552f9a6baaa (patch)
tree5f23e410b2ac4f8dddf89422ab57e738b3b04b2f /app/src/main/java/org/terst/feedreader/ui/LinkReaderScreen.kt
parentab392e2ab983a4c87e241b457c98244251b2206a (diff)
Collapsible folders, long-press link menu, YouTube thumbnails, strip more Ars sequel chrome
- Feed list: folders now collapse (start collapsed, with a per-folder unread count so collapsing doesn't hide "is there anything new") - Long-pressing a link inside an article shows an action menu (open in browser, share, save to Stash, save for later) instead of WebView's default text-selection popup -- confirmed live end to end, including the Stash/save-for-later paths creating a real standalone article - New shared ensureStandaloneArticle() helper (data/ArticleSaving.kt), factored out of ShareReceiverActivity, now also used by the long-press menu - YouTube iframe embeds become tap-to-open thumbnails (JS is off in the reader WebView, so the real player never worked anyway); tapping one goes straight to the YouTube app/browser instead of our own article-extraction pipeline - Fixed back navigation through a chain of links-within-links: each hop was stacking a new backstack entry, so back stepped through the chain one link at a time instead of returning straight to the source article. Confirmed live: A -> link -> B -> link -> C, one back-press now goes straight to A - Extended the <header> chrome-stripping from last round: also strip <footer>, an author bio card, and a "Most Read" trending-stories widget -- confirmed live one of the latter showed up as a giant unrelated photo plus an empty numbered list (its lazy-loaded items never populate in this hidden, off-screen extraction WebView) Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EZ7ikw2ukGJFTHE3bJS7zL
Diffstat (limited to 'app/src/main/java/org/terst/feedreader/ui/LinkReaderScreen.kt')
-rw-r--r--app/src/main/java/org/terst/feedreader/ui/LinkReaderScreen.kt49
1 files changed, 44 insertions, 5 deletions
diff --git a/app/src/main/java/org/terst/feedreader/ui/LinkReaderScreen.kt b/app/src/main/java/org/terst/feedreader/ui/LinkReaderScreen.kt
index 4c7251f..c001b69 100644
--- a/app/src/main/java/org/terst/feedreader/ui/LinkReaderScreen.kt
+++ b/app/src/main/java/org/terst/feedreader/ui/LinkReaderScreen.kt
@@ -46,14 +46,12 @@ import org.terst.feedreader.data.AppDatabase
import org.terst.feedreader.data.ArticleEntity
import org.terst.feedreader.data.Net
import org.terst.feedreader.data.Settings
+import org.terst.feedreader.data.ensureStandaloneArticle
+import org.terst.feedreader.data.urlToArticleId
import org.terst.feedreader.readability.ReaderExtractor
import org.terst.feedreader.stash.StashClient
import org.terst.feedreader.stash.StashSaveResult
import java.net.URLEncoder
-import java.security.MessageDigest
-
-private fun urlToArticleId(url: String): String =
- MessageDigest.getInstance("SHA-256").digest(url.toByteArray()).joinToString("") { "%02x".format(it) }
/**
* A reader view for links tapped inside an article's WebView -- extracts the linked
@@ -83,6 +81,7 @@ fun LinkReaderScreen(url: String, onBack: () -> Unit, onOpenLink: (String) -> Un
var isReaderMode by remember(url) { mutableStateOf(true) }
var isSaving by remember(url) { mutableStateOf(false) }
var moreMenuExpanded by remember(url) { mutableStateOf(false) }
+ var longPressedLink by remember(url) { mutableStateOf<String?>(null) }
LaunchedEffect(url) {
val existing = db.articleDao().getById(articleId)
@@ -223,7 +222,7 @@ fun LinkReaderScreen(url: String, onBack: () -> Unit, onOpenLink: (String) -> Un
AndroidView(
modifier = Modifier.fillMaxSize(),
factory = { ctx ->
- newReaderWebView(ctx, onOpenLink).apply {
+ newReaderWebView(ctx, onOpenLink, onLongPressLink = { longPressedLink = it }).apply {
loadDataWithBaseURL(url, wrapReaderHtml(currentExtractedContent, extractedTitle), "text/html", "UTF-8", null)
loadedContent.value = currentExtractedContent
}
@@ -255,5 +254,45 @@ fun LinkReaderScreen(url: String, onBack: () -> Unit, onOpenLink: (String) -> Un
else -> CircularProgressIndicator(modifier = Modifier.align(Alignment.Center))
}
}
+ longPressedLink?.let { linkUrl ->
+ LinkActionsDialog(
+ url = linkUrl,
+ onDismiss = { longPressedLink = null },
+ onOpenInBrowser = { context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(linkUrl))) },
+ onShare = {
+ val send = Intent(Intent.ACTION_SEND).apply {
+ type = "text/plain"
+ putExtra(Intent.EXTRA_TEXT, linkUrl)
+ }
+ context.startActivity(Intent.createChooser(send, null))
+ },
+ onSaveToStash = {
+ scope.launch {
+ val entity = ensureStandaloneArticle(context, db, linkUrl)
+ val settings = Settings(context)
+ val client = StashClient(Net.client, settings.stashBaseUrlNow(), settings.stashApiKeyNow())
+ when (val result = client.saveArticle(linkUrl, entity.title)) {
+ is StashSaveResult.Saved -> {
+ db.articleDao().setStashArtifactId(entity.id, result.artifact.id)
+ snackbarHostState.showSnackbar("Saved to Stash")
+ }
+ is StashSaveResult.AlreadySaved -> {
+ db.articleDao().setStashArtifactId(entity.id, result.existingId)
+ snackbarHostState.showSnackbar("Already in Stash")
+ }
+ is StashSaveResult.Failed ->
+ snackbarHostState.showSnackbar("Save failed: ${result.message}")
+ }
+ }
+ },
+ onSaveForLater = {
+ scope.launch {
+ val entity = ensureStandaloneArticle(context, db, linkUrl)
+ if (!entity.isSaved) db.articleDao().setSaved(entity.id, true)
+ snackbarHostState.showSnackbar("Saved for later")
+ }
+ }
+ )
+ }
}
}