Add click notification feature

This commit is contained in:
Ash 2022-03-04 00:14:36 +08:00
parent bfe1307b27
commit ee9e0a4553
19 changed files with 274 additions and 103 deletions

View File

@ -1,6 +1,10 @@
package me.ash.reader
import android.app.Application
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.material3.ExperimentalMaterial3Api
import com.google.accompanist.pager.ExperimentalPagerApi
import dagger.hilt.android.HiltAndroidApp
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
@ -14,6 +18,10 @@ import me.ash.reader.data.source.ReaderDatabase
import me.ash.reader.data.source.RssNetworkDataSource
import javax.inject.Inject
@ExperimentalAnimationApi
@ExperimentalMaterial3Api
@ExperimentalPagerApi
@ExperimentalFoundationApi
@DelicateCoroutinesApi
@HiltAndroidApp
class App : Application() {

View File

@ -271,6 +271,15 @@ interface ArticleDao {
)
suspend fun queryLatestByFeedId(accountId: Int, feedId: Int): Article?
@Transaction
@Query(
"""
SELECT * FROM article
WHERE id = :id
"""
)
suspend fun queryById(id: Int): ArticleWithFeed?
@Insert
suspend fun insert(article: Article): Long

View File

@ -1,4 +1,4 @@
package me.ash.reader.ui.data
package me.ash.reader.data.constant
class Filter(
var index: Int,

View File

@ -1,7 +1,9 @@
package me.ash.reader.ui.data
package me.ash.reader.data.constant
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.*
import androidx.compose.material.icons.rounded.FiberManualRecord
import androidx.compose.material.icons.rounded.Star
import androidx.compose.material.icons.rounded.Subject
import androidx.compose.ui.graphics.vector.ImageVector
class NavigationBarItem(

View File

@ -0,0 +1,7 @@
package me.ash.reader.data.constant
object Symbol {
const val NOTHING: String = "null"
const val NOTIFICATION_CHANNEL_GROUP_ARTICLE_UPDATE: String = "article.update"
const val EXTRA_ARTICLE_ID: String = "article.id"
}

View File

@ -86,4 +86,8 @@ class ArticleRepository @Inject constructor(
suspend fun updateArticleInfo(article: Article) {
articleDao.update(article)
}
suspend fun findArticleById(id: Int): ArticleWithFeed? {
return articleDao.queryById(id)
}
}

View File

@ -3,29 +3,34 @@ package me.ash.reader.data.repository
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import android.util.Log
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat.getSystemService
import androidx.work.*
import com.github.muhrifqii.parserss.ParseRSS
import com.google.accompanist.pager.ExperimentalPagerApi
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import me.ash.reader.DataStoreKeys
import me.ash.reader.*
import me.ash.reader.R
import me.ash.reader.data.account.AccountDao
import me.ash.reader.data.article.Article
import me.ash.reader.data.article.ArticleDao
import me.ash.reader.data.constant.Symbol
import me.ash.reader.data.feed.Feed
import me.ash.reader.data.feed.FeedDao
import me.ash.reader.data.source.ReaderDatabase
import me.ash.reader.data.source.RssNetworkDataSource
import me.ash.reader.dataStore
import me.ash.reader.get
import net.dankito.readability4j.Readability4J
import net.dankito.readability4j.extended.Readability4JExtended
import okhttp3.*
@ -34,7 +39,6 @@ import java.io.IOException
import java.util.*
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import kotlin.random.Random
class RssRepository @Inject constructor(
@ -83,6 +87,10 @@ class RssRepository @Inject constructor(
return workManager.getWorkInfosByTag("sync").get().size.toString()
}
@ExperimentalAnimationApi
@ExperimentalMaterial3Api
@ExperimentalPagerApi
@ExperimentalFoundationApi
suspend fun sync(isWork: Boolean? = false) {
if (isWork == true) {
workManager.cancelAllWork()
@ -92,7 +100,6 @@ class RssRepository @Inject constructor(
).setConstraints(
Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.setRequiresCharging(true)
.build()
).addTag("sync").build()
workManager.enqueue(syncWorkerRequest)
@ -101,6 +108,10 @@ class RssRepository @Inject constructor(
}
}
@ExperimentalAnimationApi
@ExperimentalMaterial3Api
@ExperimentalPagerApi
@ExperimentalFoundationApi
@DelicateCoroutinesApi
companion object {
data class SyncState(
@ -194,26 +205,38 @@ class RssRepository @Inject constructor(
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
notificationManager.createNotificationChannel(
NotificationChannel(
"ARTICLE_UPDATE",
Symbol.NOTIFICATION_CHANNEL_GROUP_ARTICLE_UPDATE,
"文章更新",
NotificationManager.IMPORTANCE_DEFAULT
)
)
}
it.reversed().forEachIndexed { index, articleList ->
articleList.forEach { article ->
Log.i("RlOG", "combine $index ${article.feedId}: ${article.title}")
val builder = NotificationCompat.Builder(context, "ARTICLE_UPDATE")
it.reversed().forEach { articleList ->
val ids = articleDao.insertList(articleList)
articleList.forEachIndexed { index, article ->
Log.i("RlOG", "combine ${article.feedId}: ${article.title}")
val builder = NotificationCompat.Builder(context, Symbol.NOTIFICATION_CHANNEL_GROUP_ARTICLE_UPDATE)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setGroup("ARTICLE_UPDATE")
.setGroup(Symbol.NOTIFICATION_CHANNEL_GROUP_ARTICLE_UPDATE)
.setContentTitle(article.title)
.setContentText(article.shortDescription)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
notificationManager.notify(Random.nextInt(), builder.build().apply {
.setContentIntent(
PendingIntent.getActivity(
context,
ids[index].toInt(),
Intent(context, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or
Intent.FLAG_ACTIVITY_CLEAR_TASK
putExtra(Symbol.EXTRA_ARTICLE_ID, ids[index].toInt())
},
PendingIntent.FLAG_UPDATE_CURRENT
)
)
notificationManager.notify(ids[index].toInt(), builder.build().apply {
flags = Notification.FLAG_AUTO_CANCEL
})
}
articleDao.insertList(articleList)
}
}.buffer().onCompletion {
val afterTime = System.currentTimeMillis()
@ -323,6 +346,10 @@ class RssRepository @Inject constructor(
}
}
@ExperimentalAnimationApi
@ExperimentalMaterial3Api
@ExperimentalPagerApi
@ExperimentalFoundationApi
@DelicateCoroutinesApi
class SyncWorker(
context: Context,

View File

@ -12,12 +12,16 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import com.google.accompanist.insets.ProvideWindowInsets
import com.google.accompanist.insets.navigationBarsHeight
import com.google.accompanist.insets.statusBarsPadding
import com.google.accompanist.pager.ExperimentalPagerApi
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import me.ash.reader.ui.page.home.HomePage
import me.ash.reader.ui.page.settings.SettingsPage
import me.ash.reader.ui.theme.AppTheme
@ExperimentalAnimationApi
@ -26,6 +30,8 @@ import me.ash.reader.ui.theme.AppTheme
@ExperimentalFoundationApi
@Composable
fun HomeEntry() {
val navController = rememberNavController()
AppTheme {
ProvideWindowInsets {
rememberSystemUiController().run {
@ -33,13 +39,24 @@ fun HomeEntry() {
setSystemBarsColor(MaterialTheme.colorScheme.surface, !isSystemInDarkTheme())
setNavigationBarColor(MaterialTheme.colorScheme.surface, !isSystemInDarkTheme())
}
Column (modifier = Modifier.background(MaterialTheme.colorScheme.surface)){
Column(modifier = Modifier.background(MaterialTheme.colorScheme.surface)) {
Row(
modifier = Modifier
.weight(1f)
.statusBarsPadding()
) {
HomePage()
NavHost(
modifier = Modifier.background(MaterialTheme.colorScheme.surface),
navController = navController,
startDestination = RouteName.HOME,
) {
composable(route = RouteName.HOME) {
HomePage(navController)
}
composable(route = RouteName.SETTINGS) {
SettingsPage(navController)
}
}
}
Spacer(
modifier = Modifier

View File

@ -1,7 +1,9 @@
package me.ash.reader.ui.page.common
object RouteName {
const val HOME = "home"
const val FEED = "feed"
const val ARTICLE = "article"
const val READ = "read"
const val SETTINGS = "settings"
}

View File

@ -4,28 +4,31 @@ import android.util.Log
import androidx.activity.compose.BackHandler
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.compose.rememberNavController
import androidx.navigation.NavHostController
import com.google.accompanist.pager.ExperimentalPagerApi
import com.google.accompanist.pager.HorizontalPager
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import me.ash.reader.data.constant.Symbol
import me.ash.reader.ui.page.home.article.ArticlePage
import me.ash.reader.ui.page.home.feed.FeedPage
import me.ash.reader.ui.page.home.read.ReadPage
import me.ash.reader.ui.page.home.read.ReadViewAction
import me.ash.reader.ui.page.home.read.ReadViewModel
import me.ash.reader.ui.util.collectAsStateValue
import me.ash.reader.ui.util.findActivity
import me.ash.reader.ui.util.pagerAnimate
import me.ash.reader.ui.widget.AppNavigationBar
@ -35,15 +38,44 @@ import me.ash.reader.ui.widget.AppNavigationBar
@ExperimentalFoundationApi
@Composable
fun HomePage(
navController: NavHostController,
viewModel: HomeViewModel = hiltViewModel(),
readViewModel: ReadViewModel = hiltViewModel(),
) {
val context = LocalContext.current
val viewState = viewModel.viewState.collectAsStateValue()
val filterState = viewModel.filterState.collectAsStateValue()
val readState = readViewModel.viewState.collectAsStateValue()
val navController = rememberNavController()
val scope = rememberCoroutineScope()
DisposableEffect(Unit) {
context.findActivity()?.let { activity ->
activity.intent?.let { intent ->
intent.extras?.get(Symbol.EXTRA_ARTICLE_ID)?.let {
readViewModel.dispatch(ReadViewAction.ScrollToItem(2))
scope.launch {
val article =
readViewModel.articleRepository.findArticleById(it.toString().toInt())
?: return@launch
readViewModel.dispatch(ReadViewAction.InitData(article))
if (article.feed.isFullContent) readViewModel.dispatch(ReadViewAction.RenderFullContent)
else readViewModel.dispatch(ReadViewAction.RenderDescriptionContent)
readViewModel.dispatch(ReadViewAction.RenderDescriptionContent)
viewModel.dispatch(
HomeViewAction.ScrollToPage(
scope = scope,
targetPage = 2,
)
)
}
}
intent.extras?.clear()
}
}
onDispose { }
}
BackHandler(true) {
val currentPage = viewState.pagerState.currentPage
viewModel.dispatch(
@ -115,12 +147,11 @@ fun HomePage(
HorizontalPager(
count = 3,
state = viewState.pagerState,
modifier = Modifier
.weight(1f)
.background(MaterialTheme.colorScheme.surface),
modifier = Modifier.weight(1f)
) { page ->
when (page) {
0 -> FeedPage(
navController = navController,
modifier = Modifier.pagerAnimate(this, page),
filter = filterState.filter,
groupAndFeedOnClick = { currentGroup, currentFeed ->
@ -141,6 +172,7 @@ fun HomePage(
},
)
1 -> ArticlePage(
navController = navController,
modifier = Modifier.pagerAnimate(this, page),
BackOnClick = {
viewModel.dispatch(
@ -165,6 +197,7 @@ fun HomePage(
},
)
2 -> ReadPage(
navController = navController,
modifier = Modifier.pagerAnimate(this, page),
btnBackOnClickListener = {
viewModel.dispatch(

View File

@ -1,5 +1,8 @@
package me.ash.reader.ui.page.home
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.google.accompanist.pager.ExperimentalPagerApi
@ -15,10 +18,13 @@ import kotlinx.coroutines.launch
import me.ash.reader.data.feed.Feed
import me.ash.reader.data.group.Group
import me.ash.reader.data.repository.RssRepository
import me.ash.reader.ui.data.Filter
import me.ash.reader.data.constant.Filter
import javax.inject.Inject
@ExperimentalAnimationApi
@ExperimentalMaterial3Api
@ExperimentalPagerApi
@ExperimentalFoundationApi
@HiltViewModel
class HomeViewModel @Inject constructor(
private val rssRepository: RssRepository,

View File

@ -30,6 +30,7 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import androidx.paging.compose.collectAsLazyPagingItems
import com.google.accompanist.pager.ExperimentalPagerApi
import com.google.accompanist.swiperefresh.SwipeRefresh
@ -40,8 +41,8 @@ import me.ash.reader.DateTimeExt
import me.ash.reader.DateTimeExt.toString
import me.ash.reader.R
import me.ash.reader.data.article.ArticleWithFeed
import me.ash.reader.data.constant.Filter
import me.ash.reader.data.repository.RssRepository
import me.ash.reader.ui.data.Filter
import me.ash.reader.ui.page.home.HomeViewAction
import me.ash.reader.ui.page.home.HomeViewModel
import me.ash.reader.ui.util.collectAsStateValue
@ -57,6 +58,7 @@ import me.ash.reader.ui.widget.TopTitleBox
@ExperimentalFoundationApi
@Composable
fun ArticlePage(
navController: NavHostController,
modifier: Modifier,
homeViewModel: HomeViewModel = hiltViewModel(),
viewModel: ArticleViewModel = hiltViewModel(),
@ -92,7 +94,7 @@ fun ArticlePage(
homeViewModel.dispatch(HomeViewAction.Sync())
}
) {
Box(modifier.background(MaterialTheme.colorScheme.surface)) {
Box {
TopTitleBox(
title = when {
filterState.group != null -> filterState.group.name
@ -241,65 +243,67 @@ private fun ArticleItem(
)
}
Spacer(modifier = modifier.height(1.dp))
if (true) {
Box(
modifier = Modifier
.padding(top = 3.dp)
.size(24.dp)
.border(
2.dp,
MaterialTheme.colorScheme.inverseOnSurface,
RoundedCornerShape(4.dp)
),
) {
if (articleWithFeed.feed.icon == null) {
Icon(
painter = painterResource(id = R.drawable.default_folder),
contentDescription = "icon",
modifier = modifier
.fillMaxSize()
.padding(2.dp),
tint = MaterialTheme.colorScheme.onPrimaryContainer,
)
} else {
Image(
painter = BitmapPainter(
BitmapFactory.decodeByteArray(
articleWithFeed.feed.icon,
0,
articleWithFeed.feed.icon!!.size
).asImageBitmap()
Row {
if (true) {
Box(
modifier = Modifier
.padding(top = 3.dp)
.size(24.dp)
.border(
2.dp,
MaterialTheme.colorScheme.inverseOnSurface,
RoundedCornerShape(4.dp)
),
contentDescription = "icon",
modifier = modifier
.fillMaxSize()
.padding(2.dp),
)
) {
if (articleWithFeed.feed.icon == null) {
Icon(
painter = painterResource(id = R.drawable.default_folder),
contentDescription = "icon",
modifier = modifier
.fillMaxSize()
.padding(2.dp),
tint = MaterialTheme.colorScheme.onPrimaryContainer,
)
} else {
Image(
painter = BitmapPainter(
BitmapFactory.decodeByteArray(
articleWithFeed.feed.icon,
0,
articleWithFeed.feed.icon!!.size
).asImageBitmap()
),
contentDescription = "icon",
modifier = modifier
.fillMaxSize()
.padding(2.dp),
)
}
}
Spacer(modifier = Modifier.width(8.dp))
}
Column {
Text(
text = articleWithFeed.article.title,
fontSize = 18.sp,
fontWeight = FontWeight.Bold,
color = if (isStarredFilter || articleWithFeed.article.isUnread) {
MaterialTheme.colorScheme.onPrimaryContainer
} else {
MaterialTheme.colorScheme.outline
},
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = modifier.height(1.dp))
Text(
text = articleWithFeed.article.shortDescription,
fontSize = 18.sp,
color = MaterialTheme.colorScheme.outline,
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
}
Spacer(modifier = Modifier.width(8.dp))
}
Column {
Text(
text = articleWithFeed.article.title,
fontSize = 18.sp,
fontWeight = FontWeight.Bold,
color = if (isStarredFilter || articleWithFeed.article.isUnread) {
MaterialTheme.colorScheme.onPrimaryContainer
} else {
MaterialTheme.colorScheme.outline
},
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = modifier.height(1.dp))
Text(
text = articleWithFeed.article.shortDescription,
fontSize = 18.sp,
color = MaterialTheme.colorScheme.outline,
maxLines = 2,
overflow = TextOverflow.Ellipsis
)
}
}
}

View File

@ -6,7 +6,6 @@ import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.animation.*
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
@ -26,15 +25,17 @@ import androidx.compose.ui.graphics.painter.BitmapPainter
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.google.accompanist.pager.ExperimentalPagerApi
import kotlinx.coroutines.flow.collect
import me.ash.reader.DateTimeExt
import me.ash.reader.DateTimeExt.toString
import me.ash.reader.data.constant.Filter
import me.ash.reader.data.feed.Feed
import me.ash.reader.data.group.Group
import me.ash.reader.data.group.GroupWithFeed
import me.ash.reader.data.repository.RssRepository
import me.ash.reader.ui.data.Filter
import me.ash.reader.ui.page.common.RouteName
import me.ash.reader.ui.page.home.HomeViewAction
import me.ash.reader.ui.page.home.HomeViewModel
import me.ash.reader.ui.util.collectAsStateValue
@ -47,6 +48,7 @@ import me.ash.reader.ui.widget.*
@ExperimentalFoundationApi
@Composable
fun FeedPage(
navController: NavHostController,
modifier: Modifier,
viewModel: FeedViewModel = hiltViewModel(),
homeViewModel: HomeViewModel = hiltViewModel(),
@ -84,9 +86,7 @@ fun FeedPage(
}
Box(
modifier
.fillMaxSize()
.background(MaterialTheme.colorScheme.surface)
modifier.fillMaxSize()
) {
TopTitleBox(
title = viewState.account?.name ?: "未知账户",
@ -109,7 +109,7 @@ fun FeedPage(
title = {},
navigationIcon = {
IconButton(onClick = {
navController.navigate(route = RouteName.SETTINGS)
}) {
Icon(
modifier = Modifier.size(22.dp),

View File

@ -5,7 +5,6 @@ import android.content.Intent
import android.net.Uri
import androidx.compose.animation.*
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.text.selection.SelectionContainer
@ -24,6 +23,7 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.airbnb.lottie.compose.LottieAnimation
import com.airbnb.lottie.compose.LottieCompositionSpec
import com.airbnb.lottie.compose.rememberLottieComposition
@ -44,6 +44,7 @@ import me.ash.reader.ui.widget.WebView
@ExperimentalFoundationApi
@Composable
fun ReadPage(
navController: NavHostController,
modifier: Modifier = Modifier,
viewModel: ReadViewModel = hiltViewModel(),
btnBackOnClickListener: () -> Unit,
@ -66,9 +67,7 @@ fun ReadPage(
Box {
Column(
modifier
.fillMaxSize()
.background(MaterialTheme.colorScheme.surface)
modifier.fillMaxSize()
) {
SmallTopAppBar(

View File

@ -16,7 +16,7 @@ import javax.inject.Inject
@HiltViewModel
class ReadViewModel @Inject constructor(
private val articleRepository: ArticleRepository,
val articleRepository: ArticleRepository,
private val rssRepository: RssRepository,
) : ViewModel() {
private val _viewState = MutableStateFlow(ReadViewState())

View File

@ -0,0 +1,49 @@
package me.ash.reader.ui.page.settings
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.navigation.NavHostController
import com.google.accompanist.pager.ExperimentalPagerApi
@ExperimentalAnimationApi
@ExperimentalMaterial3Api
@ExperimentalPagerApi
@ExperimentalFoundationApi
@Composable
fun SettingsPage(
navController: NavHostController,
) {
Scaffold(
topBar = {
LargeTopAppBar(
title = {
Text(
text = "Settings",
color = MaterialTheme.colorScheme.primary,
)
},
navigationIcon = {
IconButton(onClick = {
navController.popBackStack()
}) {
IconButton(onClick = { /*TODO*/ }) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = "Back",
tint = MaterialTheme.colorScheme.primary
)
}
}
},
)
},
content = {
Text(text = "af")
},
)
}

View File

@ -1,5 +1,8 @@
package me.ash.reader.ui.util
import android.app.Activity
import android.content.Context
import android.content.ContextWrapper
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyListState
@ -69,4 +72,10 @@ fun Modifier.roundClick(onClick: () -> Unit = {}) = this
fun Modifier.paddingFixedHorizontal(top: Dp = 0.dp, bottom: Dp = 0.dp) = this
.padding(horizontal = 10.dp)
.padding(top = top, bottom = bottom)
.padding(top = top, bottom = bottom)
fun Context.findActivity(): Activity? = when (this) {
is Activity -> this
is ContextWrapper -> baseContext.findActivity()
else -> null
}

View File

@ -1,5 +0,0 @@
package me.ash.reader.ui.util
object Symbol {
const val nothing: String = "null"
}

View File

@ -34,8 +34,8 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.google.accompanist.pager.ExperimentalPagerApi
import com.google.accompanist.pager.PagerState
import me.ash.reader.ui.data.Filter
import me.ash.reader.ui.data.NavigationBarItem
import me.ash.reader.data.constant.Filter
import me.ash.reader.data.constant.NavigationBarItem
import kotlin.math.absoluteValue
@ExperimentalPagerApi