diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-07-24 03:28:31 +0000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-07-24 03:28:31 +0000 |
| commit | 72f76cc41ae406e00a4dd9d448e2b552f9a6baaa (patch) | |
| tree | 5f23e410b2ac4f8dddf89422ab57e738b3b04b2f /app/src/main/java/org/terst/feedreader/ui/LinkReaderScreen.kt | |
| parent | ab392e2ab983a4c87e241b457c98244251b2206a (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.kt | 49 |
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") + } + } + ) + } } } |
