From a422e42f71f1dee670d3dc7f73d0cef7ff420a92 Mon Sep 17 00:00:00 2001
From: Josiah Campbell <9521010+jocmp@users.noreply.github.com>
Date: Sun, 10 Nov 2024 20:45:29 -0600
Subject: [PATCH 1/3] wip
---
.../app/ui/articles/ArticleLayout.kt | 4 +--
.../app/ui/articles/detail/ArticleReader.kt | 2 +-
.../capyreader/app/ui/components/WebView.kt | 36 ++-----------------
article_forge/views/template.liquid | 4 +--
.../jocmp/capy/articles/ArticleRenderer.kt | 2 --
.../com/jocmp/capy/articles/CleanLinks.kt | 17 ---------
.../java/com/jocmp/capy/articles/ParseHTML.kt | 2 --
capy/src/main/res/raw/template.html | 4 +--
.../android/en-US/changelogs/1071.txt | 6 ++++
9 files changed, 16 insertions(+), 61 deletions(-)
delete mode 100644 capy/src/main/java/com/jocmp/capy/articles/CleanLinks.kt
diff --git a/app/src/main/java/com/capyreader/app/ui/articles/ArticleLayout.kt b/app/src/main/java/com/capyreader/app/ui/articles/ArticleLayout.kt
index 8f2a64ab..a9f82511 100644
--- a/app/src/main/java/com/capyreader/app/ui/articles/ArticleLayout.kt
+++ b/app/src/main/java/com/capyreader/app/ui/articles/ArticleLayout.kt
@@ -133,7 +133,7 @@ fun ArticleLayout(
scaffoldNavigator.navigateTo(ListDetailPaneScaffoldRole.Detail)
}
- val scrollState = rememberSaveable(key = article?.id, saver = ScrollState.Saver) {
+ val scrollState = rememberSaveable(saver = ScrollState.Saver) {
ScrollState(initial = 0)
}
val webViewState = rememberWebViewState(
@@ -141,7 +141,7 @@ fun ArticleLayout(
mediaUrl = it
},
onPageStarted = {
- coroutineScope.launch {
+ coroutineScope.launchUI {
scrollState.scrollTo(0)
}
}
diff --git a/app/src/main/java/com/capyreader/app/ui/articles/detail/ArticleReader.kt b/app/src/main/java/com/capyreader/app/ui/articles/detail/ArticleReader.kt
index 5857d965..4b9e2f6c 100644
--- a/app/src/main/java/com/capyreader/app/ui/articles/detail/ArticleReader.kt
+++ b/app/src/main/java/com/capyreader/app/ui/articles/detail/ArticleReader.kt
@@ -40,7 +40,7 @@ fun ArticleReader(
lastScrollY = scrollState.value
},
)
- Spacer(modifier = Modifier.height(150.dp))
+ Spacer(modifier = Modifier.height(120.dp))
}
}
diff --git a/app/src/main/java/com/capyreader/app/ui/components/WebView.kt b/app/src/main/java/com/capyreader/app/ui/components/WebView.kt
index 41351d83..77dc8555 100644
--- a/app/src/main/java/com/capyreader/app/ui/components/WebView.kt
+++ b/app/src/main/java/com/capyreader/app/ui/components/WebView.kt
@@ -16,14 +16,10 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.viewinterop.AndroidView
-import androidx.core.graphics.drawable.toBitmap
import androidx.webkit.WebViewAssetLoader
import androidx.webkit.WebViewAssetLoader.AssetsPathHandler
import androidx.webkit.WebViewAssetLoader.DEFAULT_DOMAIN
import androidx.webkit.WebViewAssetLoader.ResourcesPathHandler
-import coil.executeBlocking
-import coil.imageLoader
-import coil.request.ImageRequest
import com.capyreader.app.common.AppPreferences
import com.capyreader.app.common.WebViewInterface
import com.capyreader.app.common.openLink
@@ -74,7 +70,7 @@ fun WebView(
class AccompanistWebViewClient(
private val assetLoader: WebViewAssetLoader,
- private val onPageStarted: () -> Unit
+ private val onPageStarted: () -> Unit,
) : WebViewClient(),
KoinComponent {
lateinit var state: WebViewState
@@ -84,10 +80,10 @@ class AccompanistWebViewClient(
override fun onPageStarted(view: WebView, url: String?, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
+ onPageStarted()
view.postVisualStateCallback(requestId, object : WebView.VisualStateCallback() {
override fun onComplete(requestId: Long) {
- onPageStarted()
view.visibility = View.VISIBLE
}
})
@@ -95,36 +91,10 @@ class AccompanistWebViewClient(
private val requestId = 1200L
- override fun onPageFinished(view: WebView, url: String?) {
- super.onPageFinished(view, url)
- }
-
override fun shouldInterceptRequest(
view: WebView,
request: WebResourceRequest
): WebResourceResponse? {
- val accept = request.requestHeaders.getOrDefault("Accept", null)
-
- if (accept != null && accept.contains("image")) {
- try {
- val imageRequest = ImageRequest.Builder(view.context)
- .data(request.url)
- .build()
- val bitmap =
- view.context.imageLoader.executeBlocking(imageRequest).drawable?.toBitmap()
-
- if (bitmap != null) {
- return WebResourceResponse(
- "image/jpg",
- "UTF-8",
- jpegStream(bitmap)
- )
- }
- } catch (exception: Exception) {
- return null
- }
- }
-
return assetLoader.shouldInterceptRequest(request.url)
}
@@ -171,7 +141,7 @@ class WebViewState(
withContext(Dispatchers.Main) {
webView.loadDataWithBaseURL(
- ASSET_BASE_URL,
+ null,
html,
null,
"UTF-8",
diff --git a/article_forge/views/template.liquid b/article_forge/views/template.liquid
index 7656c4c9..22a371b2 100644
--- a/article_forge/views/template.liquid
+++ b/article_forge/views/template.liquid
@@ -17,8 +17,8 @@
}
{{font_preload}}
-
-
+
+
diff --git a/capy/src/main/java/com/jocmp/capy/articles/ArticleRenderer.kt b/capy/src/main/java/com/jocmp/capy/articles/ArticleRenderer.kt
index 225f29a3..ccece280 100644
--- a/capy/src/main/java/com/jocmp/capy/articles/ArticleRenderer.kt
+++ b/capy/src/main/java/com/jocmp/capy/articles/ArticleRenderer.kt
@@ -48,8 +48,6 @@ class ArticleRenderer(
document.getElementById("article-body-content")?.append(article.content)
- cleanLinks(document)
-
return document.html()
}
diff --git a/capy/src/main/java/com/jocmp/capy/articles/CleanLinks.kt b/capy/src/main/java/com/jocmp/capy/articles/CleanLinks.kt
deleted file mode 100644
index 55dd58a8..00000000
--- a/capy/src/main/java/com/jocmp/capy/articles/CleanLinks.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.jocmp.capy.articles
-
-import org.jsoup.nodes.Element
-
-internal fun cleanLinks(element: Element) {
- element.getElementsByTag("img").forEachIndexed{ index, child ->
- child.attr("src", child.absUrl("src"))
-
- if (index > 0) {
- child.attr("loading", "lazy")
- }
- }
-
- element.select("img[data-src]").forEach { child ->
- child.attr("src", child.absUrl("data-src"))
- }
-}
diff --git a/capy/src/main/java/com/jocmp/capy/articles/ParseHTML.kt b/capy/src/main/java/com/jocmp/capy/articles/ParseHTML.kt
index 40dc473b..e932ceaa 100644
--- a/capy/src/main/java/com/jocmp/capy/articles/ParseHTML.kt
+++ b/capy/src/main/java/com/jocmp/capy/articles/ParseHTML.kt
@@ -13,8 +13,6 @@ fun parseHtml(article: Article, html: String): String {
element.append(" ")
}
- cleanLinks(content)
-
return content.html()
} catch (ex: Throwable) {
return ""
diff --git a/capy/src/main/res/raw/template.html b/capy/src/main/res/raw/template.html
index 1d557c25..e77a5ebe 100644
--- a/capy/src/main/res/raw/template.html
+++ b/capy/src/main/res/raw/template.html
@@ -17,8 +17,8 @@
}
{{font_preload}}
-
-
+
+
diff --git a/fastlane/metadata/android/en-US/changelogs/1071.txt b/fastlane/metadata/android/en-US/changelogs/1071.txt
index e91e98d8..05048e66 100644
--- a/fastlane/metadata/android/en-US/changelogs/1071.txt
+++ b/fastlane/metadata/android/en-US/changelogs/1071.txt
@@ -1 +1,7 @@
+Added
+
• Add initial support for FreshRSS and Google Reader API
+
+Fixed
+
+• Fixed missing images on some articles
From 8a1e1ba9c3e72faaa423196e295c50cf19153e6c Mon Sep 17 00:00:00 2001
From: Josiah Campbell <9521010+jocmp@users.noreply.github.com>
Date: Sun, 10 Nov 2024 21:23:57 -0600
Subject: [PATCH 2/3] Use OR instead of AND for visibility
---
.../com/capyreader/app/ui/components/WebView.kt | 17 +++--------------
1 file changed, 3 insertions(+), 14 deletions(-)
diff --git a/app/src/main/java/com/capyreader/app/ui/components/WebView.kt b/app/src/main/java/com/capyreader/app/ui/components/WebView.kt
index 77dc8555..76ab2651 100644
--- a/app/src/main/java/com/capyreader/app/ui/components/WebView.kt
+++ b/app/src/main/java/com/capyreader/app/ui/components/WebView.kt
@@ -27,6 +27,7 @@ import com.capyreader.app.ui.articles.detail.articleTemplateColors
import com.capyreader.app.ui.articles.detail.byline
import com.jocmp.capy.Article
import com.jocmp.capy.articles.ArticleRenderer
+import com.jocmp.capy.common.launchUI
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -34,9 +35,6 @@ import kotlinx.coroutines.withContext
import org.koin.compose.koinInject
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
-import java.io.ByteArrayInputStream
-import java.io.ByteArrayOutputStream
-import java.io.InputStream
/**
* Doesn't really fetch from androidplatform.net. This is used as a placeholder domain:
@@ -126,7 +124,7 @@ class WebViewState(
val id = article.id
scope.launch {
- if (htmlId != null && id != htmlId) {
+ if (htmlId == null || id != htmlId) {
webView.visibility = View.INVISIBLE
}
@@ -207,13 +205,4 @@ fun rememberWebViewState(
client.state = it
}
}
-}
-
-private fun jpegStream(
- bitmap: Bitmap,
-): InputStream {
- val byteArrayOutputStream = ByteArrayOutputStream()
- bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream)
- val bitmapData = byteArrayOutputStream.toByteArray()
- return ByteArrayInputStream(bitmapData)
-}
+}
\ No newline at end of file
From 92f91837eabde233c8e8544f0302d8edd5b62371 Mon Sep 17 00:00:00 2001
From: Josiah Campbell <9521010+jocmp@users.noreply.github.com>
Date: Sun, 10 Nov 2024 21:45:59 -0600
Subject: [PATCH 3/3] Fix scroll bug
---
.../app/ui/articles/ArticleLayout.kt | 10 -------
.../app/ui/articles/detail/ArticleReader.kt | 5 +++-
.../app/ui/articles/detail/ArticleView.kt | 28 ++++++++---------
.../capyreader/app/ui/components/WebView.kt | 30 ++-----------------
4 files changed, 20 insertions(+), 53 deletions(-)
diff --git a/app/src/main/java/com/capyreader/app/ui/articles/ArticleLayout.kt b/app/src/main/java/com/capyreader/app/ui/articles/ArticleLayout.kt
index a9f82511..864cfd18 100644
--- a/app/src/main/java/com/capyreader/app/ui/articles/ArticleLayout.kt
+++ b/app/src/main/java/com/capyreader/app/ui/articles/ArticleLayout.kt
@@ -4,7 +4,6 @@ import androidx.activity.compose.BackHandler
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
-import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
@@ -133,18 +132,10 @@ fun ArticleLayout(
scaffoldNavigator.navigateTo(ListDetailPaneScaffoldRole.Detail)
}
- val scrollState = rememberSaveable(saver = ScrollState.Saver) {
- ScrollState(initial = 0)
- }
val webViewState = rememberWebViewState(
onNavigateToMedia = {
mediaUrl = it
},
- onPageStarted = {
- coroutineScope.launchUI {
- scrollState.scrollTo(0)
- }
- }
)
fun scrollToArticle(index: Int) {
@@ -373,7 +364,6 @@ fun ArticleLayout(
ArticleView(
article = article,
webViewState = webViewState,
- scrollState = scrollState,
articles = indexedArticles,
onBackPressed = {
coroutineScope.launchUI {
diff --git a/app/src/main/java/com/capyreader/app/ui/articles/detail/ArticleReader.kt b/app/src/main/java/com/capyreader/app/ui/articles/detail/ArticleReader.kt
index 4b9e2f6c..5de49c51 100644
--- a/app/src/main/java/com/capyreader/app/ui/articles/detail/ArticleReader.kt
+++ b/app/src/main/java/com/capyreader/app/ui/articles/detail/ArticleReader.kt
@@ -23,9 +23,12 @@ import com.jocmp.capy.Article
@Composable
fun ArticleReader(
article: Article,
- scrollState: ScrollState,
webViewState: WebViewState,
) {
+ val scrollState = rememberSaveable(saver = ScrollState.Saver) {
+ ScrollState(initial = 0)
+ }
+
var lastScrollY by rememberSaveable { mutableIntStateOf(0) }
ColumnScrollbar(state = scrollState) {
diff --git a/app/src/main/java/com/capyreader/app/ui/articles/detail/ArticleView.kt b/app/src/main/java/com/capyreader/app/ui/articles/detail/ArticleView.kt
index 89b4f3a5..a45a8adb 100644
--- a/app/src/main/java/com/capyreader/app/ui/articles/detail/ArticleView.kt
+++ b/app/src/main/java/com/capyreader/app/ui/articles/detail/ArticleView.kt
@@ -8,7 +8,6 @@ import androidx.compose.animation.expandVertically
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkVertically
-import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
@@ -26,6 +25,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
+import androidx.compose.runtime.key
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
@@ -49,7 +49,6 @@ import org.koin.compose.koinInject
fun ArticleView(
article: Article,
webViewState: WebViewState,
- scrollState: ScrollState,
articles: IndexedArticles,
onBackPressed: () -> Unit,
onToggleRead: () -> Unit,
@@ -93,18 +92,19 @@ fun ArticleView(
)
},
reader = {
- ArticlePullRefresh(
- toolbars.show && !toolbars.pinned,
- onToggleFullContent = onToggleFullContent,
- onRequestNext = onRequestNext,
- onRequestPrevious = onRequestPrevious,
- articles = articles,
- ) {
- ArticleReader(
- article = article,
- webViewState = webViewState,
- scrollState = scrollState,
- )
+ key(article.id) {
+ ArticlePullRefresh(
+ toolbars.show && !toolbars.pinned,
+ onToggleFullContent = onToggleFullContent,
+ onRequestNext = onRequestNext,
+ onRequestPrevious = onRequestPrevious,
+ articles = articles,
+ ) {
+ ArticleReader(
+ article = article,
+ webViewState = webViewState,
+ )
+ }
}
},
bottomBar = {
diff --git a/app/src/main/java/com/capyreader/app/ui/components/WebView.kt b/app/src/main/java/com/capyreader/app/ui/components/WebView.kt
index 76ab2651..d5dab306 100644
--- a/app/src/main/java/com/capyreader/app/ui/components/WebView.kt
+++ b/app/src/main/java/com/capyreader/app/ui/components/WebView.kt
@@ -1,8 +1,6 @@
package com.capyreader.app.ui.components
import android.annotation.SuppressLint
-import android.graphics.Bitmap
-import android.view.View
import android.webkit.WebResourceRequest
import android.webkit.WebResourceResponse
import android.webkit.WebView
@@ -27,7 +25,6 @@ import com.capyreader.app.ui.articles.detail.articleTemplateColors
import com.capyreader.app.ui.articles.detail.byline
import com.jocmp.capy.Article
import com.jocmp.capy.articles.ArticleRenderer
-import com.jocmp.capy.common.launchUI
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@@ -68,7 +65,6 @@ fun WebView(
class AccompanistWebViewClient(
private val assetLoader: WebViewAssetLoader,
- private val onPageStarted: () -> Unit,
) : WebViewClient(),
KoinComponent {
lateinit var state: WebViewState
@@ -76,19 +72,6 @@ class AccompanistWebViewClient(
private val appPreferences by inject()
- override fun onPageStarted(view: WebView, url: String?, favicon: Bitmap?) {
- super.onPageStarted(view, url, favicon)
- onPageStarted()
-
- view.postVisualStateCallback(requestId, object : WebView.VisualStateCallback() {
- override fun onComplete(requestId: Long) {
- view.visibility = View.VISIBLE
- }
- })
- }
-
- private val requestId = 1200L
-
override fun shouldInterceptRequest(
view: WebView,
request: WebResourceRequest
@@ -124,12 +107,6 @@ class WebViewState(
val id = article.id
scope.launch {
- if (htmlId == null || id != htmlId) {
- webView.visibility = View.INVISIBLE
- }
-
- htmlId = id
-
withContext(Dispatchers.IO) {
val html = renderer.render(
article,
@@ -163,7 +140,6 @@ class WebViewState(
fun rememberWebViewState(
renderer: ArticleRenderer = koinInject(),
onNavigateToMedia: (url: String) -> Unit,
- onPageStarted: () -> Unit,
): WebViewState {
val colors = articleTemplateColors()
val scope = rememberCoroutineScope()
@@ -171,13 +147,11 @@ fun rememberWebViewState(
val client = remember {
AccompanistWebViewClient(
- assetLoader =
- WebViewAssetLoader.Builder()
+ assetLoader = WebViewAssetLoader.Builder()
.setDomain(DEFAULT_DOMAIN)
.addPathHandler("/assets/", AssetsPathHandler(context))
.addPathHandler("/res/", ResourcesPathHandler(context))
.build(),
- onPageStarted = onPageStarted,
)
}
@@ -205,4 +179,4 @@ fun rememberWebViewState(
client.state = it
}
}
-}
\ No newline at end of file
+}