summaryrefslogtreecommitdiff
path: root/app/src/main/java/org/terst
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/org/terst')
-rw-r--r--app/src/main/java/org/terst/feedreader/ui/AddFeedScreen.kt19
-rw-r--r--app/src/main/java/org/terst/feedreader/ui/ReaderScreen.kt70
2 files changed, 42 insertions, 47 deletions
diff --git a/app/src/main/java/org/terst/feedreader/ui/AddFeedScreen.kt b/app/src/main/java/org/terst/feedreader/ui/AddFeedScreen.kt
index 5d19c90..066d8d9 100644
--- a/app/src/main/java/org/terst/feedreader/ui/AddFeedScreen.kt
+++ b/app/src/main/java/org/terst/feedreader/ui/AddFeedScreen.kt
@@ -63,7 +63,14 @@ fun AddFeedScreen(onDone: () -> Unit) {
// as some larger number even though upsert already collapses them to one row each.
val uniqueFeeds = imported.distinctBy { it.xmlUrl }
for (feed in uniqueFeeds) {
- db.feedDao().upsert(FeedEntity(id = feed.xmlUrl, title = feed.title, siteUrl = feed.htmlUrl))
+ // upsert() REPLACEs the whole row -- for a feed that's already subscribed,
+ // building a bare FeedEntity here would silently wipe readerModeDisabled
+ // (and etag/lastModified/lastError) back to defaults on every re-import.
+ // Preserve the existing row's other fields; only title/siteUrl come from OPML.
+ val existing = db.feedDao().getById(feed.xmlUrl)
+ val entity = existing?.copy(title = feed.title, siteUrl = feed.htmlUrl ?: existing.siteUrl)
+ ?: FeedEntity(id = feed.xmlUrl, title = feed.title, siteUrl = feed.htmlUrl)
+ db.feedDao().upsert(entity)
}
FeedFetchWorker.fetchNow(context)
status = "Imported ${uniqueFeeds.size} feed(s)"
@@ -145,9 +152,13 @@ private suspend fun addFeedByUrl(context: android.content.Context, db: AppDataba
if (!it.isSuccessful) return@withContext "Couldn't fetch feed: HTTP ${it.code}"
val body = it.body ?: return@withContext "Empty response"
val parsed = FeedParser.parse(body.byteStream())
- db.feedDao().upsert(
- FeedEntity(id = feedUrl, title = parsed.title.ifBlank { feedUrl }, siteUrl = parsed.siteUrl)
- )
+ // Same REPLACE-wipes-other-fields concern as the OPML import path.
+ val existing = db.feedDao().getById(feedUrl)
+ val entity = existing?.copy(
+ title = parsed.title.ifBlank { feedUrl },
+ siteUrl = parsed.siteUrl ?: existing.siteUrl
+ ) ?: FeedEntity(id = feedUrl, title = parsed.title.ifBlank { feedUrl }, siteUrl = parsed.siteUrl)
+ db.feedDao().upsert(entity)
}
FeedFetchWorker.fetchNow(context)
"Added"
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 9b53f8c..eae11af 100644
--- a/app/src/main/java/org/terst/feedreader/ui/ReaderScreen.kt
+++ b/app/src/main/java/org/terst/feedreader/ui/ReaderScreen.kt
@@ -3,7 +3,7 @@ package org.terst.feedreader.ui
import android.content.Intent
import android.net.Uri
import androidx.compose.foundation.ExperimentalFoundationApi
-import androidx.compose.foundation.gestures.detectDragGestures
+import androidx.compose.foundation.gestures.detectHorizontalDragGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
@@ -58,7 +58,6 @@ import org.terst.feedreader.readability.ReaderExtractor
import org.terst.feedreader.stash.StashClient
import org.terst.feedreader.stash.StashSaveResult
import java.net.URLEncoder
-import kotlin.math.abs
// 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.
@@ -106,59 +105,44 @@ fun ReaderScreen(
val initialIndex = safeIds.indexOf(initialArticleId).coerceAtLeast(0)
val pagerState = rememberPagerState(initialPage = initialIndex) { safeIds.size }
val scope = rememberCoroutineScope()
- val directionLockPx = with(LocalDensity.current) { 16.dp.toPx() }
val swipeThresholdPx = with(LocalDensity.current) { 80.dp.toPx() }
// HorizontalPager's own full-surface drag detection was grabbing ordinary vertical
// scrolling inside the embedded WebView (a native View, which doesn't arbitrate with
// Compose's gesture system the way a pure-Compose scrollable child would) as an
- // attempted horizontal page-turn on anything less than a perfectly vertical swipe --
- // which is most real thumb scrolling. An edge-zone-gated version of this was tried
- // first, but on gesture-nav Android the screen edges belong to the OS's own back
- // gesture, which wins before the app ever sees the touch (confirmed live: an edge
- // swipe triggered system back, not the pager). So instead: disable the Pager's own
- // gesture and drive it from a detector that works anywhere on screen but only commits
- // to a page turn once the drag is clearly horizontal-dominant (>2x the vertical
- // movement) -- ordinary scrolling, even sloppy/diagonal, stays vertical-dominant and
- // is left completely unconsumed for the WebView to handle normally.
+ // attempted horizontal page-turn on anything less than a perfectly vertical swipe.
+ // detectHorizontalDragGestures has its own orientation-aware touch-slop detection, so
+ // it already declines to engage for vertical-dominant movement -- confirmed live: a
+ // diagonal mid-screen scroll stays vertical, doesn't page-turn. (A generic,
+ // non-oriented detectDragGestures was tried for a stricter dx/dy ratio check and broke
+ // scrolling entirely: its slop detector claims the first bit of movement in ANY
+ // direction isotropically, before it knows which way the gesture is really going --
+ // reported live as "the article view doesn't scroll at all anymore.") Also: page-turn
+ // commit is based on total drag distance, not where the gesture started, since an
+ // edge-anchored version collided with Android's own edge-swipe-back gesture (confirmed
+ // live: an edge swipe triggered system back, not the pager).
Box(
modifier = Modifier
.fillMaxSize()
.pointerInput(safeIds.size) {
- var totalDx = 0f
- var totalDy = 0f
- var committedHorizontal = false
- detectDragGestures(
- onDragStart = {
- totalDx = 0f
- totalDy = 0f
- committedHorizontal = false
- },
- onDragCancel = { committedHorizontal = false },
+ var totalDrag = 0f
+ detectHorizontalDragGestures(
+ onDragStart = { totalDrag = 0f },
+ onDragCancel = { totalDrag = 0f },
onDragEnd = {
- if (committedHorizontal) {
- val direction = when {
- totalDx <= -swipeThresholdPx -> 1
- totalDx >= swipeThresholdPx -> -1
- else -> 0
- }
- if (direction != 0) {
- val target = (pagerState.currentPage + direction).coerceIn(0, safeIds.size - 1)
- scope.launch { pagerState.animateScrollToPage(target) }
- }
+ val direction = when {
+ totalDrag <= -swipeThresholdPx -> 1
+ totalDrag >= swipeThresholdPx -> -1
+ else -> 0
}
- committedHorizontal = false
- },
- onDrag = { change, dragAmount ->
- totalDx += dragAmount.x
- totalDy += dragAmount.y
- if (!committedHorizontal &&
- abs(totalDx) > directionLockPx &&
- abs(totalDx) > abs(totalDy) * 2f
- ) {
- committedHorizontal = true
+ if (direction != 0) {
+ val target = (pagerState.currentPage + direction).coerceIn(0, safeIds.size - 1)
+ scope.launch { pagerState.animateScrollToPage(target) }
}
- if (committedHorizontal) change.consume()
+ },
+ onHorizontalDrag = { change, dragAmount ->
+ change.consume()
+ totalDrag += dragAmount
}
)
}