界面优化

This commit is contained in:
HapeLee committed 2026-05-15 21:20:49 +08:00
1 parent f411b7136e
commit e64e50bf38
23 files changed
+1234 -1072

No files matched your search

-10
View File
@@ -193,11 +193,6 @@
android:name=".ui.qrcode.QrCodeActivity" android:name=".ui.qrcode.QrCodeActivity"
android:enableOnBackInvokedCallback="true" android:enableOnBackInvokedCallback="true"
android:launchMode="singleTask" /> android:launchMode="singleTask" />
<!-- 规则订阅 -->
<activity
android:name=".ui.rss.subscription.RuleSubActivity"
android:enableOnBackInvokedCallback="true"
android:launchMode="singleTask" />
<!-- 书源编辑 --> <!-- 书源编辑 -->
<activity <activity
android:name=".ui.book.source.edit.BookSourceEditActivity" android:name=".ui.book.source.edit.BookSourceEditActivity"
@@ -268,11 +263,6 @@
android:name=".ui.rss.source.debug.RssSourceDebugActivity" android:name=".ui.rss.source.debug.RssSourceDebugActivity"
android:enableOnBackInvokedCallback="true" android:enableOnBackInvokedCallback="true"
android:launchMode="singleTop" /> android:launchMode="singleTop" />
<!-- Rss收藏 -->
<activity
android:name=".ui.rss.favorites.RssFavoritesActivity"
android:enableOnBackInvokedCallback="true"
android:launchMode="singleTop" />
<!-- 书签 --> <!-- 书签 -->
<activity <activity
android:name=".ui.book.bookmark.AllBookmarkActivity" android:name=".ui.book.bookmark.AllBookmarkActivity"
@@ -271,6 +271,7 @@ object PreferKey {
const val bookshelfCoverShadow = "bookshelfCoverShadow" const val bookshelfCoverShadow = "bookshelfCoverShadow"
const val bookshelfSearchActionDirectToSearch = "bookshelfSearchActionDirectToSearch" const val bookshelfSearchActionDirectToSearch = "bookshelfSearchActionDirectToSearch"
const val bookshelfCardColor = "bookshelfCardColor" const val bookshelfCardColor = "bookshelfCardColor"
const val bookshelfCardColorDark = "bookshelfCardColorDark"
const val bookshelfGroupListStyle = "bookshelfGroupListStyle" const val bookshelfGroupListStyle = "bookshelfGroupListStyle"
const val bookshelfGroupCoverCount = "bookshelfGroupCoverCount" const val bookshelfGroupCoverCount = "bookshelfGroupCoverCount"
@@ -723,8 +723,8 @@ interface BookDao {
type, `group`, `order`, canUpdate, type, `group`, `order`, canUpdate,
ifnull(customIntro, intro) as intro, kind ifnull(customIntro, intro) as intro, kind
FROM books FROM books
ORDER BY CASE WHEN (coverUrl IS NOT NULL OR customCoverUrl IS NOT NULL) THEN 0 ELSE 1 END, durChapterTime DESC ORDER BY durChapterTime DESC
LIMIT 4 LIMIT 10
""" """
) )
fun flowBookShelfPreview(): Flow<List<BookShelfItem>> fun flowBookShelfPreview(): Flow<List<BookShelfItem>>
@@ -741,8 +741,8 @@ interface BookDao {
WHERE type & ${BookType.text} > 0 AND type & ${BookType.local} = 0 WHERE type & ${BookType.text} > 0 AND type & ${BookType.local} = 0
AND ((SELECT COALESCE(SUM(groupId), 0) FROM book_groups WHERE groupId > 0) & `group`) = 0 AND ((SELECT COALESCE(SUM(groupId), 0) FROM book_groups WHERE groupId > 0) & `group`) = 0
AND (SELECT show FROM book_groups WHERE groupId = ${BookGroup.IdNetNone}) != 1 AND (SELECT show FROM book_groups WHERE groupId = ${BookGroup.IdNetNone}) != 1
ORDER BY CASE WHEN (coverUrl IS NOT NULL OR customCoverUrl IS NOT NULL) THEN 0 ELSE 1 END, durChapterTime DESC ORDER BY durChapterTime DESC
LIMIT 4 LIMIT 10
""" """
) )
fun flowBookShelfRootPreview(): Flow<List<BookShelfItem>> fun flowBookShelfRootPreview(): Flow<List<BookShelfItem>>
@@ -757,8 +757,8 @@ interface BookDao {
ifnull(customIntro, intro) as intro, kind ifnull(customIntro, intro) as intro, kind
FROM books FROM books
WHERE type & ${BookType.local} > 0 WHERE type & ${BookType.local} > 0
ORDER BY CASE WHEN (coverUrl IS NOT NULL OR customCoverUrl IS NOT NULL) THEN 0 ELSE 1 END, durChapterTime DESC ORDER BY durChapterTime DESC
LIMIT 4 LIMIT 10
""" """
) )
fun flowBookShelfLocalPreview(): Flow<List<BookShelfItem>> fun flowBookShelfLocalPreview(): Flow<List<BookShelfItem>>
@@ -773,8 +773,8 @@ interface BookDao {
ifnull(customIntro, intro) as intro, kind ifnull(customIntro, intro) as intro, kind
FROM books FROM books
WHERE type & ${BookType.audio} > 0 WHERE type & ${BookType.audio} > 0
ORDER BY CASE WHEN (coverUrl IS NOT NULL OR customCoverUrl IS NOT NULL) THEN 0 ELSE 1 END, durChapterTime DESC ORDER BY durChapterTime DESC
LIMIT 4 LIMIT 10
""" """
) )
fun flowBookShelfAudioPreview(): Flow<List<BookShelfItem>> fun flowBookShelfAudioPreview(): Flow<List<BookShelfItem>>
@@ -790,8 +790,8 @@ interface BookDao {
FROM books FROM books
WHERE type & ${BookType.audio} = 0 AND type & ${BookType.local} = 0 WHERE type & ${BookType.audio} = 0 AND type & ${BookType.local} = 0
AND ((SELECT COALESCE(SUM(groupId), 0) FROM book_groups WHERE groupId > 0) & `group`) = 0 AND ((SELECT COALESCE(SUM(groupId), 0) FROM book_groups WHERE groupId > 0) & `group`) = 0
ORDER BY CASE WHEN (coverUrl IS NOT NULL OR customCoverUrl IS NOT NULL) THEN 0 ELSE 1 END, durChapterTime DESC ORDER BY durChapterTime DESC
LIMIT 4 LIMIT 10
""" """
) )
fun flowBookShelfNetNoGroupPreview(): Flow<List<BookShelfItem>> fun flowBookShelfNetNoGroupPreview(): Flow<List<BookShelfItem>>
@@ -807,8 +807,8 @@ interface BookDao {
FROM books FROM books
WHERE type & ${BookType.local} > 0 WHERE type & ${BookType.local} > 0
AND ((SELECT COALESCE(SUM(groupId), 0) FROM book_groups WHERE groupId > 0) & `group`) = 0 AND ((SELECT COALESCE(SUM(groupId), 0) FROM book_groups WHERE groupId > 0) & `group`) = 0
ORDER BY CASE WHEN (coverUrl IS NOT NULL OR customCoverUrl IS NOT NULL) THEN 0 ELSE 1 END, durChapterTime DESC ORDER BY durChapterTime DESC
LIMIT 4 LIMIT 10
""" """
) )
fun flowBookShelfLocalNoGroupPreview(): Flow<List<BookShelfItem>> fun flowBookShelfLocalNoGroupPreview(): Flow<List<BookShelfItem>>
@@ -823,8 +823,8 @@ interface BookDao {
ifnull(customIntro, intro) as intro, kind ifnull(customIntro, intro) as intro, kind
FROM books FROM books
WHERE type & ${BookType.image} > 0 WHERE type & ${BookType.image} > 0
ORDER BY CASE WHEN (coverUrl IS NOT NULL OR customCoverUrl IS NOT NULL) THEN 0 ELSE 1 END, durChapterTime DESC ORDER BY durChapterTime DESC
LIMIT 4 LIMIT 10
""" """
) )
fun flowBookShelfMangaPreview(): Flow<List<BookShelfItem>> fun flowBookShelfMangaPreview(): Flow<List<BookShelfItem>>
@@ -839,8 +839,8 @@ interface BookDao {
ifnull(customIntro, intro) as intro, kind ifnull(customIntro, intro) as intro, kind
FROM books FROM books
WHERE type & ${BookType.text} > 0 WHERE type & ${BookType.text} > 0
ORDER BY CASE WHEN (coverUrl IS NOT NULL OR customCoverUrl IS NOT NULL) THEN 0 ELSE 1 END, durChapterTime DESC ORDER BY durChapterTime DESC
LIMIT 4 LIMIT 10
""" """
) )
fun flowBookShelfTextPreview(): Flow<List<BookShelfItem>> fun flowBookShelfTextPreview(): Flow<List<BookShelfItem>>
@@ -855,8 +855,8 @@ interface BookDao {
ifnull(customIntro, intro) as intro, kind ifnull(customIntro, intro) as intro, kind
FROM books FROM books
WHERE type & ${BookType.updateError} > 0 WHERE type & ${BookType.updateError} > 0
ORDER BY CASE WHEN (coverUrl IS NOT NULL OR customCoverUrl IS NOT NULL) THEN 0 ELSE 1 END, durChapterTime DESC ORDER BY durChapterTime DESC
LIMIT 4 LIMIT 10
""" """
) )
fun flowBookShelfUpdateErrorPreview(): Flow<List<BookShelfItem>> fun flowBookShelfUpdateErrorPreview(): Flow<List<BookShelfItem>>
@@ -871,8 +871,8 @@ interface BookDao {
ifnull(customIntro, intro) as intro, kind ifnull(customIntro, intro) as intro, kind
FROM books FROM books
WHERE durChapterIndex = 0 AND durChapterPos = 0 WHERE durChapterIndex = 0 AND durChapterPos = 0
ORDER BY CASE WHEN (coverUrl IS NOT NULL OR customCoverUrl IS NOT NULL) THEN 0 ELSE 1 END, durChapterTime DESC ORDER BY durChapterTime DESC
LIMIT 4 LIMIT 10
""" """
) )
fun flowBookShelfUnreadPreview(): Flow<List<BookShelfItem>> fun flowBookShelfUnreadPreview(): Flow<List<BookShelfItem>>
@@ -887,8 +887,8 @@ interface BookDao {
ifnull(customIntro, intro) as intro, kind ifnull(customIntro, intro) as intro, kind
FROM books FROM books
WHERE totalChapterNum > 0 AND durChapterIndex > 0 AND durChapterIndex < totalChapterNum - 1 WHERE totalChapterNum > 0 AND durChapterIndex > 0 AND durChapterIndex < totalChapterNum - 1
ORDER BY CASE WHEN (coverUrl IS NOT NULL OR customCoverUrl IS NOT NULL) THEN 0 ELSE 1 END, durChapterTime DESC ORDER BY durChapterTime DESC
LIMIT 4 LIMIT 10
""" """
) )
fun flowBookShelfReadingPreview(): Flow<List<BookShelfItem>> fun flowBookShelfReadingPreview(): Flow<List<BookShelfItem>>
@@ -903,8 +903,8 @@ interface BookDao {
ifnull(customIntro, intro) as intro, kind ifnull(customIntro, intro) as intro, kind
FROM books FROM books
WHERE totalChapterNum > 0 AND durChapterIndex >= totalChapterNum - 1 WHERE totalChapterNum > 0 AND durChapterIndex >= totalChapterNum - 1
ORDER BY CASE WHEN (coverUrl IS NOT NULL OR customCoverUrl IS NOT NULL) THEN 0 ELSE 1 END, durChapterTime DESC ORDER BY durChapterTime DESC
LIMIT 4 LIMIT 10
""" """
) )
fun flowBookShelfReadFinishedPreview(): Flow<List<BookShelfItem>> fun flowBookShelfReadFinishedPreview(): Flow<List<BookShelfItem>>
@@ -919,8 +919,8 @@ interface BookDao {
ifnull(customIntro, intro) as intro, kind ifnull(customIntro, intro) as intro, kind
FROM books FROM books
WHERE (`group` & :groupId) > 0 WHERE (`group` & :groupId) > 0
ORDER BY CASE WHEN (coverUrl IS NOT NULL OR customCoverUrl IS NOT NULL) THEN 0 ELSE 1 END, durChapterTime DESC ORDER BY durChapterTime DESC
LIMIT 4 LIMIT 10
""" """
) )
fun flowBookShelfPreviewByUserGroup(groupId: Long): Flow<List<BookShelfItem>> fun flowBookShelfPreviewByUserGroup(groupId: Long): Flow<List<BookShelfItem>>
@@ -14,23 +14,23 @@ import io.legado.app.data.repository.BookRepository
import io.legado.app.data.repository.BookSourceCallbackRepository import io.legado.app.data.repository.BookSourceCallbackRepository
import io.legado.app.data.repository.CacheBookDownloadRepository import io.legado.app.data.repository.CacheBookDownloadRepository
import io.legado.app.data.repository.DatabaseMaintenanceRepository import io.legado.app.data.repository.DatabaseMaintenanceRepository
import io.legado.app.data.repository.DirectLinkUploadRepository
import io.legado.app.data.repository.DictRuleRepository import io.legado.app.data.repository.DictRuleRepository
import io.legado.app.data.repository.DirectLinkUploadRepository
import io.legado.app.data.repository.ExploreRepository import io.legado.app.data.repository.ExploreRepository
import io.legado.app.data.repository.ExploreRepositoryImpl import io.legado.app.data.repository.ExploreRepositoryImpl
import io.legado.app.data.repository.LocalBookRepository import io.legado.app.data.repository.LocalBookRepository
import io.legado.app.data.repository.ReadRecordRepository import io.legado.app.data.repository.ReadRecordRepository
import io.legado.app.data.repository.RemoteBookRepository import io.legado.app.data.repository.RemoteBookRepository
import io.legado.app.data.repository.RssRepository import io.legado.app.data.repository.RssRepository
import io.legado.app.data.repository.SearchContentRepository
import io.legado.app.data.repository.SearchRepository import io.legado.app.data.repository.SearchRepository
import io.legado.app.data.repository.SearchRepositoryImpl import io.legado.app.data.repository.SearchRepositoryImpl
import io.legado.app.data.repository.SearchContentRepository
import io.legado.app.data.repository.SettingsRepository import io.legado.app.data.repository.SettingsRepository
import io.legado.app.data.repository.UploadRepository import io.legado.app.data.repository.UploadRepository
import io.legado.app.data.repository.WebDavBackupRepository import io.legado.app.data.repository.WebDavBackupRepository
import io.legado.app.data.repository.WebDavReadingProgressRepository import io.legado.app.data.repository.WebDavReadingProgressRepository
import io.legado.app.domain.gateway.BookCacheCleanupGateway
import io.legado.app.domain.gateway.AppStartupGateway import io.legado.app.domain.gateway.AppStartupGateway
import io.legado.app.domain.gateway.BookCacheCleanupGateway
import io.legado.app.domain.gateway.BookCacheDownloadGateway import io.legado.app.domain.gateway.BookCacheDownloadGateway
import io.legado.app.domain.gateway.BookSearchGateway import io.legado.app.domain.gateway.BookSearchGateway
import io.legado.app.domain.gateway.BookSourceCallbackGateway import io.legado.app.domain.gateway.BookSourceCallbackGateway
@@ -47,14 +47,13 @@ import io.legado.app.domain.usecase.ClearBookCacheUseCase
import io.legado.app.domain.usecase.DeleteBooksUseCase import io.legado.app.domain.usecase.DeleteBooksUseCase
import io.legado.app.domain.usecase.GetReadingProgressUseCase import io.legado.app.domain.usecase.GetReadingProgressUseCase
import io.legado.app.domain.usecase.RemoveBookGroupAssignmentUseCase import io.legado.app.domain.usecase.RemoveBookGroupAssignmentUseCase
import io.legado.app.ui.widget.components.explore.ExploreKindUiUseCase
import io.legado.app.domain.usecase.ResolveBookShelfStateUseCase import io.legado.app.domain.usecase.ResolveBookShelfStateUseCase
import io.legado.app.domain.usecase.readRecord.GetReadRecordOverviewUseCase
import io.legado.app.domain.usecase.SearchBooksUseCase import io.legado.app.domain.usecase.SearchBooksUseCase
import io.legado.app.domain.usecase.ShrinkDatabaseUseCase import io.legado.app.domain.usecase.ShrinkDatabaseUseCase
import io.legado.app.domain.usecase.UpdateBooksGroupUseCase import io.legado.app.domain.usecase.UpdateBooksGroupUseCase
import io.legado.app.domain.usecase.UploadReadingProgressUseCase import io.legado.app.domain.usecase.UploadReadingProgressUseCase
import io.legado.app.domain.usecase.WebDavBackupUseCase import io.legado.app.domain.usecase.WebDavBackupUseCase
import io.legado.app.domain.usecase.readRecord.GetReadRecordOverviewUseCase
import io.legado.app.help.coil.CoverFetcher import io.legado.app.help.coil.CoverFetcher
import io.legado.app.help.coil.CoverInterceptor import io.legado.app.help.coil.CoverInterceptor
import io.legado.app.help.http.okHttpClient import io.legado.app.help.http.okHttpClient
@@ -64,7 +63,6 @@ import io.legado.app.ui.book.cache.manage.BookCacheManageViewModel
import io.legado.app.ui.book.changecover.ChangeCoverViewModel import io.legado.app.ui.book.changecover.ChangeCoverViewModel
import io.legado.app.ui.book.changesource.ChangeBookSourceComposeViewModel import io.legado.app.ui.book.changesource.ChangeBookSourceComposeViewModel
import io.legado.app.ui.book.changesource.ChangeBookSourceViewModel import io.legado.app.ui.book.changesource.ChangeBookSourceViewModel
import io.legado.app.ui.book.manage.BookshelfManageScreenViewModel
import io.legado.app.ui.book.explore.ExploreShowViewModel import io.legado.app.ui.book.explore.ExploreShowViewModel
import io.legado.app.ui.book.group.GroupViewModel import io.legado.app.ui.book.group.GroupViewModel
import io.legado.app.ui.book.import.local.ImportBookViewModel import io.legado.app.ui.book.import.local.ImportBookViewModel
@@ -72,10 +70,11 @@ import io.legado.app.ui.book.import.remote.RemoteBookViewModel
import io.legado.app.ui.book.import.remote.ServerConfigViewModel import io.legado.app.ui.book.import.remote.ServerConfigViewModel
import io.legado.app.ui.book.import.remote.ServersViewModel import io.legado.app.ui.book.import.remote.ServersViewModel
import io.legado.app.ui.book.info.BookInfoViewModel import io.legado.app.ui.book.info.BookInfoViewModel
import io.legado.app.ui.book.manage.BookshelfManageScreenViewModel
import io.legado.app.ui.book.manga.ReadMangaViewModel import io.legado.app.ui.book.manga.ReadMangaViewModel
import io.legado.app.ui.book.read.ReadBookViewModel import io.legado.app.ui.book.read.ReadBookViewModel
import io.legado.app.ui.book.readRecord.ReadRecordViewModel
import io.legado.app.ui.book.readRecord.ReadRecordOverviewViewModel import io.legado.app.ui.book.readRecord.ReadRecordOverviewViewModel
import io.legado.app.ui.book.readRecord.ReadRecordViewModel
import io.legado.app.ui.book.search.SearchViewModel import io.legado.app.ui.book.search.SearchViewModel
import io.legado.app.ui.book.searchContent.SearchContentViewModel import io.legado.app.ui.book.searchContent.SearchContentViewModel
import io.legado.app.ui.book.toc.TocViewModel import io.legado.app.ui.book.toc.TocViewModel
@@ -97,10 +96,13 @@ import io.legado.app.ui.main.rss.RssViewModel
import io.legado.app.ui.replace.ReplaceEditRoute import io.legado.app.ui.replace.ReplaceEditRoute
import io.legado.app.ui.replace.ReplaceRuleViewModel import io.legado.app.ui.replace.ReplaceRuleViewModel
import io.legado.app.ui.replace.edit.ReplaceEditViewModel import io.legado.app.ui.replace.edit.ReplaceEditViewModel
import io.legado.app.ui.rss.source.manage.RssSourceViewModel
import io.legado.app.ui.rss.article.RssArticlesViewModel import io.legado.app.ui.rss.article.RssArticlesViewModel
import io.legado.app.ui.rss.article.RssSortViewModel import io.legado.app.ui.rss.article.RssSortViewModel
import io.legado.app.ui.rss.favorites.RssFavoritesViewModel
import io.legado.app.ui.rss.read.ReadRssViewModel import io.legado.app.ui.rss.read.ReadRssViewModel
import io.legado.app.ui.rss.source.manage.RssSourceViewModel
import io.legado.app.ui.rss.subscription.RuleSubViewModel
import io.legado.app.ui.widget.components.explore.ExploreKindUiUseCase
import org.koin.core.module.dsl.singleOf import org.koin.core.module.dsl.singleOf
import org.koin.core.module.dsl.viewModel import org.koin.core.module.dsl.viewModel
import org.koin.core.module.dsl.viewModelOf import org.koin.core.module.dsl.viewModelOf
@@ -179,6 +181,8 @@ val appModule = module {
viewModelOf(::RssSortViewModel) viewModelOf(::RssSortViewModel)
viewModelOf(::RssArticlesViewModel) viewModelOf(::RssArticlesViewModel)
viewModelOf(::ReadRssViewModel) viewModelOf(::ReadRssViewModel)
viewModelOf(::RssFavoritesViewModel)
viewModelOf(::RuleSubViewModel)
viewModelOf(::ReadRecordViewModel) viewModelOf(::ReadRecordViewModel)
viewModelOf(::ReadRecordOverviewViewModel) viewModelOf(::ReadRecordOverviewViewModel)
viewModelOf(::ExploreShowViewModel) viewModelOf(::ExploreShowViewModel)
@@ -269,12 +269,17 @@ object BookshelfConfig {
/** /**
* 书架卡片背景颜色 * 书架卡片背景颜色
*/ */
private val _bookshelfCardColor = prefStateDelegate(PreferKey.bookshelfCardColor, 0) { private val _bookshelfCardColor = prefStateDelegate(PreferKey.bookshelfCardColor, 0)
postEvent(EventBus.NOTIFY_MAIN, false)
}
var bookshelfCardColor by _bookshelfCardColor var bookshelfCardColor by _bookshelfCardColor
val bookshelfCardColorState: State<Int> get() = _bookshelfCardColor.state val bookshelfCardColorState: State<Int> get() = _bookshelfCardColor.state
/**
* 书架卡片背景颜色 (夜间)
*/
private val _bookshelfCardColorDark = prefStateDelegate(PreferKey.bookshelfCardColorDark, 0)
var bookshelfCardColorDark by _bookshelfCardColorDark
val bookshelfCardColorDarkState: State<Int> get() = _bookshelfCardColorDark.state
/** /**
* 文件夹在列表模式下的样式: 0: 默认, 2: 横排封面 * 文件夹在列表模式下的样式: 0: 默认, 2: 横排封面
*/ */
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,152 @@
package io.legado.app.ui.main
import android.content.Context
import android.content.Intent
import io.legado.app.ui.config.ConfigTag
object MainIntent {
const val EXTRA_START_ROUTE = "startRoute"
const val EXTRA_CACHE_GROUP_ID = "extra_cache_group_id"
const val EXTRA_SEARCH_KEY = "extra_search_key"
const val EXTRA_SEARCH_SCOPE = "extra_search_scope"
const val EXTRA_BOOK_NAME = "name"
const val EXTRA_BOOK_AUTHOR = "author"
const val EXTRA_BOOK_URL = "bookUrl"
const val EXTRA_EXPLORE_NAME = "exploreName"
const val EXTRA_SOURCE_URL = "sourceUrl"
const val EXTRA_EXPLORE_URL = "exploreUrl"
const val EXTRA_RSS_SOURCE_URL = "extra_rss_source_url"
const val EXTRA_RSS_SORT_URL = "extra_rss_sort_url"
const val EXTRA_RSS_KEY = "extra_rss_key"
const val EXTRA_RSS_READ_TITLE = "extra_rss_read_title"
const val EXTRA_RSS_READ_ORIGIN = "extra_rss_read_origin"
const val EXTRA_RSS_READ_LINK = "extra_rss_read_link"
const val EXTRA_RSS_READ_OPEN_URL = "extra_rss_read_open_url"
fun createLauncherIntent(context: Context): Intent {
val launcherComponent =
context.packageManager.getLaunchIntentForPackage(context.packageName)?.component
return if (launcherComponent != null) {
Intent().setComponent(launcherComponent)
} else {
Intent(context, MainActivity::class.java)
}
}
fun createHomeIntent(context: Context): Intent {
return createLauncherIntent(context).apply {
putExtra(EXTRA_START_ROUTE, MainRouteConst.ROUTE_MAIN)
}
}
fun createIntent(context: Context, configTag: String? = null): Intent {
return createLauncherIntent(context).apply {
putExtra(EXTRA_START_ROUTE, routeForConfigTag(configTag))
}
}
fun createRssSortIntent(
context: Context,
sourceUrl: String,
sortUrl: String? = null,
key: String? = null
): Intent {
return createLauncherIntent(context).apply {
putExtra(EXTRA_START_ROUTE, MainRouteConst.ROUTE_RSS_SORT)
putExtra(EXTRA_RSS_SOURCE_URL, sourceUrl)
putExtra(EXTRA_RSS_SORT_URL, sortUrl)
putExtra(EXTRA_RSS_KEY, key)
}
}
fun createRssReadIntent(
context: Context,
title: String? = null,
origin: String,
link: String? = null,
openUrl: String? = null
): Intent {
return createLauncherIntent(context).apply {
putExtra(EXTRA_START_ROUTE, MainRouteConst.ROUTE_RSS_READ)
putExtra(EXTRA_RSS_READ_TITLE, title)
putExtra(EXTRA_RSS_READ_ORIGIN, origin)
putExtra(EXTRA_RSS_READ_LINK, link)
putExtra(EXTRA_RSS_READ_OPEN_URL, openUrl)
}
}
fun createBookshelfManageScreenIntent(
context: Context,
groupId: Long = -1L
): Intent {
return createLauncherIntent(context).apply {
putExtra(EXTRA_START_ROUTE, MainRouteConst.ROUTE_CACHE)
putExtra(EXTRA_CACHE_GROUP_ID, groupId)
}
}
fun createCacheIntent(
context: Context,
groupId: Long = -1L
): Intent = createBookshelfManageScreenIntent(context, groupId)
fun createBookCacheManageIntent(context: Context): Intent {
return createLauncherIntent(context).apply {
putExtra(EXTRA_START_ROUTE, MainRouteConst.ROUTE_BOOK_CACHE_MANAGE)
}
}
fun createSearchIntent(
context: Context,
key: String? = null,
scopeRaw: String? = null
): Intent {
return createLauncherIntent(context).apply {
putExtra(EXTRA_START_ROUTE, MainRouteConst.ROUTE_SEARCH)
putExtra(EXTRA_SEARCH_KEY, key)
putExtra(EXTRA_SEARCH_SCOPE, scopeRaw)
}
}
fun createBookInfoIntent(
context: Context,
name: String? = null,
author: String? = null,
bookUrl: String
): Intent {
return createLauncherIntent(context).apply {
putExtra(EXTRA_START_ROUTE, MainRouteConst.ROUTE_BOOK_INFO)
putExtra(EXTRA_BOOK_NAME, name)
putExtra(EXTRA_BOOK_AUTHOR, author)
putExtra(EXTRA_BOOK_URL, bookUrl)
}
}
fun createExploreShowIntent(
context: Context,
exploreName: String? = null,
sourceUrl: String,
exploreUrl: String? = null
): Intent {
return createLauncherIntent(context).apply {
putExtra(EXTRA_START_ROUTE, MainRouteConst.ROUTE_EXPLORE_SHOW)
putExtra(EXTRA_EXPLORE_NAME, exploreName)
putExtra(EXTRA_SOURCE_URL, sourceUrl)
putExtra(EXTRA_EXPLORE_URL, exploreUrl)
}
}
private fun routeForConfigTag(configTag: String?): String {
return when (configTag) {
ConfigTag.OTHER_CONFIG -> MainRouteConst.ROUTE_SETTINGS_OTHER
ConfigTag.READ_CONFIG -> MainRouteConst.ROUTE_SETTINGS_READ
ConfigTag.COVER_CONFIG -> MainRouteConst.ROUTE_SETTINGS_COVER
ConfigTag.THEME_CONFIG -> MainRouteConst.ROUTE_SETTINGS_THEME
ConfigTag.BACKUP_CONFIG -> MainRouteConst.ROUTE_SETTINGS_BACKUP
ConfigTag.DOWNLOAD_CACHE_CONFIG -> MainRouteConst.ROUTE_SETTINGS_DOWNLOAD_CACHE
else -> MainRouteConst.ROUTE_SETTINGS
}
}
}
@@ -0,0 +1,423 @@
package io.legado.app.ui.main
import androidx.compose.animation.ExperimentalSharedTransitionApi
import androidx.compose.animation.SharedTransitionScope
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.togetherWith
import androidx.compose.runtime.LaunchedEffect
import androidx.lifecycle.lifecycleScope
import androidx.navigation3.runtime.NavKey
import androidx.navigation3.runtime.entryProvider
import androidx.navigation3.ui.LocalNavAnimatedContentScope
import androidx.navigation3.ui.NavDisplay
import io.legado.app.ui.book.cache.manage.BookCacheManageRouteScreen
import io.legado.app.ui.book.explore.ExploreShowScreen
import io.legado.app.ui.book.import.local.ImportBookScreen
import io.legado.app.ui.book.import.remote.RemoteBookScreen
import io.legado.app.ui.book.info.BookInfoRouteScreen
import io.legado.app.ui.book.info.BookInfoViewModel
import io.legado.app.ui.book.manage.BookshelfManageRouteScreen
import io.legado.app.ui.book.readRecord.ReadRecordOverviewScreen
import io.legado.app.ui.book.readRecord.ReadRecordScreen
import io.legado.app.ui.book.search.SearchIntent
import io.legado.app.ui.book.search.SearchScreen
import io.legado.app.ui.book.search.SearchViewModel
import io.legado.app.ui.book.source.manage.BookSourceActivity
import io.legado.app.ui.config.ConfigNavScreen
import io.legado.app.ui.config.backupConfig.BackupConfigScreen
import io.legado.app.ui.config.coverConfig.CoverConfigScreen
import io.legado.app.ui.config.customTheme.CustomThemeScreen
import io.legado.app.ui.config.downloadCacheConfig.DownloadCacheConfigScreen
import io.legado.app.ui.config.otherConfig.OtherConfigScreen
import io.legado.app.ui.config.readConfig.ReadConfigScreen
import io.legado.app.ui.config.themeConfig.ThemeConfigScreen
import io.legado.app.ui.config.themeManage.ThemeManageScreen
import io.legado.app.ui.rss.article.MainRouteRssSort
import io.legado.app.ui.rss.article.RssSortRouteScreen
import io.legado.app.ui.rss.favorites.RssFavoritesScreen
import io.legado.app.ui.rss.read.MainRouteRssRead
import io.legado.app.ui.rss.read.RssReadRouteScreen
import io.legado.app.ui.rss.subscription.RuleSubScreen
import io.legado.app.utils.startActivity
import io.legado.app.utils.startActivityForBook
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.koin.androidx.compose.koinViewModel
@OptIn(ExperimentalSharedTransitionApi::class)
fun MainActivity.mainEntryProvider(
backStack: MutableList<NavKey>,
useRail: Boolean,
sharedTransitionScope: SharedTransitionScope,
onNavigateToRoute: (NavKey) -> Unit,
onNavigateBack: () -> Unit,
onRegisterVariableSetter: (((String, String?) -> Unit)?) -> Unit
) = entryProvider {
entry<MainRouteHome> {
MainScreen(
useRail = useRail,
onOpenSettings = {
onNavigateToRoute(MainRouteSettings)
},
onNavigateToSearch = { key ->
onNavigateToRoute(
MainRouteSearch(
key = key?.trim()?.takeIf { it.isNotEmpty() }
)
)
},
onNavigateToRemoteImport = {
onNavigateToRoute(MainRouteImportRemote)
},
onNavigateToLocalImport = {
onNavigateToRoute(MainRouteImportLocal)
},
onNavigateToCache = { groupId ->
onNavigateToRoute(MainRouteCache(groupId))
},
onNavigateToBookCacheManage = {
onNavigateToRoute(MainRouteBookCacheManage)
},
onNavigateToBookInfo = { name, author, bookUrl ->
onNavigateToRoute(
MainRouteBookInfo(
name = name,
author = author,
bookUrl = bookUrl
)
)
},
onNavigateToExploreShow = { title, sourceUrl, exploreUrl ->
onNavigateToRoute(
MainRouteExploreShow(
title = title,
sourceUrl = sourceUrl,
exploreUrl = exploreUrl
)
)
},
onNavigateToRssSort = { sourceUrl, sortUrl, key ->
onNavigateToRoute(
MainRouteRssSort(
sourceUrl = sourceUrl,
sortUrl = sortUrl,
key = key
)
)
},
onNavigateToRssRead = { title, origin, link, openUrl ->
onNavigateToRoute(
MainRouteRssRead(
title = title,
origin = origin,
link = link,
openUrl = openUrl
)
)
},
onNavigateToRssFavorites = {
onNavigateToRoute(MainRouteRssFavorites)
},
onNavigateToRuleSub = {
onNavigateToRoute(MainRouteRuleSub)
},
onNavigateToReadRecord = {
onNavigateToRoute(MainRouteReadRecord)
},
sharedTransitionScope = sharedTransitionScope,
animatedVisibilityScope = LocalNavAnimatedContentScope.current,
)
}
entry<MainRouteSettings> {
ConfigNavScreen(
onBackClick = { onNavigateBack() },
onNavigateToOther = { backStack.add(MainRouteSettingsOther) },
onNavigateToRead = { backStack.add(MainRouteSettingsRead) },
onNavigateToCover = { backStack.add(MainRouteSettingsCover) },
onNavigateToTheme = { backStack.add(MainRouteSettingsTheme) },
onNavigateToBackup = { backStack.add(MainRouteSettingsBackup) },
onNavigateToDownloadCache = { backStack.add(MainRouteSettingsDownloadCache) }
)
}
entry<MainRouteSettingsOther> {
OtherConfigScreen(onBackClick = { onNavigateBack() })
}
entry<MainRouteSettingsRead> {
ReadConfigScreen(onBackClick = { onNavigateBack() })
}
entry<MainRouteSettingsCover> {
CoverConfigScreen(onBackClick = { onNavigateBack() })
}
entry<MainRouteSettingsTheme> {
ThemeConfigScreen(
onBackClick = { onNavigateBack() },
onNavigateToCustomTheme = { backStack.add(MainRouteSettingsCustomTheme) },
onNavigateToThemeManage = { backStack.add(MainRouteSettingsThemeManage) }
)
}
entry<MainRouteSettingsBackup> {
BackupConfigScreen(onBackClick = { onNavigateBack() })
}
entry<MainRouteSettingsDownloadCache> {
DownloadCacheConfigScreen(onBackClick = { onNavigateBack() })
}
entry<MainRouteSettingsCustomTheme> {
CustomThemeScreen(
onBackClick = { onNavigateBack() }
)
}
entry<MainRouteSettingsThemeManage> {
ThemeManageScreen(onBackClick = { onNavigateBack() })
}
entry<MainRouteImportLocal> {
ImportBookScreen(
onBackClick = { onNavigateBack() }
)
}
entry<MainRouteImportRemote> {
RemoteBookScreen(
onBackClick = { onNavigateBack() }
)
}
entry<MainRouteCache> { route ->
BookshelfManageRouteScreen(
groupId = route.groupId,
onBackClick = { onNavigateBack() },
onOpenBookInfo = { name, author, bookUrl ->
onNavigateToRoute(
MainRouteBookInfo(
name = name,
author = author,
bookUrl = bookUrl
)
)
}
)
}
entry<MainRouteBookCacheManage> {
BookCacheManageRouteScreen(
onBackClick = { onNavigateBack() }
)
}
entry<MainRouteSearch> { route ->
val searchViewModel = koinViewModel<SearchViewModel>()
LaunchedEffect(route.key, route.scopeRaw, searchViewModel) {
searchViewModel.onIntent(
SearchIntent.Initialize(
key = route.key,
scopeRaw = route.scopeRaw
)
)
}
SearchScreen(
viewModel = searchViewModel,
onBack = {
searchViewModel.onIntent(SearchIntent.ClearSearchResults)
onNavigateBack()
},
onOpenBookInfo = { name, author, bookUrl ->
onNavigateToRoute(
MainRouteBookInfo(
name = name,
author = author,
bookUrl = bookUrl
)
)
},
onOpenSourceManage = {
this@mainEntryProvider.startActivity<BookSourceActivity>()
},
sharedTransitionScope = sharedTransitionScope,
animatedVisibilityScope = LocalNavAnimatedContentScope.current,
)
}
entry<MainRouteRssSort> { route ->
RssSortRouteScreen(
sourceUrl = route.sourceUrl,
initialSortUrl = route.sortUrl,
onBackClick = { onNavigateBack() },
onOpenRead = { title, origin, link, openUrl ->
if (link?.contains("@js:") == true) {
onNavigateToRoute(
MainRouteRssSort(
sourceUrl = origin,
sortUrl = link
)
)
} else {
onNavigateToRoute(
MainRouteRssRead(
title = title,
origin = origin,
link = link,
openUrl = openUrl
)
)
}
}
)
}
entry<MainRouteRssRead> { route ->
RssReadRouteScreen(
title = route.title,
origin = route.origin,
link = route.link,
openUrl = route.openUrl,
onBackClick = { onNavigateBack() }
)
}
entry<MainRouteRssFavorites> {
RssFavoritesScreen(
onBackClick = { onNavigateBack() },
onOpenRead = { title, origin, link, openUrl ->
onNavigateToRoute(
MainRouteRssRead(
title = title,
origin = origin,
link = link,
openUrl = openUrl
)
)
}
)
}
entry<MainRouteRuleSub> {
RuleSubScreen(
onBackClick = { onNavigateBack() }
)
}
entry<MainRouteReadRecord> {
ReadRecordScreen(
onBackClick = { onNavigateBack() },
onBookClick = { name, author ->
lifecycleScope.launch {
val book = withContext(IO) {
io.legado.app.data.appDb.bookDao.getBook(name, author)
}
if (book != null) this@mainEntryProvider.startActivityForBook(book)
else {
onNavigateToRoute(MainRouteSearch(key = name))
}
}
},
onSummaryClick = {
onNavigateToRoute(MainRouteReadRecordOverview)
}
)
}
entry<MainRouteReadRecordOverview> {
ReadRecordOverviewScreen(
onBackClick = { onNavigateBack() },
onBookClick = { name, author ->
lifecycleScope.launch {
val book = withContext(IO) {
io.legado.app.data.appDb.bookDao.getBook(name, author)
}
if (book != null) this@mainEntryProvider.startActivityForBook(book)
else {
onNavigateToRoute(MainRouteSearch(key = name))
}
}
}
)
}
entry<MainRouteBookInfo>(
metadata = NavDisplay.transitionSpec {
val from = initialState.key
val fromStr = from.toString()
if (from is MainRouteHome || from is MainRouteExploreShow || from is MainRouteSearch ||
fromStr.startsWith("MainRouteHome") || fromStr.startsWith("MainRouteExploreShow") || fromStr.startsWith(
"MainRouteSearch"
)
) {
fadeIn(animationSpec = tween(300)) togetherWith
fadeOut(animationSpec = tween(300))
} else null
} + NavDisplay.popTransitionSpec {
val to = targetState.key
val toStr = to.toString()
if (to is MainRouteHome || to is MainRouteExploreShow || to is MainRouteSearch ||
toStr.startsWith("MainRouteHome") || toStr.startsWith("MainRouteExploreShow") || toStr.startsWith(
"MainRouteSearch"
)
) {
fadeIn(animationSpec = tween(300)) togetherWith
fadeOut(animationSpec = tween(300))
} else null
} + NavDisplay.predictivePopTransitionSpec { _ ->
val to = targetState.key
val toStr = to.toString()
if (to is MainRouteHome || to is MainRouteExploreShow || to is MainRouteSearch ||
toStr.startsWith("MainRouteHome") || toStr.startsWith("MainRouteExploreShow") || toStr.startsWith(
"MainRouteSearch"
)
) {
fadeIn(animationSpec = tween(300)) togetherWith
fadeOut(animationSpec = tween(300))
} else null
}
) { route ->
val bookInfoViewModel = koinViewModel<BookInfoViewModel>()
BookInfoRouteScreen(
bookUrl = route.bookUrl,
viewModel = bookInfoViewModel,
onBack = { onNavigateBack() },
onFinish = { _, _ -> onNavigateBack() },
onOpenSearch = { keyword ->
onNavigateToRoute(MainRouteSearch(key = keyword))
},
sharedTransitionScope = sharedTransitionScope,
animatedVisibilityScope = LocalNavAnimatedContentScope.current,
sharedCoverKey = bookCoverSharedElementKey(route.bookUrl),
onRegisterVariableSetter = { setter ->
onRegisterVariableSetter(setter)
}
)
}
entry<MainRouteExploreShow> { route ->
ExploreShowScreen(
title = route.title ?: "探索",
sourceUrl = route.sourceUrl,
exploreUrl = route.exploreUrl,
onBack = { onNavigateBack() },
onBookClick = { book ->
onNavigateToRoute(
MainRouteBookInfo(
name = book.name,
author = book.author,
bookUrl = book.bookUrl
)
)
},
sharedTransitionScope = sharedTransitionScope,
animatedVisibilityScope = LocalNavAnimatedContentScope.current,
)
}
}
@@ -0,0 +1,106 @@
package io.legado.app.ui.main
import androidx.navigation3.runtime.NavKey
import kotlinx.serialization.Serializable
@Serializable
sealed interface MainRoute : NavKey
@Serializable
data object MainRouteHome : MainRoute
@Serializable
data object MainRouteSettings : MainRoute
@Serializable
data object MainRouteSettingsOther : MainRoute
@Serializable
data object MainRouteSettingsRead : MainRoute
@Serializable
data object MainRouteSettingsCover : MainRoute
@Serializable
data object MainRouteSettingsTheme : MainRoute
@Serializable
data object MainRouteSettingsBackup : MainRoute
@Serializable
data object MainRouteSettingsCustomTheme : MainRoute
@Serializable
data object MainRouteSettingsThemeManage : MainRoute
@Serializable
data object MainRouteSettingsDownloadCache : MainRoute
@Serializable
data object MainRouteImportLocal : MainRoute
@Serializable
data object MainRouteImportRemote : MainRoute
@Serializable
data object MainRouteReadRecord : MainRoute
@Serializable
data object MainRouteReadRecordOverview : MainRoute
@Serializable
data class MainRouteCache(val groupId: Long) : MainRoute
@Serializable
data object MainRouteBookCacheManage : MainRoute
@Serializable
data class MainRouteSearch(
val key: String?,
val scopeRaw: String? = null
) : MainRoute
@Serializable
data class MainRouteBookInfo(
val name: String?,
val author: String?,
val bookUrl: String,
) : MainRoute
@Serializable
data object MainRouteRssFavorites : MainRoute
@Serializable
data object MainRouteRuleSub : MainRoute
@Serializable
data class MainRouteExploreShow(
val title: String?,
val sourceUrl: String,
val exploreUrl: String?,
) : MainRoute
object MainRouteConst {
const val ROUTE_MAIN = "main"
const val ROUTE_SETTINGS = "settings"
const val ROUTE_SETTINGS_OTHER = "settings/other"
const val ROUTE_SETTINGS_READ = "settings/read"
const val ROUTE_SETTINGS_COVER = "settings/cover"
const val ROUTE_SETTINGS_THEME = "settings/theme"
const val ROUTE_SETTINGS_BACKUP = "settings/backup"
const val ROUTE_SETTINGS_CUSTOM_THEME = "settings/custom_theme"
const val ROUTE_SETTINGS_DOWNLOAD_CACHE = "settings/download_cache"
const val ROUTE_IMPORT_LOCAL = "import/local"
const val ROUTE_IMPORT_REMOTE = "import/remote"
const val ROUTE_CACHE = "cache"
const val ROUTE_BOOK_CACHE_MANAGE = "book/cache/manage"
const val ROUTE_SEARCH = "search"
const val ROUTE_BOOK_INFO = "book/info"
const val ROUTE_EXPLORE_SHOW = "explore/show"
const val ROUTE_RSS_SORT = "rss/sort"
const val ROUTE_RSS_READ = "rss/read"
const val ROUTE_RSS_FAVORITES = "rss/favorites"
const val ROUTE_RULE_SUB = "rss/rule_sub"
const val ROUTE_READ_RECORD = "read_record"
const val ROUTE_READ_RECORD_OVERVIEW = "read_record_overview"
}
@@ -0,0 +1,253 @@
package io.legado.app.ui.main
import android.app.Activity
import android.content.Intent
import androidx.navigation3.runtime.NavKey
import io.legado.app.ui.rss.article.MainRouteRssSort
import io.legado.app.ui.rss.read.MainRouteRssRead
object MainNavigator {
fun navigateToRoute(backStack: MutableList<NavKey>, route: NavKey) {
val currentRoute = backStack.lastOrNull()
if (currentRoute == route) return
when (route) {
MainRouteHome -> {
backStack.clear()
backStack.add(MainRouteHome)
}
MainRouteSettings -> {
if (currentRoute == MainRouteHome) {
backStack.add(MainRouteSettings)
} else {
backStack.clear()
backStack.add(MainRouteHome)
backStack.add(MainRouteSettings)
}
}
MainRouteSettingsOther,
MainRouteSettingsRead,
MainRouteSettingsCover,
MainRouteSettingsTheme,
MainRouteSettingsBackup,
MainRouteSettingsCustomTheme,
MainRouteSettingsThemeManage,
MainRouteSettingsDownloadCache -> {
backStack.clear()
backStack.add(MainRouteHome)
backStack.add(MainRouteSettings)
backStack.add(route)
}
MainRouteImportLocal,
MainRouteImportRemote,
is MainRouteCache,
MainRouteBookCacheManage -> {
if (currentRoute == MainRouteHome) {
backStack.add(route)
} else {
backStack.clear()
backStack.add(MainRouteHome)
backStack.add(route)
}
}
is MainRouteSearch -> {
if (
currentRoute == MainRouteHome ||
currentRoute is MainRouteBookInfo ||
currentRoute is MainRouteExploreShow ||
currentRoute is MainRouteSearch
) {
backStack.add(route)
} else {
backStack.clear()
backStack.add(MainRouteHome)
backStack.add(route)
}
}
is MainRouteBookInfo -> {
if (
currentRoute == MainRouteHome ||
currentRoute is MainRouteSearch ||
currentRoute is MainRouteExploreShow ||
currentRoute is MainRouteBookInfo
) {
backStack.add(route)
} else {
backStack.clear()
backStack.add(MainRouteHome)
backStack.add(route)
}
}
is MainRouteExploreShow -> {
if (
currentRoute == MainRouteHome ||
currentRoute is MainRouteBookInfo ||
currentRoute is MainRouteSearch ||
currentRoute is MainRouteExploreShow
) {
backStack.add(route)
} else {
backStack.clear()
backStack.add(MainRouteHome)
backStack.add(route)
}
}
is MainRouteRssSort -> {
if (
currentRoute == MainRouteHome ||
currentRoute is MainRouteRssSort ||
currentRoute is MainRouteRssRead
) {
backStack.add(route)
} else {
backStack.clear()
backStack.add(MainRouteHome)
backStack.add(route)
}
}
is MainRouteRssRead -> {
if (
currentRoute == MainRouteHome ||
currentRoute is MainRouteRssSort ||
currentRoute is MainRouteRssRead
) {
backStack.add(route)
} else {
backStack.clear()
backStack.add(MainRouteHome)
backStack.add(route)
}
}
MainRouteReadRecord -> {
if (currentRoute == MainRouteHome) {
backStack.add(route)
} else {
backStack.clear()
backStack.add(MainRouteHome)
backStack.add(route)
}
}
MainRouteReadRecordOverview -> {
if (currentRoute == MainRouteHome || currentRoute == MainRouteReadRecord) {
backStack.add(route)
} else {
backStack.clear()
backStack.add(MainRouteHome)
backStack.add(route)
}
}
}
}
fun navigateBack(activity: Activity, backStack: MutableList<NavKey>) {
if (backStack.size > 1) {
backStack.removeLastOrNull()
} else {
activity.finish()
}
}
fun resolveStartRoute(intent: Intent?): NavKey {
val route = intent?.getStringExtra(MainIntent.EXTRA_START_ROUTE)
resolveRssStartRoute(route, intent)?.let { return it }
return resolveStartRoute(route, intent)
}
private fun resolveRssStartRoute(route: String?, intent: Intent?): NavKey? {
return when (route) {
MainRouteConst.ROUTE_RSS_SORT -> {
val sourceUrl = intent?.getStringExtra(MainIntent.EXTRA_RSS_SOURCE_URL)
if (sourceUrl.isNullOrBlank()) {
null
} else {
MainRouteRssSort(
sourceUrl = sourceUrl,
sortUrl = intent.getStringExtra(MainIntent.EXTRA_RSS_SORT_URL),
key = intent.getStringExtra(MainIntent.EXTRA_RSS_KEY)
)
}
}
MainRouteConst.ROUTE_RSS_READ -> {
val origin = intent?.getStringExtra(MainIntent.EXTRA_RSS_READ_ORIGIN)
if (origin.isNullOrBlank()) {
null
} else {
MainRouteRssRead(
title = intent.getStringExtra(MainIntent.EXTRA_RSS_READ_TITLE),
origin = origin,
link = intent.getStringExtra(MainIntent.EXTRA_RSS_READ_LINK),
openUrl = intent.getStringExtra(MainIntent.EXTRA_RSS_READ_OPEN_URL)
)
}
}
MainRouteConst.ROUTE_RSS_FAVORITES -> MainRouteRssFavorites
MainRouteConst.ROUTE_RULE_SUB -> MainRouteRuleSub
else -> null
}
}
private fun resolveStartRoute(route: String?, intent: Intent?): MainRoute {
return when (route) {
MainRouteConst.ROUTE_MAIN -> MainRouteHome
MainRouteConst.ROUTE_SETTINGS -> MainRouteSettings
MainRouteConst.ROUTE_SETTINGS_OTHER -> MainRouteSettingsOther
MainRouteConst.ROUTE_SETTINGS_READ -> MainRouteSettingsRead
MainRouteConst.ROUTE_SETTINGS_COVER -> MainRouteSettingsCover
MainRouteConst.ROUTE_SETTINGS_THEME -> MainRouteSettingsTheme
MainRouteConst.ROUTE_SETTINGS_BACKUP -> MainRouteSettingsBackup
MainRouteConst.ROUTE_SETTINGS_CUSTOM_THEME -> MainRouteSettingsCustomTheme
MainRouteConst.ROUTE_SETTINGS_DOWNLOAD_CACHE -> MainRouteSettingsDownloadCache
MainRouteConst.ROUTE_IMPORT_LOCAL -> MainRouteImportLocal
MainRouteConst.ROUTE_IMPORT_REMOTE -> MainRouteImportRemote
MainRouteConst.ROUTE_CACHE -> MainRouteCache(
intent?.getLongExtra(
MainIntent.EXTRA_CACHE_GROUP_ID,
-1L
) ?: -1L
)
MainRouteConst.ROUTE_BOOK_CACHE_MANAGE -> MainRouteBookCacheManage
MainRouteConst.ROUTE_SEARCH -> MainRouteSearch(
key = intent?.getStringExtra(MainIntent.EXTRA_SEARCH_KEY),
scopeRaw = intent?.getStringExtra(MainIntent.EXTRA_SEARCH_SCOPE)
)
MainRouteConst.ROUTE_BOOK_INFO -> intent?.getStringExtra(MainIntent.EXTRA_BOOK_URL)
?.takeIf { it.isNotBlank() }
?.let { bookUrl ->
MainRouteBookInfo(
name = intent.getStringExtra(MainIntent.EXTRA_BOOK_NAME),
author = intent.getStringExtra(MainIntent.EXTRA_BOOK_AUTHOR),
bookUrl = bookUrl
)
} ?: MainRouteHome
MainRouteConst.ROUTE_EXPLORE_SHOW -> intent?.getStringExtra(MainIntent.EXTRA_SOURCE_URL)
?.takeIf { it.isNotBlank() }
?.let { sourceUrl ->
MainRouteExploreShow(
title = intent.getStringExtra(MainIntent.EXTRA_EXPLORE_NAME),
sourceUrl = sourceUrl,
exploreUrl = intent.getStringExtra(MainIntent.EXTRA_EXPLORE_URL)
)
} ?: MainRouteHome
else -> MainRouteHome
}
}
}
@@ -113,6 +113,8 @@ fun MainScreen(
onNavigateToExploreShow: (title: String?, sourceUrl: String, exploreUrl: String?) -> Unit, onNavigateToExploreShow: (title: String?, sourceUrl: String, exploreUrl: String?) -> Unit,
onNavigateToRssSort: (sourceUrl: String, sortUrl: String?, key: String?) -> Unit, onNavigateToRssSort: (sourceUrl: String, sortUrl: String?, key: String?) -> Unit,
onNavigateToRssRead: (title: String?, origin: String, link: String?, openUrl: String?) -> Unit, onNavigateToRssRead: (title: String?, origin: String, link: String?, openUrl: String?) -> Unit,
onNavigateToRssFavorites: () -> Unit,
onNavigateToRuleSub: () -> Unit,
onNavigateToReadRecord: () -> Unit, onNavigateToReadRecord: () -> Unit,
sharedTransitionScope: SharedTransitionScope? = null, sharedTransitionScope: SharedTransitionScope? = null,
animatedVisibilityScope: AnimatedVisibilityScope? = null, animatedVisibilityScope: AnimatedVisibilityScope? = null,
@@ -383,7 +385,9 @@ fun MainScreen(
}, },
onOpenRead = { title, origin, link, openUrl -> onOpenRead = { title, origin, link, openUrl ->
onNavigateToRssRead(title, origin, link, openUrl) onNavigateToRssRead(title, origin, link, openUrl)
} },
onOpenFavorites = onNavigateToRssFavorites,
onOpenRuleSub = onNavigateToRuleSub
) )
MainDestination.My -> MyScreen( MainDestination.My -> MyScreen(
onOpenSettings = onOpenSettings, onOpenSettings = onOpenSettings,
@@ -26,7 +26,6 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@@ -36,12 +35,12 @@ import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shadow import androidx.compose.ui.graphics.Shadow
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.text.withStyle import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.legado.app.R import io.legado.app.R
@@ -49,13 +48,11 @@ import io.legado.app.constant.BookType
import io.legado.app.ui.config.bookshelfConfig.BookshelfConfig import io.legado.app.ui.config.bookshelfConfig.BookshelfConfig
import io.legado.app.ui.config.themeConfig.ThemeConfig import io.legado.app.ui.config.themeConfig.ThemeConfig
import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.theme.LegadoTheme
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.NormalCard
import io.legado.app.ui.widget.components.card.TextCard import io.legado.app.ui.widget.components.card.TextCard
import io.legado.app.ui.widget.components.cover.CoilBookCover
import io.legado.app.ui.widget.components.cover.BookshelfCover import io.legado.app.ui.widget.components.cover.BookshelfCover
import io.legado.app.ui.widget.components.cover.CoilBookCover
import io.legado.app.ui.widget.components.icon.AppIcon import io.legado.app.ui.widget.components.icon.AppIcon
import io.legado.app.ui.widget.components.icon.AppIcons
import io.legado.app.ui.widget.components.text.AppText import io.legado.app.ui.widget.components.text.AppText
import io.legado.app.utils.splitNotBlank import io.legado.app.utils.splitNotBlank
import io.legado.app.utils.toTimeAgo import io.legado.app.utils.toTimeAgo
@@ -90,10 +87,11 @@ fun BookshelfItem(
onClick: () -> Unit, onClick: () -> Unit,
onLongClick: (() -> Unit)? onLongClick: (() -> Unit)?
) { ) {
val containerColor = if (!isGrid && BookshelfConfig.bookshelfCardColor != 0) { val isDark = LegadoTheme.isDark
Color(BookshelfConfig.bookshelfCardColor) val bookshelfCardColor =
} else if (ThemeConfig.enableDeepPersonalization && ThemeConfig.secondaryThemeColor != 0) { if (isDark) BookshelfConfig.bookshelfCardColorDark else BookshelfConfig.bookshelfCardColor
Color(ThemeConfig.secondaryThemeColor) val containerColor = if (!isGrid && bookshelfCardColor != 0) {
Color(bookshelfCardColor)
} else { } else {
LegadoTheme.colorScheme.cardContainer LegadoTheme.colorScheme.cardContainer
} }
@@ -189,7 +187,7 @@ fun BookshelfItem(
Box( Box(
modifier = Modifier modifier = Modifier
.align(Alignment.Top) .align(Alignment.Top)
.width(if (!isCompact) 80.dp else 56.dp) .width(if (!isCompact) 84.dp else 56.dp)
.padding(end = 8.dp) .padding(end = 8.dp)
) { ) {
Box( Box(
@@ -209,11 +207,13 @@ fun BookshelfItem(
} }
} }
Column( Column(
modifier = Modifier.weight(1f).padding(top = 8.dp, bottom = 8.dp, end = 8.dp), modifier = Modifier
.weight(1f)
.padding(top = 8.dp, bottom = 8.dp, end = 8.dp),
verticalArrangement = Arrangement.Center verticalArrangement = Arrangement.Center
) { ) {
Row( Row(
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.Top
) { ) {
AppText( AppText(
text = title, text = title,
@@ -222,11 +222,15 @@ fun BookshelfItem(
} else { } else {
LegadoTheme.typography.titleMediumEmphasized LegadoTheme.typography.titleMediumEmphasized
}, },
maxLines = 1, maxLines = BookshelfConfig.bookshelfTitleMaxLines,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
modifier = Modifier.weight(1f) modifier = Modifier.weight(1f)
) )
titleEnd?.invoke() titleEnd?.let {
Box(modifier = Modifier.padding(top = 4.dp)) {
it.invoke()
}
}
} }
subTitle?.let { subTitle?.let {
AppText( AppText(
@@ -296,7 +300,20 @@ fun BookGroupCover(
modifier = Modifier.fillMaxSize() modifier = Modifier.fillMaxSize()
) )
} else { } else {
Column(modifier = Modifier.fillMaxSize()) { Box(
modifier = Modifier.run {
if (BookshelfConfig.bookshelfCoverShadow) {
background(LegadoTheme.colorScheme.surface)
} else {
this
}
}
) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 1.dp),
) {
Row(modifier = Modifier.weight(1f)) { Row(modifier = Modifier.weight(1f)) {
Box( Box(
modifier = Modifier modifier = Modifier
@@ -363,6 +380,7 @@ fun BookGroupCover(
} }
} }
} }
}
if (!leftBottomText.isNullOrEmpty()) { if (!leftBottomText.isNullOrEmpty()) {
TextCard( TextCard(
@@ -482,13 +500,16 @@ fun BookGroupItemHorizontalCovers(
onBookClick: ((BookShelfItem) -> Unit)? = null onBookClick: ((BookShelfItem) -> Unit)? = null
) { ) {
Column { Column {
val isDark = LegadoTheme.isDark
val bookshelfCardColor =
if (isDark) BookshelfConfig.bookshelfCardColorDark else BookshelfConfig.bookshelfCardColor
NormalCard( NormalCard(
modifier = modifier modifier = modifier
.fillMaxWidth() .fillMaxWidth()
.padding(all = 4.dp), .padding(all = 4.dp),
cornerRadius = 12.dp, cornerRadius = 12.dp,
containerColor = if (BookshelfConfig.bookshelfCardColor != 0) { containerColor = if (bookshelfCardColor != 0) {
Color(BookshelfConfig.bookshelfCardColor) Color(bookshelfCardColor)
} else { } else {
LegadoTheme.colorScheme.cardContainer LegadoTheme.colorScheme.cardContainer
}, },
@@ -634,7 +655,9 @@ fun BookItem(
path = book.getDisplayCover(), path = book.getDisplayCover(),
isUpdating = isUpdating, isUpdating = isUpdating,
modifier = modifier, modifier = modifier,
coverModifier = Modifier.fillMaxWidth().aspectRatio(5f / 7f), coverModifier = Modifier
.fillMaxWidth()
.aspectRatio(5f / 7f),
sourceOrigin = book.origin, sourceOrigin = book.origin,
badgeText = if (layoutMode != 0) unreadText else null, badgeText = if (layoutMode != 0) unreadText else null,
showBadgeDot = BookshelfConfig.showUnread && BookshelfConfig.showUnreadNew && book.isNew, showBadgeDot = BookshelfConfig.showUnread && BookshelfConfig.showUnreadNew && book.isNew,
@@ -3,11 +3,16 @@ package io.legado.app.ui.main.bookshelf
import android.content.res.Configuration import android.content.res.Configuration
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.animateContentSize import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
@@ -17,6 +22,8 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.res.stringArrayResource import androidx.compose.ui.res.stringArrayResource
@@ -27,8 +34,8 @@ import io.legado.app.ui.config.bookshelfConfig.BookshelfConfig
import io.legado.app.ui.config.themeConfig.LabelColorManageSheet import io.legado.app.ui.config.themeConfig.LabelColorManageSheet
import io.legado.app.ui.config.themeConfig.ThemeConfig import io.legado.app.ui.config.themeConfig.ThemeConfig
import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.theme.LegadoTheme
import io.legado.app.ui.widget.components.card.GlassCard
import io.legado.app.ui.widget.components.dialog.ColorPickerSheet import io.legado.app.ui.widget.components.dialog.ColorPickerSheet
import io.legado.app.ui.widget.components.divider.PillDivider
import io.legado.app.ui.widget.components.modalBottomSheet.AppModalBottomSheet import io.legado.app.ui.widget.components.modalBottomSheet.AppModalBottomSheet
import io.legado.app.ui.widget.components.settingItem.CompactClickableSettingItem import io.legado.app.ui.widget.components.settingItem.CompactClickableSettingItem
import io.legado.app.ui.widget.components.settingItem.CompactDropdownSettingItem import io.legado.app.ui.widget.components.settingItem.CompactDropdownSettingItem
@@ -45,15 +52,13 @@ fun BookshelfConfigSheet(
val isLandscape = configuration.orientation == Configuration.ORIENTATION_LANDSCAPE val isLandscape = configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
var showLabelColorManage by remember { mutableStateOf(false) } var showLabelColorManage by remember { mutableStateOf(false) }
var showColorPicker by remember { mutableStateOf(false) } var showColorPicker by remember { mutableStateOf(false) }
var showColorPickerDark by remember { mutableStateOf(false) }
AppModalBottomSheet( AppModalBottomSheet(
title = stringResource(R.string.bookshelf_layout), title = stringResource(R.string.bookshelf_layout),
show = show, show = show,
onDismissRequest = onDismissRequest onDismissRequest = onDismissRequest
) { ) {
GlassCard() {
}
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@@ -99,21 +104,12 @@ fun BookshelfConfigSheet(
if (isLandscape) BookshelfConfig.bookshelfFolderLayoutModeLandscape if (isLandscape) BookshelfConfig.bookshelfFolderLayoutModeLandscape
else BookshelfConfig.bookshelfFolderLayoutModePortrait else BookshelfConfig.bookshelfFolderLayoutModePortrait
CompactDropdownSettingItem(
title = stringResource(R.string.layout_mode),
description = stringResource(if (isLandscape) R.string.screen_landscape else R.string.screen_portrait),
selectedValue = layoutMode.toString(),
displayEntries = arrayOf(stringResource(R.string.layout_mode_list),stringResource(R.string.layout_mode_grid)),
entryValues = arrayOf("0", "1"),
onValueChange = {
if (isLandscape) BookshelfConfig.bookshelfLayoutModeLandscape = it.toInt()
else BookshelfConfig.bookshelfLayoutModePortrait = it.toInt()
}
)
// Folder Layout Mode // Folder Layout Mode
AnimatedVisibility(visible = BookshelfConfig.bookGroupStyle == 2) { AnimatedVisibility(visible = BookshelfConfig.bookGroupStyle == 2) {
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
PillDivider()
CompactDropdownSettingItem( CompactDropdownSettingItem(
title = "文件夹布局模式", title = "文件夹布局模式",
description = stringResource(if (isLandscape) R.string.screen_landscape else R.string.screen_portrait), description = stringResource(if (isLandscape) R.string.screen_landscape else R.string.screen_portrait),
@@ -157,8 +153,6 @@ fun BookshelfConfigSheet(
} }
) )
} }
}
}
AnimatedVisibility( AnimatedVisibility(
visible = BookshelfConfig.bookGroupStyle == 2 && folderLayoutMode == 0 visible = BookshelfConfig.bookGroupStyle == 2 && folderLayoutMode == 0
@@ -171,7 +165,9 @@ fun BookshelfConfigSheet(
selectedValue = BookshelfConfig.bookshelfGroupListStyle.toString(), selectedValue = BookshelfConfig.bookshelfGroupListStyle.toString(),
displayEntries = arrayOf("默认", "紧凑", "横排封面"), displayEntries = arrayOf("默认", "紧凑", "横排封面"),
entryValues = arrayOf("0", "1", "2"), entryValues = arrayOf("0", "1", "2"),
onValueChange = { BookshelfConfig.bookshelfGroupListStyle = it.toInt() } onValueChange = {
BookshelfConfig.bookshelfGroupListStyle = it.toInt()
}
) )
AnimatedVisibility(visible = BookshelfConfig.bookshelfGroupListStyle == 2) { AnimatedVisibility(visible = BookshelfConfig.bookshelfGroupListStyle == 2) {
CompactSliderSettingItem( CompactSliderSettingItem(
@@ -179,12 +175,33 @@ fun BookshelfConfigSheet(
value = BookshelfConfig.bookshelfGroupCoverCount.toFloat(), value = BookshelfConfig.bookshelfGroupCoverCount.toFloat(),
valueRange = 1f..10f, valueRange = 1f..10f,
steps = 9, steps = 9,
onValueChange = { BookshelfConfig.bookshelfGroupCoverCount = it.toInt() } onValueChange = {
BookshelfConfig.bookshelfGroupCoverCount = it.toInt()
}
) )
} }
} }
} }
PillDivider()
}
}
CompactDropdownSettingItem(
title = stringResource(R.string.layout_mode),
description = stringResource(if (isLandscape) R.string.screen_landscape else R.string.screen_portrait),
selectedValue = layoutMode.toString(),
displayEntries = arrayOf(
stringResource(R.string.layout_mode_list),
stringResource(R.string.layout_mode_grid)
),
entryValues = arrayOf("0", "1"),
onValueChange = {
if (isLandscape) BookshelfConfig.bookshelfLayoutModeLandscape = it.toInt()
else BookshelfConfig.bookshelfLayoutModePortrait = it.toInt()
}
)
AnimatedVisibility( AnimatedVisibility(
visible = layoutMode == 1 visible = layoutMode == 1
) { ) {
@@ -243,17 +260,47 @@ fun BookshelfConfigSheet(
) )
CompactClickableSettingItem( CompactClickableSettingItem(
title = "卡片背景颜色", title = "日间卡片背景颜色",
color = LegadoTheme.colorScheme.surface, color = LegadoTheme.colorScheme.surface,
onClick = { showColorPicker = true } onClick = { showColorPicker = true },
trailingContent = {
if (BookshelfConfig.bookshelfCardColor != 0) {
Box(
modifier = Modifier
.size(20.dp)
.clip(CircleShape)
.background(Color(BookshelfConfig.bookshelfCardColor))
.border(
1.dp,
MaterialTheme.colorScheme.outlineVariant,
CircleShape
)
)
}
}
) )
val isHorizontalCovers = BookshelfConfig.bookGroupStyle == 2 && BookshelfConfig.bookshelfGroupListStyle == 2 CompactClickableSettingItem(
title = "夜间卡片背景颜色",
color = LegadoTheme.colorScheme.surface,
onClick = { showColorPickerDark = true },
trailingContent = {
if (BookshelfConfig.bookshelfCardColorDark != 0) {
Box(
modifier = Modifier
.size(20.dp)
.clip(CircleShape)
.background(Color(BookshelfConfig.bookshelfCardColorDark))
.border(
1.dp,
MaterialTheme.colorScheme.outlineVariant,
CircleShape
)
)
}
}
)
AnimatedVisibility(visible = !isHorizontalCovers) {
Column(
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
if (BookshelfConfig.bookGroupStyle != 2) { if (BookshelfConfig.bookGroupStyle != 2) {
CompactSwitchSettingItem( CompactSwitchSettingItem(
title = stringResource(R.string.compact_mode), title = stringResource(R.string.compact_mode),
@@ -292,7 +339,9 @@ fun BookshelfConfigSheet(
title = "显示最新章节", title = "显示最新章节",
checked = BookshelfConfig.bookshelfShowLatestChapter, checked = BookshelfConfig.bookshelfShowLatestChapter,
color = LegadoTheme.colorScheme.surface, color = LegadoTheme.colorScheme.surface,
onCheckedChange = { BookshelfConfig.bookshelfShowLatestChapter = it } onCheckedChange = {
BookshelfConfig.bookshelfShowLatestChapter = it
}
) )
CompactSwitchSettingItem( CompactSwitchSettingItem(
@@ -310,7 +359,9 @@ fun BookshelfConfigSheet(
value = BookshelfConfig.bookshelfIntroMaxLines.toFloat(), value = BookshelfConfig.bookshelfIntroMaxLines.toFloat(),
valueRange = 0f..10f, valueRange = 0f..10f,
steps = 10, steps = 10,
onValueChange = { BookshelfConfig.bookshelfIntroMaxLines = it.toInt() } onValueChange = {
BookshelfConfig.bookshelfIntroMaxLines = it.toInt()
}
) )
} }
CompactSwitchSettingItem( CompactSwitchSettingItem(
@@ -344,8 +395,8 @@ fun BookshelfConfigSheet(
} }
} }
} }
}
}
CompactSliderSettingItem( CompactSliderSettingItem(
title = stringResource(R.string.max_title_lines), title = stringResource(R.string.max_title_lines),
@@ -448,5 +499,12 @@ fun BookshelfConfigSheet(
onDismissRequest = { showColorPicker = false }, onDismissRequest = { showColorPicker = false },
onColorSelected = { BookshelfConfig.bookshelfCardColor = it } onColorSelected = { BookshelfConfig.bookshelfCardColor = it }
) )
ColorPickerSheet(
show = showColorPickerDark,
initialColor = if (BookshelfConfig.bookshelfCardColorDark != 0) BookshelfConfig.bookshelfCardColorDark else LegadoTheme.colorScheme.surfaceVariant.toArgb(),
onDismissRequest = { showColorPickerDark = false },
onColorSelected = { BookshelfConfig.bookshelfCardColorDark = it }
)
} }
} }
@@ -778,7 +778,7 @@ fun BookshelfScreen(
), ),
contentPadding = adaptiveContentPaddingBookshelf( contentPadding = adaptiveContentPaddingBookshelf(
top = paddingValues.calculateTopPadding(), top = paddingValues.calculateTopPadding(),
bottom = if (ThemeConfig.useFloatingBottomBar) 120.dp else 8.dp, bottom = if (ThemeConfig.useFloatingBottomBar || ThemeConfig.enableBlur) 120.dp else 8.dp,
horizontal = if (isGridMode) 8.dp else 4.dp horizontal = if (isGridMode) 8.dp else 4.dp
), ),
verticalArrangement = Arrangement.spacedBy(if (isGridMode) 8.dp else 0.dp), verticalArrangement = Arrangement.spacedBy(if (isGridMode) 8.dp else 0.dp),
@@ -1342,7 +1342,7 @@ fun BookshelfPage(
), ),
contentPadding = adaptiveContentPaddingBookshelf( contentPadding = adaptiveContentPaddingBookshelf(
top = paddingValues.calculateTopPadding(), top = paddingValues.calculateTopPadding(),
bottom = if (ThemeConfig.useFloatingBottomBar) 120.dp else 8.dp, bottom = if (ThemeConfig.useFloatingBottomBar || ThemeConfig.enableBlur) 120.dp else 8.dp,
horizontal = if (isGridMode) 8.dp else 4.dp horizontal = if (isGridMode) 8.dp else 4.dp
), ),
verticalArrangement = Arrangement.spacedBy(if (isGridMode) 8.dp else 0.dp), verticalArrangement = Arrangement.spacedBy(if (isGridMode) 8.dp else 0.dp),
@@ -45,10 +45,8 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import io.legado.app.R import io.legado.app.R
import io.legado.app.data.entities.RssSource import io.legado.app.data.entities.RssSource
import io.legado.app.ui.login.SourceLoginActivity import io.legado.app.ui.login.SourceLoginActivity
import io.legado.app.ui.rss.favorites.RssFavoritesActivity
import io.legado.app.ui.rss.source.edit.RssSourceEditActivity import io.legado.app.ui.rss.source.edit.RssSourceEditActivity
import io.legado.app.ui.rss.source.manage.RssSourceActivity import io.legado.app.ui.rss.source.manage.RssSourceActivity
import io.legado.app.ui.rss.subscription.RuleSubActivity
import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.theme.LegadoTheme
import io.legado.app.ui.theme.adaptiveContentPadding import io.legado.app.ui.theme.adaptiveContentPadding
import io.legado.app.ui.widget.components.SourceIcon import io.legado.app.ui.widget.components.SourceIcon
@@ -71,7 +69,9 @@ import org.koin.androidx.compose.koinViewModel
fun RssScreen( fun RssScreen(
viewModel: RssViewModel = koinViewModel(), viewModel: RssViewModel = koinViewModel(),
onOpenSort: (sourceUrl: String, sortUrl: String?, key: String?) -> Unit, onOpenSort: (sourceUrl: String, sortUrl: String?, key: String?) -> Unit,
onOpenRead: (title: String?, origin: String, link: String?, openUrl: String?) -> Unit onOpenRead: (title: String?, origin: String, link: String?, openUrl: String?) -> Unit,
onOpenRuleSub: () -> Unit,
onOpenFavorites: () -> Unit,
) { ) {
val context = LocalContext.current val context = LocalContext.current
val uiState by viewModel.uiState.collectAsStateWithLifecycle() val uiState by viewModel.uiState.collectAsStateWithLifecycle()
@@ -82,6 +82,8 @@ fun RssScreen(
val currentContext by rememberUpdatedState(context) val currentContext by rememberUpdatedState(context)
val currentOnOpenSort by rememberUpdatedState(onOpenSort) val currentOnOpenSort by rememberUpdatedState(onOpenSort)
val currentOnOpenRead by rememberUpdatedState(onOpenRead) val currentOnOpenRead by rememberUpdatedState(onOpenRead)
val currentOnOpenRuleSub by rememberUpdatedState(onOpenRuleSub)
val currentOnOpenFavorites by rememberUpdatedState(onOpenFavorites)
LaunchedEffect(viewModel) { LaunchedEffect(viewModel) {
viewModel.effects.collectLatest { effect -> viewModel.effects.collectLatest { effect ->
@@ -112,11 +114,11 @@ fun RssScreen(
} }
RssEffect.OpenRuleSub -> { RssEffect.OpenRuleSub -> {
currentContext.startActivity<RuleSubActivity>() currentOnOpenRuleSub()
} }
RssEffect.OpenFavorites -> { RssEffect.OpenFavorites -> {
currentContext.startActivity<RssFavoritesActivity>() currentOnOpenFavorites()
} }
RssEffect.OpenSourceManage -> { RssEffect.OpenSourceManage -> {
@@ -1,52 +0,0 @@
package io.legado.app.ui.rss.favorites
import android.os.Bundle
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import io.legado.app.base.BaseComposeActivity
import io.legado.app.ui.rss.read.RssReadRouteScreen
/**
* 收藏夹
*/
class RssFavoritesActivity : BaseComposeActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
@Composable
override fun Content() {
var readArgs by remember {
mutableStateOf<ReadArgs?>(null)
}
val currentReadArgs = readArgs
if (currentReadArgs == null) {
RssFavoritesScreen(
onBackClick = { finish() },
onOpenRead = { title, origin, link, openUrl ->
readArgs = ReadArgs(title, origin, link, openUrl)
}
)
} else {
RssReadRouteScreen(
title = currentReadArgs.title,
origin = currentReadArgs.origin,
link = currentReadArgs.link,
openUrl = currentReadArgs.openUrl,
onBackClick = { readArgs = null }
)
}
}
private data class ReadArgs(
val title: String?,
val origin: String,
val link: String?,
val openUrl: String?
)
}
@@ -28,7 +28,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import io.legado.app.R import io.legado.app.R
import io.legado.app.data.entities.RssStar import io.legado.app.data.entities.RssStar
import io.legado.app.ui.theme.adaptiveContentPadding import io.legado.app.ui.theme.adaptiveContentPadding
@@ -41,13 +40,14 @@ import io.legado.app.ui.widget.components.dialog.TextListInputDialog
import io.legado.app.ui.widget.components.divider.PillDivider import io.legado.app.ui.widget.components.divider.PillDivider
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem
import io.legado.app.ui.widget.components.rules.RuleListScaffold import io.legado.app.ui.widget.components.rules.RuleListScaffold
import org.koin.androidx.compose.koinViewModel
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun RssFavoritesScreen( fun RssFavoritesScreen(
onBackClick: () -> Unit, onBackClick: () -> Unit,
onOpenRead: (title: String?, origin: String, link: String?, openUrl: String?) -> Unit, onOpenRead: (title: String?, origin: String, link: String?, openUrl: String?) -> Unit,
viewModel: RssFavoritesViewModel = viewModel() viewModel: RssFavoritesViewModel = koinViewModel()
) { ) {
val state by viewModel.state.collectAsState() val state by viewModel.state.collectAsState()
val groups by viewModel.groups.collectAsState() val groups by viewModel.groups.collectAsState()
@@ -1,23 +0,0 @@
package io.legado.app.ui.rss.subscription
import android.os.Bundle
import androidx.compose.runtime.Composable
import io.legado.app.base.BaseComposeActivity
/**
* 规则订阅界面
*/
class RuleSubActivity : BaseComposeActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
@Composable
override fun Content() {
RuleSubScreen(
onBackClick = { finish() }
)
}
}
@@ -18,7 +18,6 @@ import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Edit import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import io.legado.app.ui.widget.components.AppFloatingActionButton
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.SnackbarHostState
@@ -37,7 +36,6 @@ import androidx.compose.ui.res.stringArrayResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.lifecycle.viewmodel.compose.viewModel
import io.legado.app.R import io.legado.app.R
import io.legado.app.data.entities.RuleSub import io.legado.app.data.entities.RuleSub
import io.legado.app.data.entities.RuleSubType import io.legado.app.data.entities.RuleSubType
@@ -46,6 +44,7 @@ import io.legado.app.ui.association.ImportReplaceRuleDialog
import io.legado.app.ui.association.ImportRssSourceDialog import io.legado.app.ui.association.ImportRssSourceDialog
import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.theme.LegadoTheme
import io.legado.app.ui.theme.adaptiveContentPadding import io.legado.app.ui.theme.adaptiveContentPadding
import io.legado.app.ui.widget.components.AppFloatingActionButton
import io.legado.app.ui.widget.components.AppTextField import io.legado.app.ui.widget.components.AppTextField
import io.legado.app.ui.widget.components.EmptyMessage import io.legado.app.ui.widget.components.EmptyMessage
import io.legado.app.ui.widget.components.alert.AppAlertDialog import io.legado.app.ui.widget.components.alert.AppAlertDialog
@@ -57,12 +56,13 @@ import io.legado.app.ui.widget.components.rules.RuleListScaffold
import io.legado.app.ui.widget.components.text.AppText import io.legado.app.ui.widget.components.text.AppText
import io.legado.app.utils.showDialogFragment import io.legado.app.utils.showDialogFragment
import io.legado.app.utils.toastOnUi import io.legado.app.utils.toastOnUi
import org.koin.androidx.compose.koinViewModel
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
@Composable @Composable
fun RuleSubScreen( fun RuleSubScreen(
onBackClick: () -> Unit, onBackClick: () -> Unit,
viewModel: RuleSubViewModel = viewModel() viewModel: RuleSubViewModel = koinViewModel()
) { ) {
val context = LocalContext.current val context = LocalContext.current
val state by viewModel.state.collectAsState() val state by viewModel.state.collectAsState()
@@ -55,7 +55,7 @@ fun adaptiveContentPadding(
bottom: Dp bottom: Dp
): PaddingValues { ): PaddingValues {
val horizontal = if (ThemeResolver.isMiuixEngine(composeEngine)) 12.dp else 16.dp val horizontal = if (ThemeResolver.isMiuixEngine(composeEngine)) 12.dp else 16.dp
val adjustedTop = if (ThemeResolver.isMiuixEngine(composeEngine)) top + 8.dp else top val adjustedTop = if (ThemeResolver.isMiuixEngine(composeEngine)) top + 12.dp else top + 16.dp
return PaddingValues( return PaddingValues(
top = adjustedTop, top = adjustedTop,
bottom = bottom, bottom = bottom,
@@ -70,7 +70,7 @@ fun adaptiveContentPadding(
bottom: Dp, bottom: Dp,
horizontal: Dp horizontal: Dp
): PaddingValues { ): PaddingValues {
val adjustedTop = if (ThemeResolver.isMiuixEngine(composeEngine)) top + 6.dp else top + 4.dp val adjustedTop = if (ThemeResolver.isMiuixEngine(composeEngine)) top + 12.dp else top + 16.dp
return PaddingValues( return PaddingValues(
top = adjustedTop, top = adjustedTop,
bottom = bottom, bottom = bottom,
@@ -5,16 +5,16 @@ import androidx.compose.animation.ExperimentalSharedTransitionApi
import androidx.compose.animation.SharedTransitionScope import androidx.compose.animation.SharedTransitionScope
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
@@ -23,37 +23,18 @@ import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Shuffle import androidx.compose.material.icons.filled.Shuffle
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import io.legado.app.data.entities.SearchBook import io.legado.app.data.entities.SearchBook
import io.legado.app.domain.model.BookShelfState import io.legado.app.domain.model.BookShelfState
import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.theme.LegadoTheme
import io.legado.app.ui.widget.components.card.TextCard
import io.legado.app.ui.widget.components.cover.CoilBookCover import io.legado.app.ui.widget.components.cover.CoilBookCover
import io.legado.app.ui.widget.components.text.AppText import io.legado.app.ui.widget.components.text.AppText
import kotlinx.coroutines.flow.Flow
@Composable
fun SearchBookListItem(
book: SearchBook,
shelfState: Flow<BookShelfState>,
onClick: () -> Unit,
modifier: Modifier = Modifier,
) {
val currentShelfState by shelfState.collectAsState(initial = BookShelfState.NOT_IN_SHELF)
SearchBookListItem(
book = book,
shelfState = currentShelfState,
onClick = onClick,
modifier = modifier,
)
}
@OptIn(ExperimentalSharedTransitionApi::class) @OptIn(ExperimentalSharedTransitionApi::class)
@Composable @Composable
@@ -72,11 +53,14 @@ fun SearchBookListItem(
.clickable(onClick = onClick) .clickable(onClick = onClick)
.padding(horizontal = 16.dp, vertical = 8.dp) .padding(horizontal = 16.dp, vertical = 8.dp)
) { ) {
Box(modifier = Modifier
.width(72.dp)
.aspectRatio(5f / 7f)) {
CoilBookCover( CoilBookCover(
name = book.name, name = book.name,
author = book.author, author = book.author,
path = book.coverUrl, path = book.coverUrl,
modifier = Modifier.width(72.dp).aspectRatio(5f / 7f), modifier = Modifier.fillMaxSize(),
sourceOrigin = book.origin, sourceOrigin = book.origin,
sharedTransitionScope = sharedTransitionScope, sharedTransitionScope = sharedTransitionScope,
animatedVisibilityScope = animatedVisibilityScope, animatedVisibilityScope = animatedVisibilityScope,
@@ -84,6 +68,25 @@ fun SearchBookListItem(
showLoadingPlaceholder = sharedCoverKey == null showLoadingPlaceholder = sharedCoverKey == null
) )
val shelfIcon = when (shelfState) {
BookShelfState.IN_SHELF -> Icons.Default.Check
BookShelfState.SAME_NAME_AUTHOR -> Icons.Default.Shuffle
else -> null
}
if (shelfIcon != null) {
TextCard(
icon = shelfIcon,
modifier = Modifier
.align(Alignment.TopEnd)
.padding(2.dp),
cornerRadius = 4.dp,
horizontalPadding = 2.dp,
verticalPadding = 2.dp
)
}
}
Spacer(modifier = Modifier.width(8.dp)) Spacer(modifier = Modifier.width(8.dp))
Column( Column(
@@ -151,22 +154,6 @@ fun SearchBookListItem(
} }
} }
@Composable
fun SearchBookGridItem(
book: SearchBook,
shelfState: Flow<BookShelfState>,
onClick: () -> Unit,
modifier: Modifier = Modifier,
) {
val currentShelfState by shelfState.collectAsState(initial = BookShelfState.NOT_IN_SHELF)
SearchBookGridItem(
book = book,
shelfState = currentShelfState,
onClick = onClick,
modifier = modifier,
)
}
@OptIn(ExperimentalSharedTransitionApi::class) @OptIn(ExperimentalSharedTransitionApi::class)
@Composable @Composable
fun SearchBookGridItem( fun SearchBookGridItem(
@@ -183,14 +170,17 @@ fun SearchBookGridItem(
.width(IntrinsicSize.Min) .width(IntrinsicSize.Min)
.clickable(onClick = onClick) .clickable(onClick = onClick)
.padding(4.dp) .padding(4.dp)
) {
Box(
modifier = Modifier
.fillMaxWidth()
.aspectRatio(5f / 7f)
) { ) {
CoilBookCover( CoilBookCover(
name = book.name, name = book.name,
author = book.author, author = book.author,
path = book.coverUrl, path = book.coverUrl,
modifier = Modifier modifier = Modifier.fillMaxSize(),
.fillMaxWidth()
.aspectRatio(5f / 7f),
sourceOrigin = book.origin, sourceOrigin = book.origin,
sharedTransitionScope = sharedTransitionScope, sharedTransitionScope = sharedTransitionScope,
animatedVisibilityScope = animatedVisibilityScope, animatedVisibilityScope = animatedVisibilityScope,
@@ -198,6 +188,25 @@ fun SearchBookGridItem(
showLoadingPlaceholder = sharedCoverKey == null showLoadingPlaceholder = sharedCoverKey == null
) )
val shelfIcon = when (shelfState) {
BookShelfState.IN_SHELF -> Icons.Default.Check
BookShelfState.SAME_NAME_AUTHOR -> Icons.Default.Shuffle
else -> null
}
if (shelfIcon != null) {
TextCard(
icon = shelfIcon,
modifier = Modifier
.align(Alignment.TopEnd)
.padding(2.dp),
cornerRadius = 4.dp,
horizontalPadding = 2.dp,
verticalPadding = 2.dp
)
}
}
Spacer(modifier = Modifier.height(4.dp)) Spacer(modifier = Modifier.height(4.dp))
AppText( AppText(
@@ -27,12 +27,18 @@ fun PillDivider(
val isMiuix = ThemeResolver.isMiuixEngine(LegadoTheme.composeEngine) val isMiuix = ThemeResolver.isMiuixEngine(LegadoTheme.composeEngine)
if (isMiuix) { if (isMiuix) {
Box( Box(
modifier = Modifier modifier = modifier
.fillMaxWidth() .fillMaxWidth()
.padding(vertical = 2.dp) .padding(vertical = 4.dp),
.height(4.dp) contentAlignment = Alignment.Center
) {
Box(
modifier = Modifier
.fillMaxWidth(0.8f)
.height(thickness)
.background(MiuixTheme.colorScheme.dividerLine) .background(MiuixTheme.colorScheme.dividerLine)
) )
}
} else { } else {
Box( Box(
modifier = modifier modifier = modifier
@@ -48,7 +48,7 @@ fun CompactDropdownSettingItem(
entryValues: Array<String>, entryValues: Array<String>,
description: String? = null, description: String? = null,
imageVector: ImageVector? = null, imageVector: ImageVector? = null,
color: Color? = LegadoTheme.colorScheme.surface, color: Color? = LegadoTheme.colorScheme.onSheetContent,
shape: Shape = MaterialTheme.shapes.small, shape: Shape = MaterialTheme.shapes.small,
onValueChange: (String) -> Unit onValueChange: (String) -> Unit
) { ) {
@@ -126,7 +126,7 @@ fun CompactSliderSettingItem(
steps: Int = 0, steps: Int = 0,
description: String? = null, description: String? = null,
imageVector: ImageVector? = null, imageVector: ImageVector? = null,
color: Color? = MaterialTheme.colorScheme.surface, color: Color? = LegadoTheme.colorScheme.onSheetContent,
shape: Shape = MaterialTheme.shapes.small, shape: Shape = MaterialTheme.shapes.small,
onValueChange: (Float) -> Unit onValueChange: (Float) -> Unit
) { ) {
@@ -222,7 +222,7 @@ fun CompactSwitchSettingItem(
checked: Boolean, checked: Boolean,
description: String? = null, description: String? = null,
imageVector: ImageVector? = null, imageVector: ImageVector? = null,
color: Color? = MaterialTheme.colorScheme.surface, color: Color? = LegadoTheme.colorScheme.onSheetContent,
shape: Shape = MaterialTheme.shapes.small, shape: Shape = MaterialTheme.shapes.small,
enabled: Boolean = true, enabled: Boolean = true,
onCheckedChange: (Boolean) -> Unit onCheckedChange: (Boolean) -> Unit
@@ -260,7 +260,7 @@ fun CompactClickableSettingItem(
title: String, title: String,
description: String? = null, description: String? = null,
imageVector: ImageVector? = null, imageVector: ImageVector? = null,
color: Color? = MaterialTheme.colorScheme.surface, color: Color? = LegadoTheme.colorScheme.onSheetContent,
shape: Shape = MaterialTheme.shapes.small, shape: Shape = MaterialTheme.shapes.small,
trailingContent: (@Composable () -> Unit)? = null, trailingContent: (@Composable () -> Unit)? = null,
onClick: () -> Unit onClick: () -> Unit