mirror of https://github.com/Ashinch/ReadYou.git
Merge notifications by feeds
This commit is contained in:
parent
ee5e6e3687
commit
72b07a7e0a
|
@ -562,7 +562,7 @@ interface ArticleDao {
|
|||
}
|
||||
|
||||
@Transaction
|
||||
suspend fun insertIfNotExist(articles: List<Article>): List<Article?> {
|
||||
return articles.map { if (insertIfNotExist(it) > 0) it else null }
|
||||
suspend fun insertIfNotExist(articles: List<Article>): List<Article> {
|
||||
return articles.mapNotNull { if (insertIfNotExist(it) > 0) it else null }
|
||||
}
|
||||
}
|
|
@ -1,14 +1,12 @@
|
|||
package me.ash.reader.data.repository
|
||||
|
||||
import android.app.Notification
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.app.*
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.BitmapFactory
|
||||
import android.util.Log
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.content.ContextCompat.getSystemService
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.work.CoroutineWorker
|
||||
import androidx.work.ListenableWorker
|
||||
import androidx.work.WorkManager
|
||||
|
@ -25,6 +23,7 @@ import me.ash.reader.data.dao.FeedDao
|
|||
import me.ash.reader.data.dao.GroupDao
|
||||
import me.ash.reader.data.entity.Article
|
||||
import me.ash.reader.data.entity.Feed
|
||||
import me.ash.reader.data.entity.FeedWithArticle
|
||||
import me.ash.reader.data.entity.Group
|
||||
import me.ash.reader.data.module.DispatcherDefault
|
||||
import me.ash.reader.data.module.DispatcherIO
|
||||
|
@ -56,12 +55,9 @@ class LocalRssRepository @Inject constructor(
|
|||
feedDao, rssNetworkDataSource, workManager,
|
||||
dispatcherIO
|
||||
) {
|
||||
private val notificationManager: NotificationManager =
|
||||
(getSystemService(
|
||||
context,
|
||||
NotificationManager::class.java
|
||||
) as NotificationManager).also {
|
||||
it.createNotificationChannel(
|
||||
private val notificationManager: NotificationManagerCompat =
|
||||
NotificationManagerCompat.from(context).apply {
|
||||
createNotificationChannel(
|
||||
NotificationChannel(
|
||||
NotificationGroupName.ARTICLE_UPDATE,
|
||||
NotificationGroupName.ARTICLE_UPDATE,
|
||||
|
@ -105,9 +101,14 @@ class LocalRssRepository @Inject constructor(
|
|||
.awaitAll()
|
||||
.forEach {
|
||||
if (it.isNotify) {
|
||||
notify(articleDao.insertIfNotExist(it.articles))
|
||||
notify(
|
||||
FeedWithArticle(
|
||||
it.feedWithArticle.feed,
|
||||
articleDao.insertIfNotExist(it.feedWithArticle.articles)
|
||||
)
|
||||
)
|
||||
} else {
|
||||
articleDao.insertIfNotExist(it.articles)
|
||||
articleDao.insertIfNotExist(it.feedWithArticle.articles)
|
||||
}
|
||||
}
|
||||
Log.i("RlOG", "onCompletion: ${System.currentTimeMillis() - preTime}")
|
||||
|
@ -158,7 +159,7 @@ class LocalRssRepository @Inject constructor(
|
|||
}
|
||||
|
||||
data class ArticleNotify(
|
||||
val articles: List<Article>,
|
||||
val feedWithArticle: FeedWithArticle,
|
||||
val isNotify: Boolean,
|
||||
)
|
||||
|
||||
|
@ -170,7 +171,7 @@ class LocalRssRepository @Inject constructor(
|
|||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
Log.e("RLog", "queryRssXml[${feed.name}]: ${e.message}")
|
||||
return ArticleNotify(listOf(), false)
|
||||
return ArticleNotify(FeedWithArticle(feed, listOf()), false)
|
||||
}
|
||||
try {
|
||||
// if (feed.icon == null && !articles.isNullOrEmpty()) {
|
||||
|
@ -178,32 +179,33 @@ class LocalRssRepository @Inject constructor(
|
|||
// }
|
||||
} catch (e: Exception) {
|
||||
Log.e("RLog", "queryRssIcon[${feed.name}]: ${e.message}")
|
||||
return ArticleNotify(listOf(), false)
|
||||
return ArticleNotify(FeedWithArticle(feed, listOf()), false)
|
||||
}
|
||||
return ArticleNotify(
|
||||
articles = articles,
|
||||
feedWithArticle = FeedWithArticle(feed, articles),
|
||||
isNotify = articles.isNotEmpty() && feed.isNotification
|
||||
)
|
||||
}
|
||||
|
||||
private fun notify(
|
||||
articles: List<Article?>,
|
||||
feedWithArticle: FeedWithArticle,
|
||||
) {
|
||||
articles.filterNotNull().forEach { article ->
|
||||
val builder = NotificationCompat.Builder(
|
||||
context,
|
||||
NotificationGroupName.ARTICLE_UPDATE
|
||||
).setSmallIcon(R.drawable.ic_notification)
|
||||
// .setLargeIcon(
|
||||
// BitmapFactory.decodeResource(
|
||||
// context.resources,
|
||||
// R.mipmap.ic_launcher_round,
|
||||
// )
|
||||
// )
|
||||
.setGroup(NotificationGroupName.ARTICLE_UPDATE)
|
||||
notificationManager.createNotificationChannelGroup(
|
||||
NotificationChannelGroup(
|
||||
feedWithArticle.feed.id,
|
||||
feedWithArticle.feed.name
|
||||
)
|
||||
)
|
||||
feedWithArticle.articles.forEach { article ->
|
||||
val builder = NotificationCompat.Builder(context, NotificationGroupName.ARTICLE_UPDATE)
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setLargeIcon(
|
||||
(BitmapFactory.decodeResource(
|
||||
context.resources,
|
||||
R.drawable.ic_notification
|
||||
))
|
||||
)
|
||||
.setContentTitle(article.title)
|
||||
.setContentText(article.shortDescription)
|
||||
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
||||
.setContentIntent(
|
||||
PendingIntent.getActivity(
|
||||
context,
|
||||
|
@ -219,6 +221,13 @@ class LocalRssRepository @Inject constructor(
|
|||
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
)
|
||||
.setGroup(feedWithArticle.feed.id)
|
||||
.setStyle(
|
||||
NotificationCompat.BigTextStyle()
|
||||
.bigText(article.shortDescription)
|
||||
.setSummaryText(feedWithArticle.feed.name)
|
||||
)
|
||||
|
||||
notificationManager.notify(
|
||||
Random().nextInt() + article.id.hashCode(),
|
||||
builder.build().apply {
|
||||
|
@ -226,5 +235,26 @@ class LocalRssRepository @Inject constructor(
|
|||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (feedWithArticle.articles.size > 1) {
|
||||
notificationManager.notify(
|
||||
Random().nextInt() + feedWithArticle.feed.id.hashCode(),
|
||||
NotificationCompat.Builder(context, NotificationGroupName.ARTICLE_UPDATE)
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setLargeIcon(
|
||||
(BitmapFactory.decodeResource(
|
||||
context.resources,
|
||||
R.drawable.ic_notification
|
||||
))
|
||||
)
|
||||
.setStyle(
|
||||
NotificationCompat.InboxStyle()
|
||||
.setSummaryText(feedWithArticle.feed.name)
|
||||
)
|
||||
.setGroup(feedWithArticle.feed.id)
|
||||
.setGroupSummary(true)
|
||||
.build()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -163,7 +163,7 @@ class RssHelper @Inject constructor(
|
|||
}
|
||||
|
||||
private fun parseDate(
|
||||
inputDate: String, patterns: Array<String?> = arrayOf(
|
||||
inputDate: String, patterns: Array<String> = arrayOf(
|
||||
"yyyy-MM-dd'T'HH:mm:ss'Z'",
|
||||
"yyyy-MM-dd",
|
||||
"yyyy-MM-dd HH:mm:ss",
|
||||
|
@ -174,7 +174,6 @@ class RssHelper @Inject constructor(
|
|||
)
|
||||
): Date? {
|
||||
val df = SimpleDateFormat()
|
||||
df.timeZone = TimeZone.getDefault()
|
||||
for (pattern in patterns) {
|
||||
df.applyPattern(pattern)
|
||||
df.isLenient = false
|
||||
|
|
|
@ -10,8 +10,6 @@ package me.ash.reader.ui.component
|
|||
|
||||
import android.view.SoundEffectConstants
|
||||
import androidx.compose.animation.Crossfade
|
||||
import androidx.compose.animation.animateContentSize
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
|
@ -86,7 +84,7 @@ fun Banner(
|
|||
)
|
||||
desc?.let {
|
||||
Text(
|
||||
modifier = Modifier.animateContentSize(tween()),
|
||||
// modifier = Modifier.animateContentSize(tween()),
|
||||
text = it,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = (MaterialTheme.colorScheme.onSurface alwaysLight true).copy(alpha = 0.7f),
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package me.ash.reader.ui.component
|
||||
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
|
@ -32,8 +31,8 @@ fun DisplayText(
|
|||
) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.height(44.dp)
|
||||
.animateContentSize(tween()),
|
||||
.height(44.dp),
|
||||
// .animateContentSize(tween()),
|
||||
text = text,
|
||||
style = MaterialTheme.typography.displaySmall.copy(
|
||||
baselineShift = BaselineShift.Superscript
|
||||
|
|
|
@ -78,7 +78,7 @@ fun HomeEntry(
|
|||
FlowPage(
|
||||
navController = navController,
|
||||
homeViewModel = homeViewModel,
|
||||
pagingItems = pagingItems
|
||||
pagingItems = pagingItems,
|
||||
)
|
||||
}
|
||||
animatedComposable(route = "${RouteName.READING}/{articleId}") {
|
||||
|
|
|
@ -166,7 +166,7 @@ fun FeedsPage(
|
|||
}
|
||||
)
|
||||
},
|
||||
text = feedsViewState.account?.name ?: "",
|
||||
text = feedsViewState.account?.name ?: stringResource(R.string.read_you),
|
||||
desc = if (isSyncing) stringResource(R.string.syncing) else "",
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package me.ash.reader.ui.page.home.flow
|
||||
|
||||
import android.util.Log
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
|
@ -89,7 +88,6 @@ fun FlowPage(
|
|||
|
||||
LaunchedEffect(viewState.listState) {
|
||||
snapshotFlow { viewState.listState.firstVisibleItemIndex }.collect {
|
||||
Log.i("RLog", "FlowPage: ${it}")
|
||||
if (it > 0) {
|
||||
keyboardController?.hide()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue