summaryrefslogtreecommitdiff
path: root/app/src/main/java/org/terst/feedreader/ui/ReaderScreen.kt
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/org/terst/feedreader/ui/ReaderScreen.kt')
-rw-r--r--app/src/main/java/org/terst/feedreader/ui/ReaderScreen.kt51
1 files changed, 48 insertions, 3 deletions
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 ced9482..8c2f64e 100644
--- a/app/src/main/java/org/terst/feedreader/ui/ReaderScreen.kt
+++ b/app/src/main/java/org/terst/feedreader/ui/ReaderScreen.kt
@@ -16,9 +16,12 @@ import androidx.compose.material.icons.filled.Bookmark
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.OpenInBrowser
import androidx.compose.material.icons.outlined.Article
import androidx.compose.material3.CircularProgressIndicator
+import androidx.compose.material3.DropdownMenu
+import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
@@ -50,6 +53,7 @@ import org.terst.feedreader.data.Settings
import org.terst.feedreader.readability.ReaderExtractor
import org.terst.feedreader.stash.StashClient
import org.terst.feedreader.stash.StashSaveResult
+import java.net.URLEncoder
// Below this length (of the plain feed-provided HTML), assume it's a teaser/summary,
// not the real article body, and auto-fall-back to on-device Readability extraction.
@@ -64,7 +68,13 @@ private const val THIN_CONTENT_THRESHOLD = 500
*/
@OptIn(ExperimentalFoundationApi::class)
@Composable
-fun ReaderScreen(feedId: String, initialArticleId: String, onBack: () -> Unit, onOpenLink: (String) -> Unit) {
+fun ReaderScreen(
+ feedId: String,
+ initialArticleId: String,
+ onBack: () -> Unit,
+ onOpenLink: (String) -> Unit,
+ onOpenBrowser: (String) -> Unit
+) {
val context = LocalContext.current
val db = remember { AppDatabase.get(context) }
var articleIds by remember(feedId) { mutableStateOf<List<String>?>(null) }
@@ -92,13 +102,23 @@ fun ReaderScreen(feedId: String, initialArticleId: String, onBack: () -> Unit, o
val pagerState = rememberPagerState(initialPage = initialIndex) { safeIds.size }
HorizontalPager(state = pagerState, modifier = Modifier.fillMaxSize()) { page ->
- ReaderContent(articleId = safeIds[page], onBack = onBack, onOpenLink = onOpenLink)
+ ReaderContent(
+ articleId = safeIds[page],
+ onBack = onBack,
+ onOpenLink = onOpenLink,
+ onOpenBrowser = onOpenBrowser
+ )
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
-private fun ReaderContent(articleId: String, onBack: () -> Unit, onOpenLink: (String) -> Unit) {
+private fun ReaderContent(
+ articleId: String,
+ onBack: () -> Unit,
+ onOpenLink: (String) -> Unit,
+ onOpenBrowser: (String) -> Unit
+) {
val context = LocalContext.current
val db = remember { AppDatabase.get(context) }
val scope = rememberCoroutineScope()
@@ -111,6 +131,7 @@ private fun ReaderContent(articleId: String, onBack: () -> Unit, onOpenLink: (St
var isReaderMode by remember(articleId) { mutableStateOf(false) }
var isExtracting by remember(articleId) { mutableStateOf(false) }
var isSaving by remember(articleId) { mutableStateOf(false) }
+ var moreMenuExpanded by remember(articleId) { mutableStateOf(false) }
LaunchedEffect(articleId) {
val loaded = db.articleDao().getById(articleId) ?: return@LaunchedEffect
@@ -250,6 +271,30 @@ private fun ReaderContent(articleId: String, onBack: () -> Unit, onOpenLink: (St
contentDescription = "Save to Stash"
)
}
+ IconButton(onClick = { moreMenuExpanded = true }) {
+ Icon(Icons.Default.MoreVert, contentDescription = "More")
+ }
+ DropdownMenu(expanded = moreMenuExpanded, onDismissRequest = { moreMenuExpanded = false }) {
+ // A real (JS-on) browser, not the extraction pipeline -- search results
+ // and login pages need actual interaction, not a Readability pass.
+ DropdownMenuItem(
+ text = { Text("Find another source") },
+ onClick = {
+ moreMenuExpanded = false
+ val a = currentArticle ?: return@DropdownMenuItem
+ val query = URLEncoder.encode(a.title, "UTF-8")
+ onOpenBrowser("https://www.google.com/search?q=$query")
+ }
+ )
+ DropdownMenuItem(
+ text = { Text("Log in to this site") },
+ onClick = {
+ moreMenuExpanded = false
+ val a = currentArticle ?: return@DropdownMenuItem
+ onOpenBrowser(a.link)
+ }
+ )
+ }
}
)
},