parent
5e569d1303
commit
4c7ff2a84e
|
@ -85,9 +85,8 @@ dependencies {
|
||||||
// https://github.com/dankito/Readability4J
|
// https://github.com/dankito/Readability4J
|
||||||
implementation "net.dankito.readability4j:readability4j:$readability4j"
|
implementation "net.dankito.readability4j:readability4j:$readability4j"
|
||||||
|
|
||||||
// https://github.com/muhrifqii/ParseRSS/releases
|
// https://mvnrepository.com/artifact/com.rometools/rome
|
||||||
implementation "com.github.muhrifqii.ParseRSS:parserss:$parseRSS"
|
implementation "com.rometools:rome:$rome"
|
||||||
implementation "com.github.muhrifqii.ParseRSS:retrofit:$parseRSS"
|
|
||||||
|
|
||||||
// https://coil-kt.github.io/coil/changelog/
|
// https://coil-kt.github.io/coil/changelog/
|
||||||
implementation("io.coil-kt:coil-compose:$coil")
|
implementation("io.coil-kt:coil-compose:$coil")
|
||||||
|
|
5
app/proguard-rules.pro
vendored
5
app/proguard-rules.pro
vendored
|
@ -29,4 +29,7 @@
|
||||||
# ksoap2 XmlPullParser confusion
|
# ksoap2 XmlPullParser confusion
|
||||||
-dontwarn org.xmlpull.v1.XmlPullParser
|
-dontwarn org.xmlpull.v1.XmlPullParser
|
||||||
-dontwarn org.xmlpull.v1.XmlSerializer
|
-dontwarn org.xmlpull.v1.XmlSerializer
|
||||||
-keep class org.xmlpull.v1.* {*;}
|
-keep class org.xmlpull.v1.* {*;}
|
||||||
|
|
||||||
|
# Rome
|
||||||
|
-keep class com.rometools.** { *; }
|
|
@ -14,7 +14,6 @@ import me.ash.reader.data.repository.*
|
||||||
import me.ash.reader.data.source.AppNetworkDataSource
|
import me.ash.reader.data.source.AppNetworkDataSource
|
||||||
import me.ash.reader.data.source.OpmlLocalDataSource
|
import me.ash.reader.data.source.OpmlLocalDataSource
|
||||||
import me.ash.reader.data.source.ReaderDatabase
|
import me.ash.reader.data.source.ReaderDatabase
|
||||||
import me.ash.reader.data.source.RssNetworkDataSource
|
|
||||||
import me.ash.reader.ui.ext.*
|
import me.ash.reader.ui.ext.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -35,9 +34,6 @@ class App : Application(), Configuration.Provider {
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var opmlLocalDataSource: OpmlLocalDataSource
|
lateinit var opmlLocalDataSource: OpmlLocalDataSource
|
||||||
|
|
||||||
@Inject
|
|
||||||
lateinit var rssNetworkDataSource: RssNetworkDataSource
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var rssHelper: RssHelper
|
lateinit var rssHelper: RssHelper
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ import dagger.hilt.components.SingletonComponent
|
||||||
import me.ash.reader.data.source.AppNetworkDataSource
|
import me.ash.reader.data.source.AppNetworkDataSource
|
||||||
import me.ash.reader.data.source.FeverApiDataSource
|
import me.ash.reader.data.source.FeverApiDataSource
|
||||||
import me.ash.reader.data.source.GoogleReaderApiDataSource
|
import me.ash.reader.data.source.GoogleReaderApiDataSource
|
||||||
import me.ash.reader.data.source.RssNetworkDataSource
|
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
|
@ -19,11 +18,6 @@ object RetrofitModule {
|
||||||
fun provideAppNetworkDataSource(): AppNetworkDataSource =
|
fun provideAppNetworkDataSource(): AppNetworkDataSource =
|
||||||
AppNetworkDataSource.getInstance()
|
AppNetworkDataSource.getInstance()
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
fun provideRssNetworkDataSource(): RssNetworkDataSource =
|
|
||||||
RssNetworkDataSource.getInstance()
|
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
fun provideFeverApiDataSource(): FeverApiDataSource =
|
fun provideFeverApiDataSource(): FeverApiDataSource =
|
||||||
|
|
|
@ -15,7 +15,6 @@ import me.ash.reader.data.dao.ArticleDao
|
||||||
import me.ash.reader.data.dao.FeedDao
|
import me.ash.reader.data.dao.FeedDao
|
||||||
import me.ash.reader.data.dao.GroupDao
|
import me.ash.reader.data.dao.GroupDao
|
||||||
import me.ash.reader.data.entity.*
|
import me.ash.reader.data.entity.*
|
||||||
import me.ash.reader.data.source.RssNetworkDataSource
|
|
||||||
import me.ash.reader.ui.ext.currentAccountId
|
import me.ash.reader.ui.ext.currentAccountId
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
@ -26,7 +25,6 @@ abstract class AbstractRssRepository constructor(
|
||||||
private val articleDao: ArticleDao,
|
private val articleDao: ArticleDao,
|
||||||
private val groupDao: GroupDao,
|
private val groupDao: GroupDao,
|
||||||
private val feedDao: FeedDao,
|
private val feedDao: FeedDao,
|
||||||
private val rssNetworkDataSource: RssNetworkDataSource,
|
|
||||||
private val workManager: WorkManager,
|
private val workManager: WorkManager,
|
||||||
private val dispatcherIO: CoroutineDispatcher,
|
private val dispatcherIO: CoroutineDispatcher,
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -28,7 +28,6 @@ import me.ash.reader.data.entity.Group
|
||||||
import me.ash.reader.data.module.DispatcherDefault
|
import me.ash.reader.data.module.DispatcherDefault
|
||||||
import me.ash.reader.data.module.DispatcherIO
|
import me.ash.reader.data.module.DispatcherIO
|
||||||
import me.ash.reader.data.repository.SyncWorker.Companion.setIsSyncing
|
import me.ash.reader.data.repository.SyncWorker.Companion.setIsSyncing
|
||||||
import me.ash.reader.data.source.RssNetworkDataSource
|
|
||||||
import me.ash.reader.ui.ext.currentAccountId
|
import me.ash.reader.ui.ext.currentAccountId
|
||||||
import me.ash.reader.ui.ext.spacerDollar
|
import me.ash.reader.ui.ext.spacerDollar
|
||||||
import me.ash.reader.ui.page.common.ExtraName
|
import me.ash.reader.ui.page.common.ExtraName
|
||||||
|
@ -42,7 +41,6 @@ class LocalRssRepository @Inject constructor(
|
||||||
private val articleDao: ArticleDao,
|
private val articleDao: ArticleDao,
|
||||||
private val feedDao: FeedDao,
|
private val feedDao: FeedDao,
|
||||||
private val rssHelper: RssHelper,
|
private val rssHelper: RssHelper,
|
||||||
private val rssNetworkDataSource: RssNetworkDataSource,
|
|
||||||
private val accountDao: AccountDao,
|
private val accountDao: AccountDao,
|
||||||
private val groupDao: GroupDao,
|
private val groupDao: GroupDao,
|
||||||
@DispatcherDefault
|
@DispatcherDefault
|
||||||
|
@ -52,8 +50,7 @@ class LocalRssRepository @Inject constructor(
|
||||||
workManager: WorkManager,
|
workManager: WorkManager,
|
||||||
) : AbstractRssRepository(
|
) : AbstractRssRepository(
|
||||||
context, accountDao, articleDao, groupDao,
|
context, accountDao, articleDao, groupDao,
|
||||||
feedDao, rssNetworkDataSource, workManager,
|
feedDao, workManager, dispatcherIO
|
||||||
dispatcherIO
|
|
||||||
) {
|
) {
|
||||||
private val notificationManager: NotificationManagerCompat =
|
private val notificationManager: NotificationManagerCompat =
|
||||||
NotificationManagerCompat.from(context).apply {
|
NotificationManagerCompat.from(context).apply {
|
||||||
|
|
|
@ -3,6 +3,9 @@ package me.ash.reader.data.repository
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.text.Html
|
import android.text.Html
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import com.rometools.rome.feed.synd.SyndFeed
|
||||||
|
import com.rometools.rome.io.SyndFeedInput
|
||||||
|
import com.rometools.rome.io.XmlReader
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
@ -11,13 +14,13 @@ import me.ash.reader.data.entity.Article
|
||||||
import me.ash.reader.data.entity.Feed
|
import me.ash.reader.data.entity.Feed
|
||||||
import me.ash.reader.data.entity.FeedWithArticle
|
import me.ash.reader.data.entity.FeedWithArticle
|
||||||
import me.ash.reader.data.module.DispatcherIO
|
import me.ash.reader.data.module.DispatcherIO
|
||||||
import me.ash.reader.data.source.RssNetworkDataSource
|
|
||||||
import me.ash.reader.ui.ext.currentAccountId
|
import me.ash.reader.ui.ext.currentAccountId
|
||||||
import me.ash.reader.ui.ext.spacerDollar
|
import me.ash.reader.ui.ext.spacerDollar
|
||||||
import net.dankito.readability4j.Readability4J
|
import net.dankito.readability4j.Readability4J
|
||||||
import net.dankito.readability4j.extended.Readability4JExtended
|
import net.dankito.readability4j.extended.Readability4JExtended
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
|
import java.net.URL
|
||||||
import java.text.ParsePosition
|
import java.text.ParsePosition
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
@ -26,7 +29,6 @@ import javax.inject.Inject
|
||||||
class RssHelper @Inject constructor(
|
class RssHelper @Inject constructor(
|
||||||
@ApplicationContext
|
@ApplicationContext
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val rssNetworkDataSource: RssNetworkDataSource,
|
|
||||||
@DispatcherIO
|
@DispatcherIO
|
||||||
private val dispatcherIO: CoroutineDispatcher,
|
private val dispatcherIO: CoroutineDispatcher,
|
||||||
) {
|
) {
|
||||||
|
@ -34,7 +36,7 @@ class RssHelper @Inject constructor(
|
||||||
suspend fun searchFeed(feedLink: String): FeedWithArticle {
|
suspend fun searchFeed(feedLink: String): FeedWithArticle {
|
||||||
return withContext(dispatcherIO) {
|
return withContext(dispatcherIO) {
|
||||||
val accountId = context.currentAccountId
|
val accountId = context.currentAccountId
|
||||||
val parseRss = rssNetworkDataSource.parseRss(feedLink)
|
val parseRss: SyndFeed = SyndFeedInput().build(XmlReader(URL(feedLink)))
|
||||||
val feed = Feed(
|
val feed = Feed(
|
||||||
id = accountId.spacerDollar(UUID.randomUUID().toString()),
|
id = accountId.spacerDollar(UUID.randomUUID().toString()),
|
||||||
name = parseRss.title!!,
|
name = parseRss.title!!,
|
||||||
|
@ -83,28 +85,36 @@ class RssHelper @Inject constructor(
|
||||||
return withContext(dispatcherIO) {
|
return withContext(dispatcherIO) {
|
||||||
val a = mutableListOf<Article>()
|
val a = mutableListOf<Article>()
|
||||||
val accountId = context.currentAccountId
|
val accountId = context.currentAccountId
|
||||||
val parseRss = rssNetworkDataSource.parseRss(feed.url)
|
val parseRss: SyndFeed = SyndFeedInput().build(XmlReader(URL(feed.url)))
|
||||||
parseRss.items.forEach {
|
parseRss.entries.forEach {
|
||||||
if (latestLink != null && latestLink == it.link) return@withContext a
|
if (latestLink != null && latestLink == it.link) return@withContext a
|
||||||
Log.i("RLog", "request rss:\n${feed.name},${feed.url}\n${it.title}\n${it.link}\n")
|
val desc = it.description?.value
|
||||||
|
val content = it.contents
|
||||||
|
.takeIf { it.isNotEmpty() }
|
||||||
|
?.let { it.joinToString("\n") { it.value } }
|
||||||
|
Log.i(
|
||||||
|
"RLog",
|
||||||
|
"request rss:\n" +
|
||||||
|
"name: ${feed.name}\n" +
|
||||||
|
"url: ${feed.url}\n" +
|
||||||
|
"title: ${it.title}\n" +
|
||||||
|
"desc: ${desc}\n" +
|
||||||
|
"content: ${content}\n"
|
||||||
|
)
|
||||||
a.add(
|
a.add(
|
||||||
Article(
|
Article(
|
||||||
id = accountId.spacerDollar(UUID.randomUUID().toString()),
|
id = accountId.spacerDollar(UUID.randomUUID().toString()),
|
||||||
accountId = accountId,
|
accountId = accountId,
|
||||||
feedId = feed.id,
|
feedId = feed.id,
|
||||||
date = (it.publishDate ?: it.lastUpdated).toString().let {
|
date = it.publishedDate ?: it.updatedDate ?: Date(),
|
||||||
try {
|
|
||||||
Date(it)
|
|
||||||
} catch (e: IllegalArgumentException) {
|
|
||||||
parseDate(it) ?: Date()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
title = Html.fromHtml(it.title.toString()).toString(),
|
title = Html.fromHtml(it.title.toString()).toString(),
|
||||||
author = it.author?.name,
|
author = it.author,
|
||||||
rawDescription = it.description ?: it.summary ?: "",
|
rawDescription = (desc ?: content) ?: "",
|
||||||
shortDescription =
|
shortDescription = (Readability4JExtended("", desc ?: content ?: "")
|
||||||
(Readability4JExtended("", it.description ?: it.summary ?: "")
|
.parse().textContent ?: "")
|
||||||
.parse().textContent ?: "").take(100).trim(),
|
.take(100)
|
||||||
|
.trim(),
|
||||||
|
fullContent = content,
|
||||||
link = it.link ?: "",
|
link = it.link ?: "",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
package me.ash.reader.data.source
|
package me.ash.reader.data.source
|
||||||
|
|
||||||
import com.github.muhrifqii.parserss.ParseRSS
|
|
||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
import okhttp3.RequestBody.Companion.toRequestBody
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
import org.xmlpull.v1.XmlPullParserFactory
|
|
||||||
import retrofit2.Call
|
import retrofit2.Call
|
||||||
import retrofit2.Retrofit
|
import retrofit2.Retrofit
|
||||||
import retrofit2.converter.gson.GsonConverterFactory
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
|
@ -48,7 +46,6 @@ interface FeverApiDataSource {
|
||||||
|
|
||||||
fun getInstance(): FeverApiDataSource {
|
fun getInstance(): FeverApiDataSource {
|
||||||
return instance ?: synchronized(this) {
|
return instance ?: synchronized(this) {
|
||||||
ParseRSS.init(XmlPullParserFactory.newInstance())
|
|
||||||
instance ?: Retrofit.Builder()
|
instance ?: Retrofit.Builder()
|
||||||
.baseUrl("http://10.0.2.2/api/")
|
.baseUrl("http://10.0.2.2/api/")
|
||||||
.addConverterFactory(GsonConverterFactory.create())
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package me.ash.reader.data.source
|
package me.ash.reader.data.source
|
||||||
|
|
||||||
import com.github.muhrifqii.parserss.ParseRSS
|
|
||||||
import org.xmlpull.v1.XmlPullParserFactory
|
|
||||||
import retrofit2.Call
|
import retrofit2.Call
|
||||||
import retrofit2.Retrofit
|
import retrofit2.Retrofit
|
||||||
import retrofit2.converter.gson.GsonConverterFactory
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
|
@ -33,7 +31,6 @@ interface GoogleReaderApiDataSource {
|
||||||
|
|
||||||
fun getInstance(): GoogleReaderApiDataSource {
|
fun getInstance(): GoogleReaderApiDataSource {
|
||||||
return instance ?: synchronized(this) {
|
return instance ?: synchronized(this) {
|
||||||
ParseRSS.init(XmlPullParserFactory.newInstance())
|
|
||||||
instance ?: Retrofit.Builder()
|
instance ?: Retrofit.Builder()
|
||||||
.baseUrl("http://10.0.2.2/api/greader.php/")
|
.baseUrl("http://10.0.2.2/api/greader.php/")
|
||||||
.addConverterFactory(GsonConverterFactory.create())
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
package me.ash.reader.data.source
|
|
||||||
|
|
||||||
import com.github.muhrifqii.parserss.ParseRSS
|
|
||||||
import com.github.muhrifqii.parserss.RSSFeedObject
|
|
||||||
import com.github.muhrifqii.parserss.retrofit.ParseRSSConverterFactory
|
|
||||||
import org.xmlpull.v1.XmlPullParserFactory
|
|
||||||
import retrofit2.Retrofit
|
|
||||||
import retrofit2.http.GET
|
|
||||||
import retrofit2.http.Url
|
|
||||||
|
|
||||||
interface RssNetworkDataSource {
|
|
||||||
@GET
|
|
||||||
suspend fun parseRss(@Url url: String): RSSFeedObject
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private var instance: RssNetworkDataSource? = null
|
|
||||||
|
|
||||||
fun getInstance(): RssNetworkDataSource {
|
|
||||||
return instance ?: synchronized(this) {
|
|
||||||
ParseRSS.init(XmlPullParserFactory.newInstance())
|
|
||||||
instance ?: Retrofit.Builder()
|
|
||||||
.baseUrl("https://api.feeddd.org/feeds/")
|
|
||||||
.addConverterFactory(ParseRSSConverterFactory.create<RSSFeedObject>())
|
|
||||||
.build().create(RssNetworkDataSource::class.java).also {
|
|
||||||
instance = it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,10 +6,7 @@ import android.net.http.SslError
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.webkit.*
|
import android.webkit.*
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.toArgb
|
import androidx.compose.ui.graphics.toArgb
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
@ -122,11 +119,12 @@ fun WebView(
|
||||||
// }
|
// }
|
||||||
|
|
||||||
AndroidView(
|
AndroidView(
|
||||||
modifier = modifier,
|
modifier = modifier,//.padding(horizontal = if (content.contains("class=\"page\"")) 0.dp else 24.dp),
|
||||||
factory = { webView },
|
factory = { webView },
|
||||||
update = {
|
update = {
|
||||||
it.apply {
|
it.apply {
|
||||||
Log.i("RLog", "CustomWebView: ${content}")
|
Log.i("RLog", "CustomWebView: ${content}")
|
||||||
|
settings.javaScriptEnabled = true
|
||||||
loadDataWithBaseURL(
|
loadDataWithBaseURL(
|
||||||
null,
|
null,
|
||||||
getStyle(color) + content,
|
getStyle(color) + content,
|
||||||
|
@ -138,10 +136,12 @@ fun WebView(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Stable
|
||||||
fun argbToCssColor(argb: Int): String = String.format("#%06X", 0xFFFFFF and argb)
|
fun argbToCssColor(argb: Int): String = String.format("#%06X", 0xFFFFFF and argb)
|
||||||
|
|
||||||
|
@Stable
|
||||||
fun getStyle(argb: Int): String = """
|
fun getStyle(argb: Int): String = """
|
||||||
<head><style>
|
<html><head><style>
|
||||||
*{
|
*{
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
@ -154,14 +154,13 @@ fun getStyle(argb: Int): String = """
|
||||||
url('/android_asset_font/font/google_sans_text_bold.TTF');
|
url('/android_asset_font/font/google_sans_text_bold.TTF');
|
||||||
}
|
}
|
||||||
|
|
||||||
.page {
|
html {
|
||||||
padding: 0 24px;
|
padding: 0 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
img, video {
|
img, video, iframe {
|
||||||
margin: 0 -24px 20px;
|
margin: 0 -24px 20px;
|
||||||
width: calc(100% + 48px);
|
width: calc(100% + 48px);
|
||||||
height: auto;
|
|
||||||
border-top: 1px solid ${argbToCssColor(argb)}08;
|
border-top: 1px solid ${argbToCssColor(argb)}08;
|
||||||
border-bottom: 1px solid ${argbToCssColor(argb)}08;
|
border-bottom: 1px solid ${argbToCssColor(argb)}08;
|
||||||
}
|
}
|
||||||
|
@ -213,5 +212,5 @@ h1,h2,h3,h4,h5,h6,figure,br {
|
||||||
}
|
}
|
||||||
|
|
||||||
.element::-webkit-scrollbar { width: 0 !important }
|
.element::-webkit-scrollbar { width: 0 !important }
|
||||||
</style></head>
|
</style></head></html>
|
||||||
"""
|
"""
|
|
@ -190,7 +190,7 @@ fun FeedsPage(
|
||||||
item {
|
item {
|
||||||
Banner(
|
Banner(
|
||||||
title = filterState.filter.getName(),
|
title = filterState.filter.getName(),
|
||||||
desc = feedsViewState.importantCount,
|
desc = feedsViewState.importantCount.ifEmpty { stringResource(R.string.loading) },
|
||||||
icon = filterState.filter.iconOutline,
|
icon = filterState.filter.iconOutline,
|
||||||
action = {
|
action = {
|
||||||
Icon(
|
Icon(
|
||||||
|
|
|
@ -121,7 +121,7 @@ fun ArticleItem(
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
)
|
)
|
||||||
// Description
|
// Description
|
||||||
if (articleListDesc.value) {
|
if (articleListDesc.value && articleWithFeed.article.shortDescription.isNotBlank()) {
|
||||||
Text(
|
Text(
|
||||||
text = articleWithFeed.article.shortDescription,
|
text = articleWithFeed.article.shortDescription,
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.7f),
|
color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.7f),
|
||||||
|
|
|
@ -273,6 +273,7 @@ fun FlowPage(
|
||||||
if (pagingItems.loadState.source.refresh is LoadState.NotLoading && pagingItems.itemCount != 0) {
|
if (pagingItems.loadState.source.refresh is LoadState.NotLoading && pagingItems.itemCount != 0) {
|
||||||
Spacer(modifier = Modifier.height(64.dp))
|
Spacer(modifier = Modifier.height(64.dp))
|
||||||
}
|
}
|
||||||
|
Spacer(modifier = Modifier.windowInsetsBottomHeight(WindowInsets.navigationBars))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,11 +46,13 @@ fun Header(
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
articleWithFeed.article.author?.let {
|
articleWithFeed.article.author?.let {
|
||||||
Text(
|
if (it.isNotEmpty()) {
|
||||||
text = articleWithFeed.article.author,
|
Text(
|
||||||
color = MaterialTheme.colorScheme.outline.copy(alpha = 0.7f),
|
text = it,
|
||||||
style = MaterialTheme.typography.labelMedium,
|
color = MaterialTheme.colorScheme.outline.copy(alpha = 0.7f),
|
||||||
)
|
style = MaterialTheme.typography.labelMedium,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Text(
|
Text(
|
||||||
text = articleWithFeed.feed.name,
|
text = articleWithFeed.feed.name,
|
||||||
|
|
|
@ -54,10 +54,8 @@ class ReadViewModel @Inject constructor(
|
||||||
private fun renderDescriptionContent() {
|
private fun renderDescriptionContent() {
|
||||||
_viewState.update {
|
_viewState.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
content = rssHelper.parseDescriptionContent(
|
content = it.articleWithFeed?.article?.fullContent
|
||||||
link = it.articleWithFeed?.article?.link ?: "",
|
?: it.articleWithFeed?.article?.rawDescription ?: "",
|
||||||
content = it.articleWithFeed?.article?.rawDescription ?: "",
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
<string name="starred_desc">%1$d 项已加星标</string>
|
<string name="starred_desc">%1$d 项已加星标</string>
|
||||||
<string name="feeds">分组</string>
|
<string name="feeds">分组</string>
|
||||||
<string name="syncing">正在同步…</string>
|
<string name="syncing">正在同步…</string>
|
||||||
|
<string name="loading">加载中…</string>
|
||||||
<string name="expand_less">收缩</string>
|
<string name="expand_less">收缩</string>
|
||||||
<string name="expand_more">展开</string>
|
<string name="expand_more">展开</string>
|
||||||
<string name="confirm">确认</string>
|
<string name="confirm">确认</string>
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
<string name="starred_desc">%1$d Starred Items</string>
|
<string name="starred_desc">%1$d Starred Items</string>
|
||||||
<string name="feeds">Feeds</string>
|
<string name="feeds">Feeds</string>
|
||||||
<string name="syncing">Syncing…</string>
|
<string name="syncing">Syncing…</string>
|
||||||
|
<string name="loading">Loading…</string>
|
||||||
<string name="expand_less">Expand Less</string>
|
<string name="expand_less">Expand Less</string>
|
||||||
<string name="expand_more">Expand More</string>
|
<string name="expand_more">Expand More</string>
|
||||||
<string name="confirm">Confirm</string>
|
<string name="confirm">Confirm</string>
|
||||||
|
|
|
@ -12,7 +12,7 @@ buildscript {
|
||||||
profileinstaller = '1.2.0-alpha02'
|
profileinstaller = '1.2.0-alpha02'
|
||||||
retrofit2 = '2.9.0'
|
retrofit2 = '2.9.0'
|
||||||
coil = '2.0.0-rc03'
|
coil = '2.0.0-rc03'
|
||||||
parseRSS = '0.6.0'
|
rome = '1.18.0'
|
||||||
readability4j = '1.0.8'
|
readability4j = '1.0.8'
|
||||||
opmlParser = '2.2.0'
|
opmlParser = '2.2.0'
|
||||||
androidSVG = '1.4'
|
androidSVG = '1.4'
|
||||||
|
|
Loading…
Reference in New Issue
Block a user