diff options
Diffstat (limited to 'app/src/main')
| -rw-r--r-- | app/src/main/java/org/terst/feedreader/ui/AddFeedScreen.kt | 19 | ||||
| -rw-r--r-- | app/src/main/java/org/terst/feedreader/ui/ReaderScreen.kt | 70 |
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 } ) } |
