界面优化
This commit is contained in:
@@ -271,6 +271,7 @@ object PreferKey {
|
||||
const val bookshelfCoverShadow = "bookshelfCoverShadow"
|
||||
const val bookshelfSearchActionDirectToSearch = "bookshelfSearchActionDirectToSearch"
|
||||
const val bookshelfCardColor = "bookshelfCardColor"
|
||||
const val bookshelfCardColorDark = "bookshelfCardColorDark"
|
||||
const val bookshelfGroupListStyle = "bookshelfGroupListStyle"
|
||||
const val bookshelfGroupCoverCount = "bookshelfGroupCoverCount"
|
||||
|
||||
|
||||
@@ -723,8 +723,8 @@ interface BookDao {
|
||||
type, `group`, `order`, canUpdate,
|
||||
ifnull(customIntro, intro) as intro, kind
|
||||
FROM books
|
||||
ORDER BY CASE WHEN (coverUrl IS NOT NULL OR customCoverUrl IS NOT NULL) THEN 0 ELSE 1 END, durChapterTime DESC
|
||||
LIMIT 4
|
||||
ORDER BY durChapterTime DESC
|
||||
LIMIT 10
|
||||
"""
|
||||
)
|
||||
fun flowBookShelfPreview(): Flow<List<BookShelfItem>>
|
||||
@@ -741,8 +741,8 @@ interface BookDao {
|
||||
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 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
|
||||
LIMIT 4
|
||||
ORDER BY durChapterTime DESC
|
||||
LIMIT 10
|
||||
"""
|
||||
)
|
||||
fun flowBookShelfRootPreview(): Flow<List<BookShelfItem>>
|
||||
@@ -757,8 +757,8 @@ interface BookDao {
|
||||
ifnull(customIntro, intro) as intro, kind
|
||||
FROM books
|
||||
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
|
||||
LIMIT 4
|
||||
ORDER BY durChapterTime DESC
|
||||
LIMIT 10
|
||||
"""
|
||||
)
|
||||
fun flowBookShelfLocalPreview(): Flow<List<BookShelfItem>>
|
||||
@@ -773,8 +773,8 @@ interface BookDao {
|
||||
ifnull(customIntro, intro) as intro, kind
|
||||
FROM books
|
||||
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
|
||||
LIMIT 4
|
||||
ORDER BY durChapterTime DESC
|
||||
LIMIT 10
|
||||
"""
|
||||
)
|
||||
fun flowBookShelfAudioPreview(): Flow<List<BookShelfItem>>
|
||||
@@ -790,8 +790,8 @@ interface BookDao {
|
||||
FROM books
|
||||
WHERE type & ${BookType.audio} = 0 AND type & ${BookType.local} = 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
|
||||
LIMIT 4
|
||||
ORDER BY durChapterTime DESC
|
||||
LIMIT 10
|
||||
"""
|
||||
)
|
||||
fun flowBookShelfNetNoGroupPreview(): Flow<List<BookShelfItem>>
|
||||
@@ -807,8 +807,8 @@ interface BookDao {
|
||||
FROM books
|
||||
WHERE type & ${BookType.local} > 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
|
||||
LIMIT 4
|
||||
ORDER BY durChapterTime DESC
|
||||
LIMIT 10
|
||||
"""
|
||||
)
|
||||
fun flowBookShelfLocalNoGroupPreview(): Flow<List<BookShelfItem>>
|
||||
@@ -823,8 +823,8 @@ interface BookDao {
|
||||
ifnull(customIntro, intro) as intro, kind
|
||||
FROM books
|
||||
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
|
||||
LIMIT 4
|
||||
ORDER BY durChapterTime DESC
|
||||
LIMIT 10
|
||||
"""
|
||||
)
|
||||
fun flowBookShelfMangaPreview(): Flow<List<BookShelfItem>>
|
||||
@@ -839,8 +839,8 @@ interface BookDao {
|
||||
ifnull(customIntro, intro) as intro, kind
|
||||
FROM books
|
||||
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
|
||||
LIMIT 4
|
||||
ORDER BY durChapterTime DESC
|
||||
LIMIT 10
|
||||
"""
|
||||
)
|
||||
fun flowBookShelfTextPreview(): Flow<List<BookShelfItem>>
|
||||
@@ -855,8 +855,8 @@ interface BookDao {
|
||||
ifnull(customIntro, intro) as intro, kind
|
||||
FROM books
|
||||
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
|
||||
LIMIT 4
|
||||
ORDER BY durChapterTime DESC
|
||||
LIMIT 10
|
||||
"""
|
||||
)
|
||||
fun flowBookShelfUpdateErrorPreview(): Flow<List<BookShelfItem>>
|
||||
@@ -871,8 +871,8 @@ interface BookDao {
|
||||
ifnull(customIntro, intro) as intro, kind
|
||||
FROM books
|
||||
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
|
||||
LIMIT 4
|
||||
ORDER BY durChapterTime DESC
|
||||
LIMIT 10
|
||||
"""
|
||||
)
|
||||
fun flowBookShelfUnreadPreview(): Flow<List<BookShelfItem>>
|
||||
@@ -887,8 +887,8 @@ interface BookDao {
|
||||
ifnull(customIntro, intro) as intro, kind
|
||||
FROM books
|
||||
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
|
||||
LIMIT 4
|
||||
ORDER BY durChapterTime DESC
|
||||
LIMIT 10
|
||||
"""
|
||||
)
|
||||
fun flowBookShelfReadingPreview(): Flow<List<BookShelfItem>>
|
||||
@@ -903,8 +903,8 @@ interface BookDao {
|
||||
ifnull(customIntro, intro) as intro, kind
|
||||
FROM books
|
||||
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
|
||||
LIMIT 4
|
||||
ORDER BY durChapterTime DESC
|
||||
LIMIT 10
|
||||
"""
|
||||
)
|
||||
fun flowBookShelfReadFinishedPreview(): Flow<List<BookShelfItem>>
|
||||
@@ -919,8 +919,8 @@ interface BookDao {
|
||||
ifnull(customIntro, intro) as intro, kind
|
||||
FROM books
|
||||
WHERE (`group` & :groupId) > 0
|
||||
ORDER BY CASE WHEN (coverUrl IS NOT NULL OR customCoverUrl IS NOT NULL) THEN 0 ELSE 1 END, durChapterTime DESC
|
||||
LIMIT 4
|
||||
ORDER BY durChapterTime DESC
|
||||
LIMIT 10
|
||||
"""
|
||||
)
|
||||
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.CacheBookDownloadRepository
|
||||
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.DirectLinkUploadRepository
|
||||
import io.legado.app.data.repository.ExploreRepository
|
||||
import io.legado.app.data.repository.ExploreRepositoryImpl
|
||||
import io.legado.app.data.repository.LocalBookRepository
|
||||
import io.legado.app.data.repository.ReadRecordRepository
|
||||
import io.legado.app.data.repository.RemoteBookRepository
|
||||
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.SearchRepositoryImpl
|
||||
import io.legado.app.data.repository.SearchContentRepository
|
||||
import io.legado.app.data.repository.SettingsRepository
|
||||
import io.legado.app.data.repository.UploadRepository
|
||||
import io.legado.app.data.repository.WebDavBackupRepository
|
||||
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.BookCacheCleanupGateway
|
||||
import io.legado.app.domain.gateway.BookCacheDownloadGateway
|
||||
import io.legado.app.domain.gateway.BookSearchGateway
|
||||
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.GetReadingProgressUseCase
|
||||
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.readRecord.GetReadRecordOverviewUseCase
|
||||
import io.legado.app.domain.usecase.SearchBooksUseCase
|
||||
import io.legado.app.domain.usecase.ShrinkDatabaseUseCase
|
||||
import io.legado.app.domain.usecase.UpdateBooksGroupUseCase
|
||||
import io.legado.app.domain.usecase.UploadReadingProgressUseCase
|
||||
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.CoverInterceptor
|
||||
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.changesource.ChangeBookSourceComposeViewModel
|
||||
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.group.GroupViewModel
|
||||
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.ServersViewModel
|
||||
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.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.ReadRecordViewModel
|
||||
import io.legado.app.ui.book.search.SearchViewModel
|
||||
import io.legado.app.ui.book.searchContent.SearchContentViewModel
|
||||
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.ReplaceRuleViewModel
|
||||
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.RssSortViewModel
|
||||
import io.legado.app.ui.rss.favorites.RssFavoritesViewModel
|
||||
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.viewModel
|
||||
import org.koin.core.module.dsl.viewModelOf
|
||||
@@ -179,6 +181,8 @@ val appModule = module {
|
||||
viewModelOf(::RssSortViewModel)
|
||||
viewModelOf(::RssArticlesViewModel)
|
||||
viewModelOf(::ReadRssViewModel)
|
||||
viewModelOf(::RssFavoritesViewModel)
|
||||
viewModelOf(::RuleSubViewModel)
|
||||
viewModelOf(::ReadRecordViewModel)
|
||||
viewModelOf(::ReadRecordOverviewViewModel)
|
||||
viewModelOf(::ExploreShowViewModel)
|
||||
|
||||
@@ -269,12 +269,17 @@ object BookshelfConfig {
|
||||
/**
|
||||
* 书架卡片背景颜色
|
||||
*/
|
||||
private val _bookshelfCardColor = prefStateDelegate(PreferKey.bookshelfCardColor, 0) {
|
||||
postEvent(EventBus.NOTIFY_MAIN, false)
|
||||
}
|
||||
private val _bookshelfCardColor = prefStateDelegate(PreferKey.bookshelfCardColor, 0)
|
||||
var bookshelfCardColor by _bookshelfCardColor
|
||||
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: 横排封面
|
||||
*/
|
||||
|
||||
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,
|
||||
onNavigateToRssSort: (sourceUrl: String, sortUrl: String?, key: String?) -> Unit,
|
||||
onNavigateToRssRead: (title: String?, origin: String, link: String?, openUrl: String?) -> Unit,
|
||||
onNavigateToRssFavorites: () -> Unit,
|
||||
onNavigateToRuleSub: () -> Unit,
|
||||
onNavigateToReadRecord: () -> Unit,
|
||||
sharedTransitionScope: SharedTransitionScope? = null,
|
||||
animatedVisibilityScope: AnimatedVisibilityScope? = null,
|
||||
@@ -383,7 +385,9 @@ fun MainScreen(
|
||||
},
|
||||
onOpenRead = { title, origin, link, openUrl ->
|
||||
onNavigateToRssRead(title, origin, link, openUrl)
|
||||
}
|
||||
},
|
||||
onOpenFavorites = onNavigateToRssFavorites,
|
||||
onOpenRuleSub = onNavigateToRuleSub
|
||||
)
|
||||
MainDestination.My -> MyScreen(
|
||||
onOpenSettings = onOpenSettings,
|
||||
|
||||
@@ -26,7 +26,6 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
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.Shadow
|
||||
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.SpanStyle
|
||||
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.unit.dp
|
||||
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.themeConfig.ThemeConfig
|
||||
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.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.CoilBookCover
|
||||
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.utils.splitNotBlank
|
||||
import io.legado.app.utils.toTimeAgo
|
||||
@@ -90,10 +87,11 @@ fun BookshelfItem(
|
||||
onClick: () -> Unit,
|
||||
onLongClick: (() -> Unit)?
|
||||
) {
|
||||
val containerColor = if (!isGrid && BookshelfConfig.bookshelfCardColor != 0) {
|
||||
Color(BookshelfConfig.bookshelfCardColor)
|
||||
} else if (ThemeConfig.enableDeepPersonalization && ThemeConfig.secondaryThemeColor != 0) {
|
||||
Color(ThemeConfig.secondaryThemeColor)
|
||||
val isDark = LegadoTheme.isDark
|
||||
val bookshelfCardColor =
|
||||
if (isDark) BookshelfConfig.bookshelfCardColorDark else BookshelfConfig.bookshelfCardColor
|
||||
val containerColor = if (!isGrid && bookshelfCardColor != 0) {
|
||||
Color(bookshelfCardColor)
|
||||
} else {
|
||||
LegadoTheme.colorScheme.cardContainer
|
||||
}
|
||||
@@ -189,7 +187,7 @@ fun BookshelfItem(
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.align(Alignment.Top)
|
||||
.width(if (!isCompact) 80.dp else 56.dp)
|
||||
.width(if (!isCompact) 84.dp else 56.dp)
|
||||
.padding(end = 8.dp)
|
||||
) {
|
||||
Box(
|
||||
@@ -209,11 +207,13 @@ fun BookshelfItem(
|
||||
}
|
||||
}
|
||||
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
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
verticalAlignment = Alignment.Top
|
||||
) {
|
||||
AppText(
|
||||
text = title,
|
||||
@@ -222,11 +222,15 @@ fun BookshelfItem(
|
||||
} else {
|
||||
LegadoTheme.typography.titleMediumEmphasized
|
||||
},
|
||||
maxLines = 1,
|
||||
maxLines = BookshelfConfig.bookshelfTitleMaxLines,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
titleEnd?.invoke()
|
||||
titleEnd?.let {
|
||||
Box(modifier = Modifier.padding(top = 4.dp)) {
|
||||
it.invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
subTitle?.let {
|
||||
AppText(
|
||||
@@ -296,68 +300,82 @@ fun BookGroupCover(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
)
|
||||
} else {
|
||||
Column(modifier = Modifier.fillMaxSize()) {
|
||||
Row(modifier = Modifier.weight(1f)) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.fillMaxHeight()
|
||||
.padding(1.dp)
|
||||
) {
|
||||
books.getOrNull(0)?.let {
|
||||
CoilBookCover(
|
||||
name = it.name,
|
||||
author = it.author,
|
||||
path = it.getDisplayCover(),
|
||||
modifier = Modifier.fillMaxSize()
|
||||
)
|
||||
}
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.fillMaxHeight()
|
||||
.padding(1.dp)
|
||||
) {
|
||||
books.getOrNull(1)?.let {
|
||||
CoilBookCover(
|
||||
name = it.name,
|
||||
author = it.author,
|
||||
path = it.getDisplayCover(),
|
||||
modifier = Modifier.fillMaxSize()
|
||||
)
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier.run {
|
||||
if (BookshelfConfig.bookshelfCoverShadow) {
|
||||
background(LegadoTheme.colorScheme.surface)
|
||||
} else {
|
||||
this
|
||||
}
|
||||
}
|
||||
Row(modifier = Modifier.weight(1f)) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.fillMaxHeight()
|
||||
.padding(1.dp)
|
||||
) {
|
||||
books.getOrNull(2)?.let {
|
||||
CoilBookCover(
|
||||
name = it.name,
|
||||
author = it.author,
|
||||
path = it.getDisplayCover(),
|
||||
modifier = Modifier.fillMaxSize()
|
||||
)
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(horizontal = 1.dp),
|
||||
) {
|
||||
Row(modifier = Modifier.weight(1f)) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.fillMaxHeight()
|
||||
.padding(1.dp)
|
||||
) {
|
||||
books.getOrNull(0)?.let {
|
||||
CoilBookCover(
|
||||
name = it.name,
|
||||
author = it.author,
|
||||
path = it.getDisplayCover(),
|
||||
modifier = Modifier.fillMaxSize()
|
||||
)
|
||||
}
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.fillMaxHeight()
|
||||
.padding(1.dp)
|
||||
) {
|
||||
books.getOrNull(1)?.let {
|
||||
CoilBookCover(
|
||||
name = it.name,
|
||||
author = it.author,
|
||||
path = it.getDisplayCover(),
|
||||
modifier = Modifier.fillMaxSize()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.fillMaxHeight()
|
||||
.padding(1.dp)
|
||||
) {
|
||||
books.getOrNull(3)?.let {
|
||||
CoilBookCover(
|
||||
name = it.name,
|
||||
author = it.author,
|
||||
path = it.getDisplayCover(),
|
||||
modifier = Modifier.fillMaxSize()
|
||||
)
|
||||
Row(modifier = Modifier.weight(1f)) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.fillMaxHeight()
|
||||
.padding(1.dp)
|
||||
) {
|
||||
books.getOrNull(2)?.let {
|
||||
CoilBookCover(
|
||||
name = it.name,
|
||||
author = it.author,
|
||||
path = it.getDisplayCover(),
|
||||
modifier = Modifier.fillMaxSize()
|
||||
)
|
||||
}
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.fillMaxHeight()
|
||||
.padding(1.dp)
|
||||
) {
|
||||
books.getOrNull(3)?.let {
|
||||
CoilBookCover(
|
||||
name = it.name,
|
||||
author = it.author,
|
||||
path = it.getDisplayCover(),
|
||||
modifier = Modifier.fillMaxSize()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -482,13 +500,16 @@ fun BookGroupItemHorizontalCovers(
|
||||
onBookClick: ((BookShelfItem) -> Unit)? = null
|
||||
) {
|
||||
Column {
|
||||
val isDark = LegadoTheme.isDark
|
||||
val bookshelfCardColor =
|
||||
if (isDark) BookshelfConfig.bookshelfCardColorDark else BookshelfConfig.bookshelfCardColor
|
||||
NormalCard(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.padding(all = 4.dp),
|
||||
cornerRadius = 12.dp,
|
||||
containerColor = if (BookshelfConfig.bookshelfCardColor != 0) {
|
||||
Color(BookshelfConfig.bookshelfCardColor)
|
||||
containerColor = if (bookshelfCardColor != 0) {
|
||||
Color(bookshelfCardColor)
|
||||
} else {
|
||||
LegadoTheme.colorScheme.cardContainer
|
||||
},
|
||||
@@ -634,7 +655,9 @@ fun BookItem(
|
||||
path = book.getDisplayCover(),
|
||||
isUpdating = isUpdating,
|
||||
modifier = modifier,
|
||||
coverModifier = Modifier.fillMaxWidth().aspectRatio(5f / 7f),
|
||||
coverModifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.aspectRatio(5f / 7f),
|
||||
sourceOrigin = book.origin,
|
||||
badgeText = if (layoutMode != 0) unreadText else null,
|
||||
showBadgeDot = BookshelfConfig.showUnread && BookshelfConfig.showUnreadNew && book.isNew,
|
||||
|
||||
@@ -3,11 +3,16 @@ package io.legado.app.ui.main.bookshelf
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
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.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
@@ -17,6 +22,8 @@ import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
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.platform.LocalConfiguration
|
||||
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.ThemeConfig
|
||||
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.divider.PillDivider
|
||||
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.CompactDropdownSettingItem
|
||||
@@ -45,15 +52,13 @@ fun BookshelfConfigSheet(
|
||||
val isLandscape = configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||
var showLabelColorManage by remember { mutableStateOf(false) }
|
||||
var showColorPicker by remember { mutableStateOf(false) }
|
||||
var showColorPickerDark by remember { mutableStateOf(false) }
|
||||
|
||||
AppModalBottomSheet(
|
||||
title = stringResource(R.string.bookshelf_layout),
|
||||
show = show,
|
||||
onDismissRequest = onDismissRequest
|
||||
) {
|
||||
GlassCard() {
|
||||
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
@@ -99,21 +104,12 @@ fun BookshelfConfigSheet(
|
||||
if (isLandscape) BookshelfConfig.bookshelfFolderLayoutModeLandscape
|
||||
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
|
||||
AnimatedVisibility(visible = BookshelfConfig.bookGroupStyle == 2) {
|
||||
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
|
||||
PillDivider()
|
||||
|
||||
CompactDropdownSettingItem(
|
||||
title = "文件夹布局模式",
|
||||
description = stringResource(if (isLandscape) R.string.screen_landscape else R.string.screen_portrait),
|
||||
@@ -157,33 +153,54 @@ fun BookshelfConfigSheet(
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
AnimatedVisibility(
|
||||
visible = BookshelfConfig.bookGroupStyle == 2 && folderLayoutMode == 0
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
CompactDropdownSettingItem(
|
||||
title = "文件夹列表样式",
|
||||
selectedValue = BookshelfConfig.bookshelfGroupListStyle.toString(),
|
||||
displayEntries = arrayOf("默认", "紧凑", "横排封面"),
|
||||
entryValues = arrayOf("0", "1", "2"),
|
||||
onValueChange = {
|
||||
BookshelfConfig.bookshelfGroupListStyle = it.toInt()
|
||||
}
|
||||
)
|
||||
AnimatedVisibility(visible = BookshelfConfig.bookshelfGroupListStyle == 2) {
|
||||
CompactSliderSettingItem(
|
||||
title = "横排封面数量",
|
||||
value = BookshelfConfig.bookshelfGroupCoverCount.toFloat(),
|
||||
valueRange = 1f..10f,
|
||||
steps = 9,
|
||||
onValueChange = {
|
||||
BookshelfConfig.bookshelfGroupCoverCount = it.toInt()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PillDivider()
|
||||
}
|
||||
}
|
||||
|
||||
AnimatedVisibility(
|
||||
visible = BookshelfConfig.bookGroupStyle == 2 && folderLayoutMode == 0
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
CompactDropdownSettingItem(
|
||||
title = "文件夹列表样式",
|
||||
selectedValue = BookshelfConfig.bookshelfGroupListStyle.toString(),
|
||||
displayEntries = arrayOf("默认", "紧凑", "横排封面"),
|
||||
entryValues = arrayOf("0", "1", "2"),
|
||||
onValueChange = { BookshelfConfig.bookshelfGroupListStyle = it.toInt() }
|
||||
)
|
||||
AnimatedVisibility(visible = BookshelfConfig.bookshelfGroupListStyle == 2) {
|
||||
CompactSliderSettingItem(
|
||||
title = "横排封面数量",
|
||||
value = BookshelfConfig.bookshelfGroupCoverCount.toFloat(),
|
||||
valueRange = 1f..10f,
|
||||
steps = 9,
|
||||
onValueChange = { BookshelfConfig.bookshelfGroupCoverCount = it.toInt() }
|
||||
)
|
||||
}
|
||||
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(
|
||||
visible = layoutMode == 1
|
||||
@@ -243,103 +260,135 @@ fun BookshelfConfigSheet(
|
||||
)
|
||||
|
||||
CompactClickableSettingItem(
|
||||
title = "卡片背景颜色",
|
||||
title = "日间卡片背景颜色",
|
||||
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) {
|
||||
if (BookshelfConfig.bookGroupStyle != 2) {
|
||||
CompactSwitchSettingItem(
|
||||
title = stringResource(R.string.compact_mode),
|
||||
checked = BookshelfConfig.bookshelfLayoutCompact,
|
||||
color = LegadoTheme.colorScheme.surface,
|
||||
onCheckedChange = { BookshelfConfig.bookshelfLayoutCompact = it }
|
||||
)
|
||||
}
|
||||
|
||||
val listColCount =
|
||||
if (isLandscape) BookshelfConfig.bookshelfLayoutListLandscape else BookshelfConfig.bookshelfLayoutListPortrait
|
||||
CompactSliderSettingItem(
|
||||
title = stringResource(R.string.number_rows_columns),
|
||||
value = listColCount.toFloat(),
|
||||
valueRange = 1f..5f,
|
||||
steps = 4,
|
||||
onValueChange = {
|
||||
if (isLandscape) BookshelfConfig.bookshelfLayoutListLandscape =
|
||||
it.toInt()
|
||||
else BookshelfConfig.bookshelfLayoutListPortrait = it.toInt()
|
||||
}
|
||||
)
|
||||
|
||||
CompactSwitchSettingItem(
|
||||
title = "显示更多信息",
|
||||
checked = BookshelfConfig.showBookIntro,
|
||||
color = LegadoTheme.colorScheme.surface,
|
||||
onCheckedChange = { BookshelfConfig.showBookIntro = it }
|
||||
)
|
||||
|
||||
AnimatedVisibility(visible = BookshelfConfig.showBookIntro) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
if (BookshelfConfig.bookGroupStyle != 2) {
|
||||
CompactSwitchSettingItem(
|
||||
title = stringResource(R.string.compact_mode),
|
||||
checked = BookshelfConfig.bookshelfLayoutCompact,
|
||||
color = LegadoTheme.colorScheme.surface,
|
||||
onCheckedChange = { BookshelfConfig.bookshelfLayoutCompact = it }
|
||||
)
|
||||
}
|
||||
|
||||
val listColCount =
|
||||
if (isLandscape) BookshelfConfig.bookshelfLayoutListLandscape else BookshelfConfig.bookshelfLayoutListPortrait
|
||||
CompactSliderSettingItem(
|
||||
title = stringResource(R.string.number_rows_columns),
|
||||
value = listColCount.toFloat(),
|
||||
valueRange = 1f..5f,
|
||||
steps = 4,
|
||||
onValueChange = {
|
||||
if (isLandscape) BookshelfConfig.bookshelfLayoutListLandscape =
|
||||
it.toInt()
|
||||
else BookshelfConfig.bookshelfLayoutListPortrait = it.toInt()
|
||||
CompactSwitchSettingItem(
|
||||
title = "显示最新章节",
|
||||
checked = BookshelfConfig.bookshelfShowLatestChapter,
|
||||
color = LegadoTheme.colorScheme.surface,
|
||||
onCheckedChange = {
|
||||
BookshelfConfig.bookshelfShowLatestChapter = it
|
||||
}
|
||||
)
|
||||
|
||||
CompactSwitchSettingItem(
|
||||
title = "显示更多信息",
|
||||
checked = BookshelfConfig.showBookIntro,
|
||||
title = "显示简介",
|
||||
checked = BookshelfConfig.bookshelfShowIntro,
|
||||
color = LegadoTheme.colorScheme.surface,
|
||||
onCheckedChange = { BookshelfConfig.showBookIntro = it }
|
||||
onCheckedChange = { BookshelfConfig.bookshelfShowIntro = it }
|
||||
)
|
||||
|
||||
AnimatedVisibility(visible = BookshelfConfig.showBookIntro) {
|
||||
AnimatedVisibility(
|
||||
visible = BookshelfConfig.bookshelfShowIntro
|
||||
) {
|
||||
CompactSliderSettingItem(
|
||||
title = "简介行数",
|
||||
description = if (BookshelfConfig.bookshelfIntroMaxLines == 0) "显示全部简介" else "显示 ${BookshelfConfig.bookshelfIntroMaxLines} 行简介",
|
||||
value = BookshelfConfig.bookshelfIntroMaxLines.toFloat(),
|
||||
valueRange = 0f..10f,
|
||||
steps = 10,
|
||||
onValueChange = {
|
||||
BookshelfConfig.bookshelfIntroMaxLines = it.toInt()
|
||||
}
|
||||
)
|
||||
}
|
||||
CompactSwitchSettingItem(
|
||||
title = "显示标签",
|
||||
checked = BookshelfConfig.bookshelfShowTag,
|
||||
color = LegadoTheme.colorScheme.surface,
|
||||
onCheckedChange = { BookshelfConfig.bookshelfShowTag = it }
|
||||
)
|
||||
AnimatedVisibility(
|
||||
visible = BookshelfConfig.bookshelfShowTag
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
CompactSwitchSettingItem(
|
||||
title = "显示最新章节",
|
||||
checked = BookshelfConfig.bookshelfShowLatestChapter,
|
||||
title = "自定义标签颜色",
|
||||
checked = ThemeConfig.enableCustomTagColors,
|
||||
color = LegadoTheme.colorScheme.surface,
|
||||
onCheckedChange = { BookshelfConfig.bookshelfShowLatestChapter = it }
|
||||
onCheckedChange = { ThemeConfig.enableCustomTagColors = it }
|
||||
)
|
||||
|
||||
CompactSwitchSettingItem(
|
||||
title = "显示简介",
|
||||
checked = BookshelfConfig.bookshelfShowIntro,
|
||||
color = LegadoTheme.colorScheme.surface,
|
||||
onCheckedChange = { BookshelfConfig.bookshelfShowIntro = it }
|
||||
)
|
||||
AnimatedVisibility(
|
||||
visible = BookshelfConfig.bookshelfShowIntro
|
||||
) {
|
||||
CompactSliderSettingItem(
|
||||
title = "简介行数",
|
||||
description = if (BookshelfConfig.bookshelfIntroMaxLines == 0) "显示全部简介" else "显示 ${BookshelfConfig.bookshelfIntroMaxLines} 行简介",
|
||||
value = BookshelfConfig.bookshelfIntroMaxLines.toFloat(),
|
||||
valueRange = 0f..10f,
|
||||
steps = 10,
|
||||
onValueChange = { BookshelfConfig.bookshelfIntroMaxLines = it.toInt() }
|
||||
AnimatedVisibility(visible = ThemeConfig.enableCustomTagColors) {
|
||||
CompactClickableSettingItem(
|
||||
title = "管理标签颜色",
|
||||
color = LegadoTheme.colorScheme.surface,
|
||||
onClick = { showLabelColorManage = true }
|
||||
)
|
||||
}
|
||||
CompactSwitchSettingItem(
|
||||
title = "显示标签",
|
||||
checked = BookshelfConfig.bookshelfShowTag,
|
||||
color = LegadoTheme.colorScheme.surface,
|
||||
onCheckedChange = { BookshelfConfig.bookshelfShowTag = it }
|
||||
)
|
||||
AnimatedVisibility(
|
||||
visible = BookshelfConfig.bookshelfShowTag
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
CompactSwitchSettingItem(
|
||||
title = "自定义标签颜色",
|
||||
checked = ThemeConfig.enableCustomTagColors,
|
||||
color = LegadoTheme.colorScheme.surface,
|
||||
onCheckedChange = { ThemeConfig.enableCustomTagColors = it }
|
||||
)
|
||||
AnimatedVisibility(visible = ThemeConfig.enableCustomTagColors) {
|
||||
CompactClickableSettingItem(
|
||||
title = "管理标签颜色",
|
||||
color = LegadoTheme.colorScheme.surface,
|
||||
onClick = { showLabelColorManage = true }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -347,6 +396,8 @@ fun BookshelfConfigSheet(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
CompactSliderSettingItem(
|
||||
title = stringResource(R.string.max_title_lines),
|
||||
value = BookshelfConfig.bookshelfTitleMaxLines.toFloat(),
|
||||
@@ -448,5 +499,12 @@ fun BookshelfConfigSheet(
|
||||
onDismissRequest = { showColorPicker = false },
|
||||
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(
|
||||
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
|
||||
),
|
||||
verticalArrangement = Arrangement.spacedBy(if (isGridMode) 8.dp else 0.dp),
|
||||
@@ -1342,7 +1342,7 @@ fun BookshelfPage(
|
||||
),
|
||||
contentPadding = adaptiveContentPaddingBookshelf(
|
||||
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
|
||||
),
|
||||
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.data.entities.RssSource
|
||||
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.manage.RssSourceActivity
|
||||
import io.legado.app.ui.rss.subscription.RuleSubActivity
|
||||
import io.legado.app.ui.theme.LegadoTheme
|
||||
import io.legado.app.ui.theme.adaptiveContentPadding
|
||||
import io.legado.app.ui.widget.components.SourceIcon
|
||||
@@ -71,7 +69,9 @@ import org.koin.androidx.compose.koinViewModel
|
||||
fun RssScreen(
|
||||
viewModel: RssViewModel = koinViewModel(),
|
||||
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 uiState by viewModel.uiState.collectAsStateWithLifecycle()
|
||||
@@ -82,6 +82,8 @@ fun RssScreen(
|
||||
val currentContext by rememberUpdatedState(context)
|
||||
val currentOnOpenSort by rememberUpdatedState(onOpenSort)
|
||||
val currentOnOpenRead by rememberUpdatedState(onOpenRead)
|
||||
val currentOnOpenRuleSub by rememberUpdatedState(onOpenRuleSub)
|
||||
val currentOnOpenFavorites by rememberUpdatedState(onOpenFavorites)
|
||||
|
||||
LaunchedEffect(viewModel) {
|
||||
viewModel.effects.collectLatest { effect ->
|
||||
@@ -112,11 +114,11 @@ fun RssScreen(
|
||||
}
|
||||
|
||||
RssEffect.OpenRuleSub -> {
|
||||
currentContext.startActivity<RuleSubActivity>()
|
||||
currentOnOpenRuleSub()
|
||||
}
|
||||
|
||||
RssEffect.OpenFavorites -> {
|
||||
currentContext.startActivity<RssFavoritesActivity>()
|
||||
currentOnOpenFavorites()
|
||||
}
|
||||
|
||||
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.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import io.legado.app.R
|
||||
import io.legado.app.data.entities.RssStar
|
||||
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.menuItem.RoundDropdownMenuItem
|
||||
import io.legado.app.ui.widget.components.rules.RuleListScaffold
|
||||
import org.koin.androidx.compose.koinViewModel
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun RssFavoritesScreen(
|
||||
onBackClick: () -> Unit,
|
||||
onOpenRead: (title: String?, origin: String, link: String?, openUrl: String?) -> Unit,
|
||||
viewModel: RssFavoritesViewModel = viewModel()
|
||||
viewModel: RssFavoritesViewModel = koinViewModel()
|
||||
) {
|
||||
val state by viewModel.state.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.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||
import io.legado.app.ui.widget.components.AppFloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
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.unit.dp
|
||||
import androidx.core.net.toUri
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import io.legado.app.R
|
||||
import io.legado.app.data.entities.RuleSub
|
||||
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.theme.LegadoTheme
|
||||
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.EmptyMessage
|
||||
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.utils.showDialogFragment
|
||||
import io.legado.app.utils.toastOnUi
|
||||
import org.koin.androidx.compose.koinViewModel
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
|
||||
@Composable
|
||||
fun RuleSubScreen(
|
||||
onBackClick: () -> Unit,
|
||||
viewModel: RuleSubViewModel = viewModel()
|
||||
viewModel: RuleSubViewModel = koinViewModel()
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val state by viewModel.state.collectAsState()
|
||||
|
||||
@@ -55,7 +55,7 @@ fun adaptiveContentPadding(
|
||||
bottom: Dp
|
||||
): PaddingValues {
|
||||
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(
|
||||
top = adjustedTop,
|
||||
bottom = bottom,
|
||||
@@ -70,7 +70,7 @@ fun adaptiveContentPadding(
|
||||
bottom: Dp,
|
||||
horizontal: Dp
|
||||
): 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(
|
||||
top = adjustedTop,
|
||||
bottom = bottom,
|
||||
|
||||
@@ -5,16 +5,16 @@ import androidx.compose.animation.ExperimentalSharedTransitionApi
|
||||
import androidx.compose.animation.SharedTransitionScope
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.horizontalScroll
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.IntrinsicSize
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
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.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
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.material3.Surface
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import io.legado.app.data.entities.SearchBook
|
||||
import io.legado.app.domain.model.BookShelfState
|
||||
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.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)
|
||||
@Composable
|
||||
@@ -72,17 +53,39 @@ fun SearchBookListItem(
|
||||
.clickable(onClick = onClick)
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||
) {
|
||||
CoilBookCover(
|
||||
name = book.name,
|
||||
author = book.author,
|
||||
path = book.coverUrl,
|
||||
modifier = Modifier.width(72.dp).aspectRatio(5f / 7f),
|
||||
sourceOrigin = book.origin,
|
||||
sharedTransitionScope = sharedTransitionScope,
|
||||
animatedVisibilityScope = animatedVisibilityScope,
|
||||
sharedCoverKey = sharedCoverKey,
|
||||
showLoadingPlaceholder = sharedCoverKey == null
|
||||
)
|
||||
Box(modifier = Modifier
|
||||
.width(72.dp)
|
||||
.aspectRatio(5f / 7f)) {
|
||||
CoilBookCover(
|
||||
name = book.name,
|
||||
author = book.author,
|
||||
path = book.coverUrl,
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
sourceOrigin = book.origin,
|
||||
sharedTransitionScope = sharedTransitionScope,
|
||||
animatedVisibilityScope = animatedVisibilityScope,
|
||||
sharedCoverKey = sharedCoverKey,
|
||||
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))
|
||||
|
||||
@@ -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)
|
||||
@Composable
|
||||
fun SearchBookGridItem(
|
||||
@@ -184,19 +171,41 @@ fun SearchBookGridItem(
|
||||
.clickable(onClick = onClick)
|
||||
.padding(4.dp)
|
||||
) {
|
||||
CoilBookCover(
|
||||
name = book.name,
|
||||
author = book.author,
|
||||
path = book.coverUrl,
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.aspectRatio(5f / 7f),
|
||||
sourceOrigin = book.origin,
|
||||
sharedTransitionScope = sharedTransitionScope,
|
||||
animatedVisibilityScope = animatedVisibilityScope,
|
||||
sharedCoverKey = sharedCoverKey,
|
||||
showLoadingPlaceholder = sharedCoverKey == null
|
||||
)
|
||||
.aspectRatio(5f / 7f)
|
||||
) {
|
||||
CoilBookCover(
|
||||
name = book.name,
|
||||
author = book.author,
|
||||
path = book.coverUrl,
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
sourceOrigin = book.origin,
|
||||
sharedTransitionScope = sharedTransitionScope,
|
||||
animatedVisibilityScope = animatedVisibilityScope,
|
||||
sharedCoverKey = sharedCoverKey,
|
||||
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))
|
||||
|
||||
|
||||
@@ -27,12 +27,18 @@ fun PillDivider(
|
||||
val isMiuix = ThemeResolver.isMiuixEngine(LegadoTheme.composeEngine)
|
||||
if (isMiuix) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 2.dp)
|
||||
.height(4.dp)
|
||||
.background(MiuixTheme.colorScheme.dividerLine)
|
||||
)
|
||||
.padding(vertical = 4.dp),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(0.8f)
|
||||
.height(thickness)
|
||||
.background(MiuixTheme.colorScheme.dividerLine)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Box(
|
||||
modifier = modifier
|
||||
|
||||
+4
-4
@@ -48,7 +48,7 @@ fun CompactDropdownSettingItem(
|
||||
entryValues: Array<String>,
|
||||
description: String? = null,
|
||||
imageVector: ImageVector? = null,
|
||||
color: Color? = LegadoTheme.colorScheme.surface,
|
||||
color: Color? = LegadoTheme.colorScheme.onSheetContent,
|
||||
shape: Shape = MaterialTheme.shapes.small,
|
||||
onValueChange: (String) -> Unit
|
||||
) {
|
||||
@@ -126,7 +126,7 @@ fun CompactSliderSettingItem(
|
||||
steps: Int = 0,
|
||||
description: String? = null,
|
||||
imageVector: ImageVector? = null,
|
||||
color: Color? = MaterialTheme.colorScheme.surface,
|
||||
color: Color? = LegadoTheme.colorScheme.onSheetContent,
|
||||
shape: Shape = MaterialTheme.shapes.small,
|
||||
onValueChange: (Float) -> Unit
|
||||
) {
|
||||
@@ -222,7 +222,7 @@ fun CompactSwitchSettingItem(
|
||||
checked: Boolean,
|
||||
description: String? = null,
|
||||
imageVector: ImageVector? = null,
|
||||
color: Color? = MaterialTheme.colorScheme.surface,
|
||||
color: Color? = LegadoTheme.colorScheme.onSheetContent,
|
||||
shape: Shape = MaterialTheme.shapes.small,
|
||||
enabled: Boolean = true,
|
||||
onCheckedChange: (Boolean) -> Unit
|
||||
@@ -260,7 +260,7 @@ fun CompactClickableSettingItem(
|
||||
title: String,
|
||||
description: String? = null,
|
||||
imageVector: ImageVector? = null,
|
||||
color: Color? = MaterialTheme.colorScheme.surface,
|
||||
color: Color? = LegadoTheme.colorScheme.onSheetContent,
|
||||
shape: Shape = MaterialTheme.shapes.small,
|
||||
trailingContent: (@Composable () -> Unit)? = null,
|
||||
onClick: () -> Unit
|
||||
|
||||
Reference in New Issue
Block a user