界面优化
This commit is contained in:
@@ -3,6 +3,9 @@ package io.legado.app.ui.book.manage
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.animation.animateColorAsState
|
||||
import androidx.compose.animation.core.FastOutSlowInEasing
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
@@ -22,10 +25,8 @@ import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.MenuOpen
|
||||
import androidx.compose.material.icons.filled.Add
|
||||
import androidx.compose.material.icons.filled.Bookmarks
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.material.icons.filled.Delete
|
||||
import androidx.compose.material.icons.filled.Download
|
||||
import androidx.compose.material.icons.filled.Info
|
||||
@@ -38,18 +39,9 @@ import androidx.compose.material.icons.filled.SkipNext
|
||||
import androidx.compose.material.icons.filled.Stop
|
||||
import androidx.compose.material.icons.filled.Upload
|
||||
import androidx.compose.material3.Checkbox
|
||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||
import androidx.compose.material3.FloatingActionButtonMenu
|
||||
import androidx.compose.material3.FloatingActionButtonMenuItem
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.RadioButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.ToggleFloatingActionButton
|
||||
import androidx.compose.material3.ToggleFloatingActionButtonDefaults.animateIcon
|
||||
import androidx.compose.material3.animateFloatingActionButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableLongStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
@@ -60,7 +52,6 @@ import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
@@ -81,13 +72,18 @@ import io.legado.app.ui.book.changesource.ChangeSourceMigrationOptionsSheet
|
||||
import io.legado.app.ui.book.info.ChangeSourceSheet
|
||||
import io.legado.app.ui.book.info.GroupSelectSheet
|
||||
import io.legado.app.ui.theme.LegadoTheme
|
||||
import io.legado.app.ui.theme.LegadoTheme.composeEngine
|
||||
import io.legado.app.ui.theme.ThemeResolver
|
||||
import io.legado.app.ui.theme.adaptiveContentPadding
|
||||
import io.legado.app.ui.theme.adaptiveHorizontalPadding
|
||||
import io.legado.app.ui.widget.components.AppFloatingActionButtonMenu
|
||||
import io.legado.app.ui.widget.components.AppTextField
|
||||
import io.legado.app.ui.widget.components.FabMenuItem
|
||||
import io.legado.app.ui.widget.components.alert.AppAlertDialog
|
||||
import io.legado.app.ui.widget.components.button.MediumIconButton
|
||||
import io.legado.app.ui.widget.components.button.SmallTonalIconButton
|
||||
import io.legado.app.ui.widget.components.button.SmallTonalTextButton
|
||||
import io.legado.app.ui.widget.components.card.GlassCard
|
||||
import io.legado.app.ui.widget.components.card.NormalCard
|
||||
import io.legado.app.ui.widget.components.card.ReorderableSelectionItem
|
||||
import io.legado.app.ui.widget.components.card.SelectionItemCard
|
||||
@@ -119,11 +115,6 @@ import org.koin.androidx.compose.koinViewModel
|
||||
import sh.calvin.reorderable.ReorderableItem
|
||||
import sh.calvin.reorderable.rememberReorderableLazyListState
|
||||
|
||||
data class BookshelfManageFabAction(
|
||||
val icon: androidx.compose.ui.graphics.vector.ImageVector,
|
||||
val label: String,
|
||||
val action: () -> Unit
|
||||
)
|
||||
|
||||
private data class BookshelfManageListState(
|
||||
override val items: List<Book> = emptyList(),
|
||||
@@ -150,7 +141,6 @@ fun BookshelfManageRouteScreen(
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||
@Composable
|
||||
private fun BookshelfManageScreen(
|
||||
viewModel: BookshelfManageScreenViewModel,
|
||||
@@ -390,20 +380,20 @@ private fun BookshelfManageScreen(
|
||||
return if (targetBooks.all { it.group == firstGroup }) firstGroup else 0L
|
||||
}
|
||||
val fabItems = listOf(
|
||||
BookshelfManageFabAction(
|
||||
FabMenuItem(
|
||||
Icons.Default.SelectAll,
|
||||
stringResource(R.string.select_all)
|
||||
) {
|
||||
selectedBookUrls = filteredBooks.mapTo(hashSetOf()) { it.bookUrl }
|
||||
},
|
||||
BookshelfManageFabAction(
|
||||
FabMenuItem(
|
||||
Icons.Default.Refresh,
|
||||
stringResource(R.string.revert_selection)
|
||||
) {
|
||||
val filteredUrls = filteredBooks.map { it.bookUrl }.toSet()
|
||||
selectedBookUrls = (selectedBookUrls - filteredUrls) + (filteredUrls - selectedBookUrls)
|
||||
},
|
||||
BookshelfManageFabAction(
|
||||
FabMenuItem(
|
||||
Icons.Default.Download,
|
||||
"缓存选中"
|
||||
) {
|
||||
@@ -411,7 +401,7 @@ private fun BookshelfManageScreen(
|
||||
showBatchDownloadConfirmDialog = true
|
||||
}
|
||||
},
|
||||
BookshelfManageFabAction(
|
||||
FabMenuItem(
|
||||
Icons.Default.Refresh,
|
||||
"批量换源"
|
||||
) {
|
||||
@@ -419,7 +409,7 @@ private fun BookshelfManageScreen(
|
||||
showBatchSourcePickerSheet = true
|
||||
}
|
||||
},
|
||||
BookshelfManageFabAction(
|
||||
FabMenuItem(
|
||||
Icons.Default.Bookmarks,
|
||||
stringResource(R.string.move_to_group)
|
||||
) {
|
||||
@@ -429,20 +419,20 @@ private fun BookshelfManageScreen(
|
||||
showGroupSelectSheet = true
|
||||
}
|
||||
},
|
||||
BookshelfManageFabAction(
|
||||
FabMenuItem(
|
||||
Icons.Default.Upload,
|
||||
"导出选中"
|
||||
) {
|
||||
exportSelected()
|
||||
},
|
||||
BookshelfManageFabAction(
|
||||
FabMenuItem(
|
||||
Icons.Default.Delete,
|
||||
stringResource(R.string.clear_cache)
|
||||
) {
|
||||
viewModel.dispatch(BookshelfManageScreenIntent.ClearCachesForBooks(selectedBookUrls))
|
||||
clearSelection()
|
||||
},
|
||||
BookshelfManageFabAction(
|
||||
FabMenuItem(
|
||||
Icons.Default.Delete,
|
||||
stringResource(R.string.delete)
|
||||
) {
|
||||
@@ -620,44 +610,14 @@ private fun BookshelfManageScreen(
|
||||
)
|
||||
},
|
||||
floatingActionButton = {
|
||||
FloatingActionButtonMenu(
|
||||
AppFloatingActionButtonMenu(
|
||||
modifier = Modifier.offset(x = 16.dp, y = 16.dp),
|
||||
expanded = fabMenuExpanded,
|
||||
button = {
|
||||
ToggleFloatingActionButton(
|
||||
modifier = Modifier
|
||||
.animateFloatingActionButton(
|
||||
visible = true,
|
||||
alignment = Alignment.BottomEnd,
|
||||
)
|
||||
.focusRequester(focusRequester),
|
||||
checked = fabMenuExpanded,
|
||||
onCheckedChange = { fabMenuExpanded = !fabMenuExpanded },
|
||||
) {
|
||||
val imageVector by remember {
|
||||
derivedStateOf {
|
||||
if (checkedProgress > 0.5f) Icons.Filled.Close else Icons.AutoMirrored.Filled.MenuOpen
|
||||
}
|
||||
}
|
||||
Icon(
|
||||
imageVector = imageVector,
|
||||
contentDescription = "Menu",
|
||||
modifier = Modifier.animateIcon({ checkedProgress }),
|
||||
)
|
||||
}
|
||||
}
|
||||
) {
|
||||
fabItems.forEach { (icon, label, action) ->
|
||||
FloatingActionButtonMenuItem(
|
||||
onClick = {
|
||||
action()
|
||||
fabMenuExpanded = false
|
||||
},
|
||||
icon = { Icon(icon, contentDescription = null) },
|
||||
text = { Text(text = label) }
|
||||
)
|
||||
}
|
||||
}
|
||||
onExpandedChange = { fabMenuExpanded = it },
|
||||
items = fabItems,
|
||||
visible = true,
|
||||
focusRequester = focusRequester
|
||||
)
|
||||
}
|
||||
) { paddingValues ->
|
||||
val renderVersion by rememberUpdatedState(state.cacheVersion)
|
||||
@@ -681,6 +641,15 @@ private fun BookshelfManageScreen(
|
||||
stringResource(R.string.cache_download_failed, it)
|
||||
}
|
||||
val isSelected = selectedBookUrls.contains(book.bookUrl)
|
||||
val isMiuix = ThemeResolver.isMiuixEngine(composeEngine)
|
||||
val animatedContainerColor by animateColorAsState(
|
||||
targetValue = if (isSelected)
|
||||
LegadoTheme.colorScheme.secondaryContainer
|
||||
else
|
||||
if (isMiuix) LegadoTheme.colorScheme.surfaceContainer else LegadoTheme.colorScheme.surfaceContainerLow,
|
||||
animationSpec = tween(durationMillis = 200, easing = FastOutSlowInEasing),
|
||||
label = "CardColor"
|
||||
)
|
||||
val exportMsg = remember(renderVersion, book.bookUrl) {
|
||||
ExportBookService.exportMsg[book.bookUrl]
|
||||
}
|
||||
@@ -689,7 +658,7 @@ private fun BookshelfManageScreen(
|
||||
key = book.bookUrl,
|
||||
enabled = canReorderBooks
|
||||
) {
|
||||
NormalCard(
|
||||
GlassCard(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.then(
|
||||
@@ -701,11 +670,7 @@ private fun BookshelfManageScreen(
|
||||
),
|
||||
onClick = { toggleBookSelection(book) },
|
||||
onLongClick = { toggleBookSelection(book) },
|
||||
containerColor = if (isSelected) {
|
||||
LegadoTheme.colorScheme.surfaceContainerHigh
|
||||
} else {
|
||||
LegadoTheme.colorScheme.surfaceContainerLow
|
||||
}
|
||||
containerColor = animatedContainerColor
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
|
||||
@@ -36,10 +36,8 @@ import androidx.compose.foundation.pager.HorizontalPager
|
||||
import androidx.compose.foundation.pager.rememberPagerState
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.FormatListBulleted
|
||||
import androidx.compose.material.icons.automirrored.filled.MenuOpen
|
||||
import androidx.compose.material.icons.filled.BookmarkAdd
|
||||
import androidx.compose.material.icons.filled.CheckCircle
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.material.icons.filled.Download
|
||||
import androidx.compose.material.icons.filled.DownloadForOffline
|
||||
import androidx.compose.material.icons.filled.ExpandMore
|
||||
@@ -52,16 +50,10 @@ import androidx.compose.material.icons.outlined.DownloadForOffline
|
||||
import androidx.compose.material.icons.rounded.LocationOn
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||
import androidx.compose.material3.FloatingActionButtonMenu
|
||||
import androidx.compose.material3.FloatingActionButtonMenuItem
|
||||
import androidx.compose.material3.FloatingToolbarDefaults.ScreenOffset
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.ToggleFloatingActionButton
|
||||
import androidx.compose.material3.ToggleFloatingActionButtonDefaults.animateIcon
|
||||
import androidx.compose.material3.animateFloatingActionButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
@@ -76,7 +68,6 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
@@ -95,8 +86,10 @@ import io.legado.app.ui.theme.adaptiveContentPaddingOnlyVertical
|
||||
import io.legado.app.ui.theme.adaptiveHorizontalPadding
|
||||
import io.legado.app.ui.widget.CollapsibleHeader
|
||||
import io.legado.app.ui.widget.components.ActionItem
|
||||
import io.legado.app.ui.widget.components.AppFloatingActionButtonMenu
|
||||
import io.legado.app.ui.widget.components.AppScaffold
|
||||
import io.legado.app.ui.widget.components.EmptyMessage
|
||||
import io.legado.app.ui.widget.components.FabMenuItem
|
||||
import io.legado.app.ui.widget.components.SelectionBottomBar
|
||||
import io.legado.app.ui.widget.components.bookmark.BookmarkEditSheet
|
||||
import io.legado.app.ui.widget.components.bookmark.BookmarkItem
|
||||
@@ -215,7 +208,7 @@ fun TocScreen(
|
||||
|
||||
val fabItems = remember(state.items) {
|
||||
listOf(
|
||||
FabAction(Icons.Default.LocationOn, "定位至当前阅读") {
|
||||
FabMenuItem(Icons.Default.LocationOn, "定位至当前阅读") {
|
||||
scope.launch {
|
||||
val target = state.items.indexOfFirst { it.isDur }
|
||||
if (target != -1) {
|
||||
@@ -226,13 +219,13 @@ fun TocScreen(
|
||||
}
|
||||
}
|
||||
},
|
||||
FabAction(Icons.Default.VerticalAlignTop, "移至顶部") {
|
||||
FabMenuItem(Icons.Default.VerticalAlignTop, "移至顶部") {
|
||||
scope.launch { listState.animateScrollToItem(0) }
|
||||
},
|
||||
FabAction(Icons.Default.VerticalAlignBottom, "移至底部") {
|
||||
FabMenuItem(Icons.Default.VerticalAlignBottom, "移至底部") {
|
||||
scope.launch { listState.animateScrollToItem(state.items.size) }
|
||||
},
|
||||
FabAction(Icons.Default.DownloadForOffline, "下载全部") {
|
||||
FabMenuItem(Icons.Default.DownloadForOffline, "下载全部") {
|
||||
viewModel.downloadAll()
|
||||
}
|
||||
)
|
||||
@@ -509,45 +502,15 @@ fun TocScreen(
|
||||
)
|
||||
},
|
||||
floatingActionButton = {
|
||||
FloatingActionButtonMenu(
|
||||
AppFloatingActionButtonMenu(
|
||||
modifier = Modifier
|
||||
.offset(x = 16.dp, y = 16.dp),
|
||||
expanded = fabMenuExpanded,
|
||||
button = {
|
||||
ToggleFloatingActionButton(
|
||||
modifier = Modifier
|
||||
.animateFloatingActionButton(
|
||||
visible = shouldShowFab,
|
||||
alignment = Alignment.BottomEnd,
|
||||
)
|
||||
.focusRequester(focusRequester),
|
||||
checked = fabMenuExpanded,
|
||||
onCheckedChange = { fabMenuExpanded = !fabMenuExpanded },
|
||||
) {
|
||||
val imageVector by remember {
|
||||
derivedStateOf {
|
||||
if (checkedProgress > 0.5f) Icons.Filled.Close else Icons.AutoMirrored.Filled.MenuOpen
|
||||
}
|
||||
}
|
||||
Icon(
|
||||
imageVector = imageVector,
|
||||
contentDescription = "Menu",
|
||||
modifier = Modifier.animateIcon({ checkedProgress }),
|
||||
)
|
||||
}
|
||||
}
|
||||
) {
|
||||
fabItems.forEach { (icon, label, action) ->
|
||||
FloatingActionButtonMenuItem(
|
||||
onClick = {
|
||||
action()
|
||||
fabMenuExpanded = false
|
||||
},
|
||||
icon = { Icon(icon, contentDescription = null) },
|
||||
text = { Text(text = label) }
|
||||
)
|
||||
}
|
||||
}
|
||||
onExpandedChange = { fabMenuExpanded = it },
|
||||
items = fabItems,
|
||||
visible = shouldShowFab,
|
||||
focusRequester = focusRequester
|
||||
)
|
||||
}
|
||||
) { padding ->
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
|
||||
@@ -4,7 +4,7 @@ import android.app.Application
|
||||
import android.net.Uri
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.runtime.snapshotFlow
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import io.legado.app.base.BaseRuleViewModel
|
||||
@@ -109,8 +109,6 @@ private data class TitleCacheKey(
|
||||
val chapterCount: Int
|
||||
)
|
||||
|
||||
data class FabAction(val icon: ImageVector, val label: String, val action: () -> Unit)
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class TocViewModel(
|
||||
application: Application,
|
||||
|
||||
@@ -219,7 +219,9 @@ fun RssFavoritesScreen(
|
||||
path = rssStar.image,
|
||||
sourceOrigin = rssStar.origin,
|
||||
contentScale = ContentScale.Crop,
|
||||
modifier = Modifier.size(54.dp)
|
||||
modifier = Modifier
|
||||
.padding(vertical = 12.dp)
|
||||
.size(54.dp)
|
||||
)
|
||||
}
|
||||
} else null,
|
||||
|
||||
@@ -3,24 +3,15 @@
|
||||
package io.legado.app.ui.rss.read
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.net.Uri
|
||||
import android.net.http.SslError
|
||||
import android.os.SystemClock
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.webkit.JavascriptInterface
|
||||
import android.webkit.SslErrorHandler
|
||||
import android.webkit.URLUtil
|
||||
import android.webkit.WebChromeClient
|
||||
import android.webkit.WebResourceRequest
|
||||
import android.webkit.WebSettings
|
||||
import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.activity.compose.LocalActivity
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
@@ -28,7 +19,6 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.Login
|
||||
import androidx.compose.material.icons.filled.Check
|
||||
@@ -42,10 +32,6 @@ import androidx.compose.material.icons.filled.Stop
|
||||
import androidx.compose.material.icons.filled.VolumeUp
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import io.legado.app.ui.widget.components.progressIndicator.AppLinearProgressIndicator
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
@@ -59,40 +45,30 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.compose.ui.zIndex
|
||||
import androidx.core.net.toUri
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.script.rhino.runScriptWithContext
|
||||
import io.legado.app.R
|
||||
import io.legado.app.constant.AppConst
|
||||
import io.legado.app.constant.AppLog
|
||||
import io.legado.app.help.config.AppConfig
|
||||
import io.legado.app.help.http.CookieManager
|
||||
import io.legado.app.lib.dialogs.SelectItem
|
||||
import io.legado.app.lib.dialogs.selector
|
||||
import io.legado.app.model.Download
|
||||
import io.legado.app.ui.association.OnLineImportActivity
|
||||
import io.legado.app.ui.config.otherConfig.OtherConfig
|
||||
import io.legado.app.ui.login.SourceLoginActivity
|
||||
import io.legado.app.ui.widget.components.AppScaffold
|
||||
import io.legado.app.ui.widget.components.AppTextField
|
||||
import io.legado.app.ui.widget.components.button.ConfirmDismissButtonsRow
|
||||
import io.legado.app.ui.widget.components.button.MediumIconButton
|
||||
import io.legado.app.ui.widget.components.card.GlassCard
|
||||
import io.legado.app.ui.widget.components.button.SmallIconButton
|
||||
import io.legado.app.ui.widget.components.topbar.TopBarActionButton
|
||||
import io.legado.app.ui.widget.components.topbar.TopBarNavigationButton
|
||||
import io.legado.app.ui.widget.components.menuItem.MenuItemIcon
|
||||
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu
|
||||
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem
|
||||
import io.legado.app.ui.widget.components.modalBottomSheet.AppModalBottomSheet
|
||||
import io.legado.app.ui.widget.components.progressIndicator.AppLinearProgressIndicator
|
||||
import io.legado.app.ui.widget.components.topbar.GlassTopAppBar
|
||||
import io.legado.app.ui.widget.components.topbar.TopBarActionButton
|
||||
import io.legado.app.ui.widget.components.topbar.TopBarNavigationButton
|
||||
import io.legado.app.utils.NetworkUtils
|
||||
import io.legado.app.utils.isTrue
|
||||
import io.legado.app.utils.keepScreenOn
|
||||
import io.legado.app.utils.longSnackbar
|
||||
import io.legado.app.utils.openUrl
|
||||
import io.legado.app.utils.setDarkeningAllowed
|
||||
import io.legado.app.utils.share
|
||||
@@ -101,7 +77,6 @@ import io.legado.app.utils.toastOnUi
|
||||
import io.legado.app.utils.toggleSystemBar
|
||||
import org.apache.commons.text.StringEscapeUtils
|
||||
import org.jsoup.Jsoup
|
||||
import java.net.URLDecoder
|
||||
import org.koin.androidx.compose.koinViewModel
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
@@ -140,7 +115,6 @@ fun RssReadRouteScreen(
|
||||
|
||||
val content by viewModel.contentState.collectAsStateWithLifecycle()
|
||||
val analyzeUrl by viewModel.urlState.collectAsStateWithLifecycle()
|
||||
val rssStar by viewModel.rssStarState.collectAsStateWithLifecycle()
|
||||
val isSpeaking by viewModel.isSpeakingState.collectAsStateWithLifecycle()
|
||||
val fallbackUserAgent = OtherConfig.userAgent
|
||||
|
||||
@@ -175,19 +149,29 @@ fun RssReadRouteScreen(
|
||||
val article = viewModel.rssArticle ?: return@LaunchedEffect
|
||||
val url = NetworkUtils.getAbsoluteURL(article.origin, article.link)
|
||||
val html = viewModel.clHtml(body)
|
||||
if (viewModel.rssSource?.loadWithBaseUrl == true) {
|
||||
currentWebView.loadDataWithBaseURL(url, html, "text/html", "utf-8", url)
|
||||
} else {
|
||||
currentWebView.loadDataWithBaseURL(null, html, "text/html;charset=utf-8", "utf-8", url)
|
||||
if (currentWebView.url != url) {
|
||||
if (viewModel.rssSource?.loadWithBaseUrl == true) {
|
||||
currentWebView.loadDataWithBaseURL(url, html, "text/html", "utf-8", url)
|
||||
} else {
|
||||
currentWebView.loadDataWithBaseURL(
|
||||
null,
|
||||
html,
|
||||
"text/html;charset=utf-8",
|
||||
"utf-8",
|
||||
url
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(analyzeUrl, webView) {
|
||||
val url = analyzeUrl ?: return@LaunchedEffect
|
||||
val currentWebView = webView ?: return@LaunchedEffect
|
||||
CookieManager.applyToWebView(url.url)
|
||||
currentWebView.settings.userAgentString = url.getUserAgent()
|
||||
currentWebView.loadUrl(url.url, url.headerMap)
|
||||
if (currentWebView.url != url.url) {
|
||||
CookieManager.applyToWebView(url.url)
|
||||
currentWebView.settings.userAgentString = url.getUserAgent()
|
||||
currentWebView.loadUrl(url.url, url.headerMap)
|
||||
}
|
||||
}
|
||||
|
||||
BackHandler {
|
||||
@@ -205,17 +189,19 @@ fun RssReadRouteScreen(
|
||||
}
|
||||
}
|
||||
|
||||
val isNight = isSystemInDarkTheme()
|
||||
|
||||
LaunchedEffect(isNight, webView) {
|
||||
val currentWebView = webView ?: return@LaunchedEffect
|
||||
currentWebView.settings.setDarkeningAllowed(isNight)
|
||||
}
|
||||
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
Scaffold(
|
||||
AppScaffold(
|
||||
disableHazeSource = true,
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
title = {
|
||||
Text(
|
||||
text = pageTitle.ifBlank { defaultTopBarTitle },
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
},
|
||||
GlassTopAppBar(
|
||||
title = pageTitle.ifBlank { defaultTopBarTitle },
|
||||
navigationIcon = {
|
||||
TopBarNavigationButton(onClick = onBackClick)
|
||||
},
|
||||
@@ -236,11 +222,11 @@ fun RssReadRouteScreen(
|
||||
}
|
||||
)
|
||||
Box {
|
||||
TopBarActionButton(
|
||||
imageVector = Icons.Default.MoreVert,
|
||||
contentDescription = "Menu",
|
||||
onClick = { showMenu = true }
|
||||
)
|
||||
TopBarActionButton(
|
||||
imageVector = Icons.Default.MoreVert,
|
||||
contentDescription = "Menu",
|
||||
onClick = { showMenu = true }
|
||||
)
|
||||
RoundDropdownMenu(
|
||||
expanded = showMenu,
|
||||
onDismissRequest = { showMenu = false }
|
||||
@@ -256,7 +242,7 @@ fun RssReadRouteScreen(
|
||||
context.share(it.link)
|
||||
} ?: context.toastOnUi(R.string.null_url)
|
||||
}
|
||||
)
|
||||
)
|
||||
RoundDropdownMenuItem(
|
||||
text = if (isSpeaking) stringResource(R.string.aloud_stop) else stringResource(
|
||||
R.string.read_aloud
|
||||
@@ -276,21 +262,21 @@ fun RssReadRouteScreen(
|
||||
Jsoup.parse(html).text()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
if (!viewModel.rssSource?.loginUrl.isNullOrBlank()) {
|
||||
RoundDropdownMenuItem(
|
||||
text = stringResource(R.string.login),
|
||||
leadingIcon = { MenuItemIcon(Icons.AutoMirrored.Filled.Login) },
|
||||
onClick = {
|
||||
dismiss()
|
||||
context.startActivity<SourceLoginActivity> {
|
||||
putExtra("type", "rssSource")
|
||||
putExtra("key", viewModel.rssSource?.sourceUrl)
|
||||
}
|
||||
RoundDropdownMenuItem(
|
||||
text = stringResource(R.string.login),
|
||||
leadingIcon = { MenuItemIcon(Icons.AutoMirrored.Filled.Login) },
|
||||
onClick = {
|
||||
dismiss()
|
||||
context.startActivity<SourceLoginActivity> {
|
||||
putExtra("type", "rssSource")
|
||||
putExtra("key", viewModel.rssSource?.sourceUrl)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
RoundDropdownMenuItem(
|
||||
text = stringResource(R.string.redirect_policy),
|
||||
@@ -301,8 +287,9 @@ fun RssReadRouteScreen(
|
||||
leadingIcon = { MenuItemIcon(Icons.Default.OpenInBrowser) },
|
||||
onClick = {
|
||||
dismiss()
|
||||
webView?.url?.let { context.openUrl(it) } ?: context.toastOnUi("url null")
|
||||
}
|
||||
webView?.url?.let { context.openUrl(it) }
|
||||
?: context.toastOnUi("url null")
|
||||
}
|
||||
)
|
||||
}
|
||||
RoundDropdownMenu(
|
||||
@@ -310,27 +297,30 @@ fun RssReadRouteScreen(
|
||||
onDismissRequest = { showRedirectMenu = false }
|
||||
) { dismiss ->
|
||||
RedirectPolicy.entries.forEach { policy ->
|
||||
RoundDropdownMenuItem(
|
||||
text = policy.title(),
|
||||
onClick = {
|
||||
dismiss()
|
||||
showMenu = false
|
||||
viewModel.rssSource?.let { source ->
|
||||
viewModel.updateRssSourceRedirectPolicy(source.sourceUrl, policy.name)
|
||||
redirectPolicy = policy
|
||||
}
|
||||
context.toastOnUi("重定向策略已更新")
|
||||
},
|
||||
trailingIcon = {
|
||||
if (policy == redirectPolicy) {
|
||||
Icon(Icons.Default.Check, null)
|
||||
}
|
||||
RoundDropdownMenuItem(
|
||||
text = policy.title(),
|
||||
onClick = {
|
||||
dismiss()
|
||||
showMenu = false
|
||||
viewModel.rssSource?.let { source ->
|
||||
viewModel.updateRssSourceRedirectPolicy(
|
||||
source.sourceUrl,
|
||||
policy.name
|
||||
)
|
||||
redirectPolicy = policy
|
||||
}
|
||||
)
|
||||
}
|
||||
context.toastOnUi("重定向策略已更新")
|
||||
},
|
||||
trailingIcon = {
|
||||
if (policy == redirectPolicy) {
|
||||
Icon(Icons.Default.Check, null)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
) { paddingValues ->
|
||||
@@ -369,18 +359,18 @@ fun RssReadRouteScreen(
|
||||
}
|
||||
},
|
||||
onHideCustomView = { hideCustomView() }
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
if (webProgress in 0..99) {
|
||||
AppLinearProgressIndicator(
|
||||
progress = webProgress / 100f,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
customView?.let { view ->
|
||||
key(view) {
|
||||
|
||||
@@ -29,6 +29,7 @@ class VisibleWebView(
|
||||
private var lastSelectedText: String = ""
|
||||
|
||||
init {
|
||||
setBackgroundColor(0)
|
||||
settings.javaScriptEnabled = true
|
||||
settings.domStorageEnabled = true
|
||||
|
||||
|
||||
@@ -1,23 +1,55 @@
|
||||
package io.legado.app.ui.widget.components
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.scaleIn
|
||||
import androidx.compose.animation.scaleOut
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.MenuOpen
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.FloatingActionButtonMenu
|
||||
import androidx.compose.material3.FloatingActionButtonMenuItem
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.PlainTooltip
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.ToggleFloatingActionButton
|
||||
import androidx.compose.material3.ToggleFloatingActionButtonDefaults.animateIcon
|
||||
import androidx.compose.material3.TooltipAnchorPosition
|
||||
import androidx.compose.material3.TooltipBox
|
||||
import androidx.compose.material3.TooltipDefaults
|
||||
import androidx.compose.material3.animateFloatingActionButton
|
||||
import androidx.compose.material3.rememberTooltipState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.legado.app.ui.theme.LegadoTheme
|
||||
import io.legado.app.ui.theme.ThemeResolver
|
||||
import io.legado.app.ui.widget.components.icon.AppIcon
|
||||
import io.legado.app.ui.widget.components.text.AppText
|
||||
import top.yukonga.miuix.kmp.basic.Button
|
||||
import top.yukonga.miuix.kmp.theme.MiuixTheme
|
||||
import top.yukonga.miuix.kmp.basic.FloatingActionButton as MiuixFloatingActionButton
|
||||
import top.yukonga.miuix.kmp.basic.Icon as MiuixIcon
|
||||
import top.yukonga.miuix.kmp.basic.Text as MiuixText
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
@@ -85,3 +117,126 @@ fun AppFloatingActionButton(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class FabMenuItem(
|
||||
val icon: ImageVector,
|
||||
val label: String,
|
||||
val action: () -> Unit
|
||||
)
|
||||
|
||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class, ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun AppFloatingActionButtonMenu(
|
||||
expanded: Boolean,
|
||||
onExpandedChange: (Boolean) -> Unit,
|
||||
items: List<FabMenuItem>,
|
||||
modifier: Modifier = Modifier,
|
||||
visible: Boolean = true,
|
||||
focusRequester: FocusRequester = remember { FocusRequester() }
|
||||
) {
|
||||
val isMiuix = ThemeResolver.isMiuixEngine(LegadoTheme.composeEngine)
|
||||
|
||||
if (isMiuix) {
|
||||
Column(
|
||||
modifier = modifier.padding(horizontal = 16.dp, vertical = 24.dp),
|
||||
horizontalAlignment = Alignment.End,
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
||||
) {
|
||||
items.forEachIndexed { index, (icon, label, action) ->
|
||||
AnimatedVisibility(
|
||||
visible = expanded,
|
||||
enter = fadeIn(tween(delayMillis = index * 40)) +
|
||||
scaleIn(tween(delayMillis = index * 40), initialScale = 0.8f),
|
||||
exit = fadeOut(tween(80)) + scaleOut(tween(80), targetScale = 0.8f)
|
||||
) {
|
||||
Button(
|
||||
onClick = {
|
||||
action()
|
||||
onExpandedChange(false)
|
||||
}
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
MiuixIcon(
|
||||
imageVector = icon,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
MiuixText(
|
||||
text = label,
|
||||
style = MiuixTheme.textStyles.subtitle
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AnimatedVisibility(
|
||||
visible = visible,
|
||||
enter = fadeIn() + scaleIn(initialScale = 0.8f),
|
||||
exit = fadeOut() + scaleOut(targetScale = 0.8f)
|
||||
) {
|
||||
MiuixFloatingActionButton(
|
||||
onClick = { onExpandedChange(!expanded) }
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
modifier = Modifier.padding(horizontal = 16.dp)
|
||||
) {
|
||||
MiuixIcon(
|
||||
imageVector = if (expanded) Icons.Filled.Close
|
||||
else Icons.AutoMirrored.Filled.MenuOpen,
|
||||
contentDescription = "Menu",
|
||||
tint = Color.White
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text("菜单", color = Color.White)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
FloatingActionButtonMenu(
|
||||
modifier = modifier,
|
||||
expanded = expanded,
|
||||
button = {
|
||||
ToggleFloatingActionButton(
|
||||
modifier = Modifier
|
||||
.animateFloatingActionButton(
|
||||
visible = visible,
|
||||
alignment = Alignment.BottomEnd,
|
||||
)
|
||||
.focusRequester(focusRequester),
|
||||
checked = expanded,
|
||||
onCheckedChange = { onExpandedChange(!expanded) },
|
||||
) {
|
||||
val imageVector by remember {
|
||||
derivedStateOf {
|
||||
if (checkedProgress > 0.5f) Icons.Filled.Close
|
||||
else Icons.AutoMirrored.Filled.MenuOpen
|
||||
}
|
||||
}
|
||||
Icon(
|
||||
imageVector = imageVector,
|
||||
contentDescription = "Menu",
|
||||
modifier = Modifier.animateIcon({ checkedProgress }),
|
||||
)
|
||||
}
|
||||
}
|
||||
) {
|
||||
items.forEach { (icon, label, action) ->
|
||||
FloatingActionButtonMenuItem(
|
||||
onClick = {
|
||||
action()
|
||||
onExpandedChange(false)
|
||||
},
|
||||
icon = { Icon(icon, contentDescription = null) },
|
||||
text = { Text(text = label) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.blur
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.unit.dp
|
||||
import coil.compose.AsyncImage
|
||||
@@ -44,6 +43,7 @@ fun AppScaffold(
|
||||
contentColor: Color = contentColorFor(MiuixTheme.colorScheme.surface),
|
||||
contentWindowInsets: WindowInsets = ScaffoldDefaults.contentWindowInsets,
|
||||
alwaysDrawBehindBars: Boolean = false,
|
||||
disableHazeSource: Boolean = false,
|
||||
content: @Composable (PaddingValues) -> Unit
|
||||
) {
|
||||
val isDark = isSystemInDarkTheme()
|
||||
@@ -97,7 +97,10 @@ fun AppScaffold(
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.responsiveHazeSource(hazeState)
|
||||
.then(
|
||||
if (!disableHazeSource) Modifier.responsiveHazeSource(hazeState)
|
||||
else Modifier
|
||||
)
|
||||
.then(
|
||||
if (contentDrawsBehindBars) Modifier
|
||||
else Modifier.padding(scaffoldPadding)
|
||||
@@ -136,7 +139,10 @@ fun AppScaffold(
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.responsiveHazeSource(hazeState)
|
||||
.then(
|
||||
if (!disableHazeSource) Modifier.responsiveHazeSource(hazeState)
|
||||
else Modifier
|
||||
)
|
||||
.then(
|
||||
if (contentDrawsBehindBars) Modifier
|
||||
else Modifier.padding(scaffoldPadding)
|
||||
|
||||
@@ -22,9 +22,6 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import io.legado.app.ui.theme.adaptiveHorizontalPadding
|
||||
import io.legado.app.ui.widget.components.SearchBar
|
||||
import io.legado.app.ui.widget.components.icon.AppIcon
|
||||
import io.legado.app.ui.widget.components.topbar.TopBarActionButton
|
||||
import io.legado.app.ui.widget.components.topbar.TopBarNavigationButton
|
||||
import io.legado.app.ui.widget.components.icon.AppIcons
|
||||
import io.legado.app.ui.widget.components.list.ListUiState
|
||||
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu
|
||||
@@ -118,12 +115,6 @@ fun <T> DynamicTopAppBar(
|
||||
onQueryChange = onSearchQueryChange,
|
||||
onSearch = onSearchSubmit,
|
||||
placeholder = searchPlaceholder,
|
||||
leadingIcon = {
|
||||
AppIcon(
|
||||
imageVector = searchLeadingIcon,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
trailingIcon = searchTrailingIcon,
|
||||
dropdownMenu = searchDropdownMenu
|
||||
)
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
package io.legado.app.ui.widget.components.topbar
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import io.legado.app.ui.theme.LegadoTheme
|
||||
import io.legado.app.ui.theme.LocalHazeState
|
||||
import io.legado.app.ui.theme.ThemeResolver
|
||||
import io.legado.app.ui.theme.responsiveHazeEffect
|
||||
import top.yukonga.miuix.kmp.basic.TopAppBar as MiuixTopAppBar
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun GlassTopAppBar(
|
||||
title: String,
|
||||
modifier: Modifier = Modifier,
|
||||
navigationIcon: @Composable () -> Unit = {},
|
||||
actions: @Composable RowScope.() -> Unit = {},
|
||||
) {
|
||||
val hazeState = LocalHazeState.current
|
||||
val composeEngine = LegadoTheme.composeEngine
|
||||
val isMiuix = ThemeResolver.isMiuixEngine(composeEngine)
|
||||
|
||||
val containerColor = if (!isMiuix) {
|
||||
GlassTopAppBarDefaults.containerColor()
|
||||
} else {
|
||||
GlassTopAppBarDefaults.getMiuixAppBarColor()
|
||||
}
|
||||
|
||||
val finalModifier = if (hazeState != null) {
|
||||
modifier
|
||||
.background(color = containerColor)
|
||||
.responsiveHazeEffect(state = hazeState)
|
||||
} else {
|
||||
modifier.background(color = containerColor)
|
||||
}
|
||||
|
||||
Column(modifier = finalModifier) {
|
||||
if (isMiuix) {
|
||||
MiuixTopAppBar(
|
||||
title = title,
|
||||
navigationIcon = navigationIcon,
|
||||
actions = actions,
|
||||
color = Color.Transparent
|
||||
)
|
||||
} else {
|
||||
TopAppBar(
|
||||
title = {
|
||||
Text(
|
||||
text = title,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
style = MaterialTheme.typography.titleLarge
|
||||
)
|
||||
},
|
||||
navigationIcon = navigationIcon,
|
||||
actions = actions,
|
||||
colors = TopAppBarDefaults.topAppBarColors(
|
||||
containerColor = Color.Transparent,
|
||||
scrolledContainerColor = Color.Transparent
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,9 @@
|
||||
package io.legado.app.utils
|
||||
|
||||
import android.content.res.Configuration
|
||||
import android.content.res.Resources
|
||||
import splitties.init.appCtx
|
||||
|
||||
val sysConfiguration: Configuration = Resources.getSystem().configuration
|
||||
val sysConfiguration: Configuration get() = appCtx.resources.configuration
|
||||
|
||||
val Configuration.isNightMode: Boolean
|
||||
get() {
|
||||
|
||||
Reference in New Issue
Block a user