diff --git a/app/src/main/assets/defaultData/coverRule.json b/app/src/main/assets/defaultData/coverRule.json index 5efef1ee6..d37be5cbf 100644 --- a/app/src/main/assets/defaultData/coverRule.json +++ b/app/src/main/assets/defaultData/coverRule.json @@ -1,5 +1,5 @@ { - "enable": false, - "searchUrl": "", - "coverRule": "" -} \ No newline at end of file + "enable": true, + "searchUrl": "data:;base64,{{java.base64Encode(key)}},{\"type\":\"lyc\"}", + "coverRule": "@js:\nvar key = java.hexDecodeToString(result);\nvar url1 = `https://pre-api.tuishujun.com/api/searchBook?search_value=${key}&page=1&pageSize=20`;\nvar url2 = `http://m.ypshuo.com/api/novel/search?keyword=${key}&searchType=1&page=1`;\nvar [rr1, rr2] = java.ajaxAll([url1, url2]).map(r => r.body());\nfunction jjson(str, rule) {\n try {\n return com.jayway.jsonpath.JsonPath.read(str, rule);\n } catch (e) {\n return [];\n }\n}\nrr1 = jjson(rr1, '$.data.data[*]');\nrr2 = jjson(rr2, '$.data.data[*]');\nvar na = String(book.name),\n au = String(book.author);\nfunction search() {\n for (let char of rr1) {\n //本地书名包含搜索结果书名\n if (na.includes(char.title + '')) {\n let au2 = char.author_nickname + '';\n //作者匹配\n if (au.includes(au2) || au2.includes(au)) {\n return char.cover;\n }\n }\n }\n for (let char of rr2) {\n if (na.includes(char.novel_name + '')) {\n let au2 = char.author_name + '';\n if (au.includes(au2) || au2.includes(au)) {\n return char.novel_img;\n }\n }\n }\n return '';\n}\nsearch()" +} diff --git a/app/src/main/assets/defaultData/rssSources.json b/app/src/main/assets/defaultData/rssSources.json index 220830854..fe51488c7 100644 --- a/app/src/main/assets/defaultData/rssSources.json +++ b/app/src/main/assets/defaultData/rssSources.json @@ -1,42 +1 @@ -[ - { - "customOrder": 2, - "enableJs": true, - "enabled": true, - "singleUrl": true, - "sourceGroup": "legado", - "sourceIcon": "https://cdn.jsdelivr.net/gh/gedoor/legado@master/app/src/main/res/mipmap-hdpi/ic_launcher.png", - "sourceName": "使用说明", - "sourceUrl": "https://www.yuque.com/legado" - }, - { - "customOrder": 3, - "enableJs": true, - "enabled": true, - "singleUrl": true, - "sourceGroup": "legado", - "sourceIcon": "http://mmbiz.qpic.cn/mmbiz_png/hpfMV8hEuL2eS6vnCxvTzoOiaCAibV6exBzJWq9xMic9xDg3YXAick87tsfafic0icRwkQ5ibV0bJ84JtSuxhPuEDVquA/0?wx_fmt=png", - "sourceName": "小说拾遗", - "sourceUrl": "snssdk1128://user/profile/562564899806367" - }, - { - "customOrder": 4, - "enableJs": true, - "enabled": true, - "singleUrl": true, - "sourceGroup": "legado", - "sourceIcon": "https://cdn.jsdelivr.net/gh/mgz0227/meowcloud/icon.png", - "sourceName": "Meow云", - "sourceUrl": "https://pan.miaogongzi.net" - }, - { - "customOrder": 5, - "enableJs": true, - "enabled": true, - "singleUrl": true, - "sourceGroup": "legado", - "sourceIcon": "https://cdn.jsdelivr.net/gh/gedoor/legado@master/app/src/main/res/mipmap-hdpi/ic_launcher.png", - "sourceName": "烏雲净化", - "sourceUrl": "https://www.lanzoux.com/b0bw8jwoh" - } -] \ No newline at end of file +[] diff --git a/app/src/main/java/io/legado/app/di/appModule.kt b/app/src/main/java/io/legado/app/di/appModule.kt index 50fde7285..be8e0339c 100644 --- a/app/src/main/java/io/legado/app/di/appModule.kt +++ b/app/src/main/java/io/legado/app/di/appModule.kt @@ -45,6 +45,7 @@ import io.legado.app.domain.usecase.CacheBookChaptersUseCase import io.legado.app.domain.usecase.ChangeBookSourceUseCase import io.legado.app.domain.usecase.ClearBookCacheUseCase import io.legado.app.domain.usecase.DeleteBooksUseCase +import io.legado.app.domain.usecase.ExploreKindUiUseCase import io.legado.app.domain.usecase.GetReadingProgressUseCase import io.legado.app.domain.usecase.RemoveBookGroupAssignmentUseCase import io.legado.app.domain.usecase.ResolveBookShelfStateUseCase @@ -103,7 +104,6 @@ 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 diff --git a/app/src/main/java/io/legado/app/ui/widget/components/explore/ExploreKindUiUseCase.kt b/app/src/main/java/io/legado/app/domain/usecase/ExploreKindUiUseCase.kt similarity index 96% rename from app/src/main/java/io/legado/app/ui/widget/components/explore/ExploreKindUiUseCase.kt rename to app/src/main/java/io/legado/app/domain/usecase/ExploreKindUiUseCase.kt index 05c3882a8..3d90ca26b 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/explore/ExploreKindUiUseCase.kt +++ b/app/src/main/java/io/legado/app/domain/usecase/ExploreKindUiUseCase.kt @@ -1,4 +1,4 @@ -package io.legado.app.ui.widget.components.explore +package io.legado.app.domain.usecase import androidx.appcompat.app.AppCompatActivity import com.script.rhino.runScriptWithContext @@ -10,7 +10,7 @@ import io.legado.app.data.entities.rule.ExploreKind import io.legado.app.help.source.getExploreInfoMap import io.legado.app.ui.login.SourceLoginJsExtensions import io.legado.app.utils.InfoMap -import kotlinx.coroutines.Dispatchers.IO +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import java.util.concurrent.ConcurrentHashMap @@ -76,7 +76,7 @@ class ExploreKindUiUseCase( override fun reUiView() = onRefreshKinds() } ) - withContext(IO) { + withContext(Dispatchers.IO) { evalButtonClick(actionText, source, effectiveInfoMap, title, sourceJsExtensions) } } @@ -92,7 +92,7 @@ class ExploreKindUiUseCase( private suspend fun getOrLoadBookSource(sourceUrl: String): BookSource? { sourceCache[sourceUrl]?.let { return it } - return withContext(IO) { + return withContext(Dispatchers.IO) { bookSourceDao.getBookSource(sourceUrl) }?.also { source -> sourceCache[sourceUrl] = source @@ -127,4 +127,4 @@ class ExploreKindUiUseCase( AppLog.put("ExploreUI Button $name JavaScript error", e) } } -} +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowScreen.kt b/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowScreen.kt index 620444d58..e0db349ce 100644 --- a/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowScreen.kt +++ b/app/src/main/java/io/legado/app/ui/book/explore/ExploreShowScreen.kt @@ -61,6 +61,7 @@ import dev.chrisbanes.haze.HazeState import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi import io.legado.app.data.entities.SearchBook import io.legado.app.domain.model.BookShelfState +import io.legado.app.domain.usecase.ExploreKindUiUseCase import io.legado.app.ui.main.bookCoverSharedElementKey import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.theme.ThemeResolver @@ -74,7 +75,6 @@ import io.legado.app.ui.widget.components.book.SearchBookListItem import io.legado.app.ui.widget.components.button.AnimatedTextButton import io.legado.app.ui.widget.components.card.TextCard import io.legado.app.ui.widget.components.explore.ExploreKindMultiTypeItem -import io.legado.app.ui.widget.components.explore.ExploreKindUiUseCase import io.legado.app.ui.widget.components.explore.calculateExploreKindRows import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem diff --git a/app/src/main/java/io/legado/app/ui/book/group/GroupEditSheet.kt b/app/src/main/java/io/legado/app/ui/book/group/GroupEditSheet.kt index 045ee4824..58a249b21 100644 --- a/app/src/main/java/io/legado/app/ui/book/group/GroupEditSheet.kt +++ b/app/src/main/java/io/legado/app/ui/book/group/GroupEditSheet.kt @@ -36,7 +36,7 @@ import io.legado.app.ui.widget.components.alert.AppAlertDialog import io.legado.app.ui.widget.components.button.ConfirmDismissButtonsRow import io.legado.app.ui.widget.components.button.MediumIconButton import io.legado.app.ui.widget.components.card.GlassCard -import io.legado.app.ui.widget.components.cover.CoilBookCover +import io.legado.app.ui.widget.components.image.cover.CoilBookCover import io.legado.app.ui.widget.components.modalBottomSheet.AppModalBottomSheet import io.legado.app.ui.widget.components.settingItem.CompactDropdownSettingItem import io.legado.app.ui.widget.components.settingItem.CompactSwitchSettingItem diff --git a/app/src/main/java/io/legado/app/ui/book/info/BookInfoScreen.kt b/app/src/main/java/io/legado/app/ui/book/info/BookInfoScreen.kt index 1f2fd67e2..74aebae4f 100644 --- a/app/src/main/java/io/legado/app/ui/book/info/BookInfoScreen.kt +++ b/app/src/main/java/io/legado/app/ui/book/info/BookInfoScreen.kt @@ -91,9 +91,9 @@ import io.legado.app.ui.widget.components.AppTextField import io.legado.app.ui.widget.components.alert.AppAlertDialog import io.legado.app.ui.widget.components.card.GlassCard 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.buildCoverImageRequest import io.legado.app.ui.widget.components.icon.AppIcon +import io.legado.app.ui.widget.components.image.cover.CoilBookCover +import io.legado.app.ui.widget.components.image.cover.buildCoverImageRequest import io.legado.app.ui.widget.components.log.AppLogSheet import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem diff --git a/app/src/main/java/io/legado/app/ui/book/info/BookInfoSheets.kt b/app/src/main/java/io/legado/app/ui/book/info/BookInfoSheets.kt index 3c120ef71..c4a64876b 100644 --- a/app/src/main/java/io/legado/app/ui/book/info/BookInfoSheets.kt +++ b/app/src/main/java/io/legado/app/ui/book/info/BookInfoSheets.kt @@ -77,7 +77,7 @@ import io.legado.app.ui.widget.components.button.SmallIconButton import io.legado.app.ui.widget.components.card.GlassCard import io.legado.app.ui.widget.components.card.SelectionItemCard import io.legado.app.ui.widget.components.checkBox.AppCheckbox -import io.legado.app.ui.widget.components.cover.CoilBookCover +import io.legado.app.ui.widget.components.image.cover.CoilBookCover import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem import io.legado.app.ui.widget.components.modalBottomSheet.AppModalBottomSheet diff --git a/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt b/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt index 7a7fe003b..b53a9091e 100644 --- a/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt @@ -50,7 +50,7 @@ import io.legado.app.model.analyzeRule.AnalyzeUrl import io.legado.app.model.localBook.LocalBook import io.legado.app.model.webBook.WebBook import io.legado.app.ui.config.coverConfig.CoverConfig -import io.legado.app.ui.widget.components.cover.buildCoverImageRequest +import io.legado.app.ui.widget.components.image.cover.buildCoverImageRequest import io.legado.app.utils.ArchiveUtils import io.legado.app.utils.GSON import io.legado.app.utils.ImageSaveUtils diff --git a/app/src/main/java/io/legado/app/ui/book/info/edit/BookInfoEditScreen.kt b/app/src/main/java/io/legado/app/ui/book/info/edit/BookInfoEditScreen.kt index 6ad0c0902..91c168c98 100644 --- a/app/src/main/java/io/legado/app/ui/book/info/edit/BookInfoEditScreen.kt +++ b/app/src/main/java/io/legado/app/ui/book/info/edit/BookInfoEditScreen.kt @@ -60,7 +60,7 @@ import io.legado.app.ui.widget.components.AppScaffold import io.legado.app.ui.widget.components.AppTextField import io.legado.app.ui.widget.components.alert.AppAlertDialog import io.legado.app.ui.widget.components.button.MediumOutlinedIconButton -import io.legado.app.ui.widget.components.cover.CoilBookCover +import io.legado.app.ui.widget.components.image.cover.CoilBookCover import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem import io.legado.app.ui.widget.components.settingItem.SwitchSettingItem diff --git a/app/src/main/java/io/legado/app/ui/book/manage/BookshelfManageScreen.kt b/app/src/main/java/io/legado/app/ui/book/manage/BookshelfManageScreen.kt index d503b7192..e4b7e3dba 100644 --- a/app/src/main/java/io/legado/app/ui/book/manage/BookshelfManageScreen.kt +++ b/app/src/main/java/io/legado/app/ui/book/manage/BookshelfManageScreen.kt @@ -88,10 +88,10 @@ import io.legado.app.ui.widget.components.card.GlassCard import io.legado.app.ui.widget.components.card.ReorderableSelectionItem import io.legado.app.ui.widget.components.card.SelectionItemCard 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.divider.PillDivider import io.legado.app.ui.widget.components.filePicker.FilePickerSheet import io.legado.app.ui.widget.components.icon.AppIcons +import io.legado.app.ui.widget.components.image.cover.CoilBookCover import io.legado.app.ui.widget.components.list.ListScaffold import io.legado.app.ui.widget.components.list.ListUiState import io.legado.app.ui.widget.components.log.AppLogSheet diff --git a/app/src/main/java/io/legado/app/ui/book/readRecord/ReadRecordOverviewScreen.kt b/app/src/main/java/io/legado/app/ui/book/readRecord/ReadRecordOverviewScreen.kt index 6939b8c74..3e81955ee 100644 --- a/app/src/main/java/io/legado/app/ui/book/readRecord/ReadRecordOverviewScreen.kt +++ b/app/src/main/java/io/legado/app/ui/book/readRecord/ReadRecordOverviewScreen.kt @@ -56,8 +56,8 @@ import io.legado.app.ui.theme.adaptiveHorizontalPadding import io.legado.app.ui.widget.components.AppScaffold import io.legado.app.ui.widget.components.button.MediumIconButton import io.legado.app.ui.widget.components.card.GlassCard -import io.legado.app.ui.widget.components.cover.CoilBookCover import io.legado.app.ui.widget.components.heatmap.HeatmapMode +import io.legado.app.ui.widget.components.image.cover.CoilBookCover import io.legado.app.ui.widget.components.tabRow.AppTabRow import io.legado.app.ui.widget.components.text.AppText import io.legado.app.ui.widget.components.topbar.GlassMediumFlexibleTopAppBar diff --git a/app/src/main/java/io/legado/app/ui/book/readRecord/ReadRecordScreen.kt b/app/src/main/java/io/legado/app/ui/book/readRecord/ReadRecordScreen.kt index 6d63a261f..4feb95a4a 100644 --- a/app/src/main/java/io/legado/app/ui/book/readRecord/ReadRecordScreen.kt +++ b/app/src/main/java/io/legado/app/ui/book/readRecord/ReadRecordScreen.kt @@ -66,8 +66,8 @@ import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.theme.adaptiveContentPaddingOnlyVertical import io.legado.app.ui.theme.adaptiveHorizontalPadding import io.legado.app.ui.theme.fadingEdge -import io.legado.app.ui.widget.CollapsibleHeader import io.legado.app.ui.widget.components.AppScaffold +import io.legado.app.ui.widget.components.CollapsibleHeader import io.legado.app.ui.widget.components.EmptyMessage import io.legado.app.ui.widget.components.SearchBar import io.legado.app.ui.widget.components.alert.AppAlertDialog @@ -75,7 +75,6 @@ import io.legado.app.ui.widget.components.button.AppIconButton import io.legado.app.ui.widget.components.card.GlassCard import io.legado.app.ui.widget.components.card.TextCard import io.legado.app.ui.widget.components.checkBox.CheckboxItem -import io.legado.app.ui.widget.components.cover.CoilBookCover import io.legado.app.ui.widget.components.heatmap.HEATMAP_CALENDAR_TITLE import io.legado.app.ui.widget.components.heatmap.HeatmapCalendarEndAction import io.legado.app.ui.widget.components.heatmap.HeatmapCalendarStartAction @@ -89,6 +88,7 @@ import io.legado.app.ui.widget.components.heatmap.rememberDateRange import io.legado.app.ui.widget.components.heatmap.rememberDaysInRange import io.legado.app.ui.widget.components.heatmap.rememberWeeks import io.legado.app.ui.widget.components.icon.AppIcon +import io.legado.app.ui.widget.components.image.cover.CoilBookCover import io.legado.app.ui.widget.components.list.TopFloatingStickyItem import io.legado.app.ui.widget.components.modalBottomSheet.AppModalBottomSheet import io.legado.app.ui.widget.components.swipe.SwipeAction diff --git a/app/src/main/java/io/legado/app/ui/book/readRecord/component/ReadRecordListItems.kt b/app/src/main/java/io/legado/app/ui/book/readRecord/component/ReadRecordListItems.kt index 9dbd6b272..aa507d445 100644 --- a/app/src/main/java/io/legado/app/ui/book/readRecord/component/ReadRecordListItems.kt +++ b/app/src/main/java/io/legado/app/ui/book/readRecord/component/ReadRecordListItems.kt @@ -2,8 +2,20 @@ package io.legado.app.ui.book.readRecord.component import androidx.compose.foundation.basicMarquee import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* -import androidx.compose.runtime.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.buildAnnotatedString @@ -16,7 +28,7 @@ import io.legado.app.ui.book.readRecord.ReadRecordFormatter import io.legado.app.ui.book.readRecord.ReadRecordViewModel import io.legado.app.ui.book.readRecord.TimelineItem import io.legado.app.ui.theme.LegadoTheme -import io.legado.app.ui.widget.components.cover.CoilBookCover +import io.legado.app.ui.widget.components.image.cover.CoilBookCover import io.legado.app.ui.widget.components.text.AppText import io.legado.app.utils.StringUtils.formatFriendlyDate diff --git a/app/src/main/java/io/legado/app/ui/book/readRecord/component/ReadRecordSummary.kt b/app/src/main/java/io/legado/app/ui/book/readRecord/component/ReadRecordSummary.kt index c0554a42d..24f4aa705 100644 --- a/app/src/main/java/io/legado/app/ui/book/readRecord/component/ReadRecordSummary.kt +++ b/app/src/main/java/io/legado/app/ui/book/readRecord/component/ReadRecordSummary.kt @@ -1,10 +1,21 @@ package io.legado.app.ui.book.readRecord.component -import androidx.compose.foundation.layout.* -import androidx.compose.runtime.* +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import io.legado.app.ui.book.readRecord.ReadRecordFormatter import io.legado.app.ui.book.readRecord.ReadRecordUiState @@ -12,7 +23,7 @@ import io.legado.app.ui.book.readRecord.ReadRecordViewModel import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.theme.adaptiveHorizontalPadding import io.legado.app.ui.widget.components.card.GlassCard -import io.legado.app.ui.widget.components.cover.CoilBookCover +import io.legado.app.ui.widget.components.image.cover.CoilBookCover import io.legado.app.ui.widget.components.text.AppText import java.time.format.DateTimeFormatter diff --git a/app/src/main/java/io/legado/app/ui/book/search/SearchScreen.kt b/app/src/main/java/io/legado/app/ui/book/search/SearchScreen.kt index eb33451bc..59f54dd80 100644 --- a/app/src/main/java/io/legado/app/ui/book/search/SearchScreen.kt +++ b/app/src/main/java/io/legado/app/ui/book/search/SearchScreen.kt @@ -14,7 +14,6 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items @@ -23,17 +22,12 @@ import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Book import androidx.compose.material.icons.filled.Close -import androidx.compose.material.icons.filled.History import androidx.compose.material.icons.filled.Layers import androidx.compose.material.icons.filled.PlayArrow import androidx.compose.material.icons.filled.Stop import androidx.compose.material3.ExperimentalMaterial3Api -import io.legado.app.ui.widget.components.progressIndicator.AppCircularProgressIndicator import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults -import io.legado.app.ui.widget.components.topbar.GlassMediumFlexibleTopAppBar -import io.legado.app.ui.widget.components.topbar.M3GlassScrollBehavior -import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect @@ -42,9 +36,9 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberUpdatedState +import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.runtime.snapshotFlow -import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll @@ -58,6 +52,7 @@ import androidx.lifecycle.compose.LocalLifecycleOwner import androidx.lifecycle.compose.collectAsStateWithLifecycle import io.legado.app.R import io.legado.app.data.entities.SearchKeyword +import io.legado.app.ui.main.bookCoverSharedElementKey import io.legado.app.ui.main.bookshelf.BookShelfItem import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.theme.ThemeResolver @@ -68,22 +63,23 @@ import io.legado.app.ui.widget.components.AppFloatingActionButton import io.legado.app.ui.widget.components.AppScaffold import io.legado.app.ui.widget.components.SearchBar import io.legado.app.ui.widget.components.alert.AppAlertDialog -import io.legado.app.ui.widget.components.modalBottomSheet.AppModalBottomSheet import io.legado.app.ui.widget.components.book.SearchBookListItem import io.legado.app.ui.widget.components.button.SmallIconButton import io.legado.app.ui.widget.components.button.SmallTextButton import io.legado.app.ui.widget.components.card.NormalCard import io.legado.app.ui.widget.components.card.SelectionItemCard +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.list.TopFloatingStickyItem +import io.legado.app.ui.widget.components.modalBottomSheet.AppModalBottomSheet +import io.legado.app.ui.widget.components.progressIndicator.AppCircularProgressIndicator +import io.legado.app.ui.widget.components.text.AppText +import io.legado.app.ui.widget.components.topbar.GlassMediumFlexibleTopAppBar +import io.legado.app.ui.widget.components.topbar.GlassTopAppBarDefaults +import io.legado.app.ui.widget.components.topbar.M3GlassScrollBehavior import io.legado.app.ui.widget.components.topbar.TopBarActionButton import io.legado.app.ui.widget.components.topbar.TopBarAnimatedActionButton import io.legado.app.ui.widget.components.topbar.TopBarNavigationButton -import io.legado.app.ui.widget.components.icon.AppIcon -import io.legado.app.ui.widget.components.icon.AppIcons -import io.legado.app.ui.book.search.ScopeSelectSheet -import io.legado.app.ui.widget.components.list.TopFloatingStickyItem -import io.legado.app.ui.widget.components.tabRow.AppTabRow -import io.legado.app.ui.widget.components.text.AppText -import io.legado.app.ui.main.bookCoverSharedElementKey import io.legado.app.utils.toastOnUi import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.debounce @@ -480,19 +476,17 @@ fun SearchScreen( viewModel.onIntent(SearchIntent.DismissEmptyScopeAction) }, title = stringResource(R.string.draw), + textProvider = { + if (wasPrecisionSearch) { + stringResource(R.string.search_empty_scope_disable_precision, scopeDisplay) + } else { + stringResource(R.string.search_empty_scope_switch_all, scopeDisplay) + } + }, confirmText = stringResource(R.string.ok), onConfirm = { viewModel.onIntent(SearchIntent.ConfirmEmptyScopeAction) }, dismissText = stringResource(R.string.cancel), onDismiss = { viewModel.onIntent(SearchIntent.DismissEmptyScopeAction) }, - content = { - Text( - text = if (it.wasPrecisionSearch) { - stringResource(R.string.search_empty_scope_disable_precision, it.scopeDisplay) - } else { - stringResource(R.string.search_empty_scope_switch_all, it.scopeDisplay) - } - ) - } ) ScopeSelectSheet( @@ -681,12 +675,8 @@ private fun SearchResultFooter( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp), ) { - Box( - modifier = Modifier.size(18.dp), - contentAlignment = Alignment.Center - ) { - AppCircularProgressIndicator() - } + AppCircularProgressIndicator() + Spacer(modifier = Modifier.padding(horizontal = 8.dp)) AppText(text = stringResource(R.string.is_loading)) } } diff --git a/app/src/main/java/io/legado/app/ui/book/toc/TocScreen.kt b/app/src/main/java/io/legado/app/ui/book/toc/TocScreen.kt index 21cb8004e..9a80a0c9a 100644 --- a/app/src/main/java/io/legado/app/ui/book/toc/TocScreen.kt +++ b/app/src/main/java/io/legado/app/ui/book/toc/TocScreen.kt @@ -84,10 +84,10 @@ import io.legado.app.ui.replace.ReplaceEditRoute import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.theme.adaptiveContentPaddingOnlyVertical import io.legado.app.ui.theme.adaptiveHorizontalPadding -import io.legado.app.ui.widget.CollapsibleHeader import io.legado.app.ui.widget.components.ActionItem import io.legado.app.ui.widget.components.AppFloatingActionButtonMenu import io.legado.app.ui.widget.components.AppScaffold +import io.legado.app.ui.widget.components.CollapsibleHeader import io.legado.app.ui.widget.components.EmptyMessage import io.legado.app.ui.widget.components.FabMenuItem import io.legado.app.ui.widget.components.SelectionBottomBar diff --git a/app/src/main/java/io/legado/app/ui/book/toc/rule/TxtTocRuleDialog.kt b/app/src/main/java/io/legado/app/ui/book/toc/rule/TxtTocRuleDialog.kt deleted file mode 100644 index 26dd1caf7..000000000 --- a/app/src/main/java/io/legado/app/ui/book/toc/rule/TxtTocRuleDialog.kt +++ /dev/null @@ -1,328 +0,0 @@ -package io.legado.app.ui.book.toc.rule - -import android.annotation.SuppressLint -import android.content.Context -import android.os.Bundle -import android.view.MenuItem -import android.view.View -import android.view.ViewGroup -import androidx.appcompat.widget.Toolbar -import androidx.core.os.bundleOf -import androidx.fragment.app.viewModels -import androidx.lifecycle.lifecycleScope -import androidx.recyclerview.widget.DiffUtil -import androidx.recyclerview.widget.ItemTouchHelper -import androidx.recyclerview.widget.RecyclerView -import io.legado.app.R -import io.legado.app.base.BaseDialogFragment -import io.legado.app.base.adapter.ItemViewHolder -import io.legado.app.base.adapter.RecyclerAdapter -import io.legado.app.constant.AppLog -import io.legado.app.data.appDb -import io.legado.app.data.entities.TxtTocRule -import io.legado.app.databinding.DialogEditTextBinding -import io.legado.app.databinding.DialogTocRegexBinding -import io.legado.app.databinding.ItemTocRegexBinding -import io.legado.app.lib.dialogs.alert -//import io.legado.app.lib.theme.backgroundColor -//import io.legado.app.lib.theme.primaryColor -import io.legado.app.ui.association.ImportTxtTocRuleDialog -import io.legado.app.ui.file.HandleFileContract -import io.legado.app.ui.qrcode.QrCodeResult -import io.legado.app.ui.widget.recycler.ItemTouchCallback -import io.legado.app.ui.widget.recycler.VerticalDivider -import io.legado.app.utils.ACache -import io.legado.app.utils.isAbsUrl -import io.legado.app.utils.launch -import io.legado.app.utils.readText -import io.legado.app.utils.showDialogFragment -import io.legado.app.utils.showHelp -import io.legado.app.utils.splitNotBlank -import io.legado.app.utils.toastOnUi -import io.legado.app.utils.viewbindingdelegate.viewBinding -import kotlinx.coroutines.Dispatchers.IO -import kotlinx.coroutines.flow.catch -import kotlinx.coroutines.flow.conflate -import kotlinx.coroutines.flow.flowOn -import kotlinx.coroutines.launch - -/** - * txt目录规则 - */ -class TxtTocRuleDialog() : BaseDialogFragment(R.layout.dialog_toc_regex), - Toolbar.OnMenuItemClickListener, - TxtTocRuleEditDialog.Callback { - - constructor(tocRegex: String?) : this() { - arguments = Bundle().apply { - putString("tocRegex", tocRegex) - } - } - - private val importTocRuleKey = "tocRuleUrl" - private val viewModel: TxtTocRuleViewModel by viewModels() - private val binding by viewBinding(DialogTocRegexBinding::bind) - private val adapter by lazy { TocRegexAdapter(requireContext()) } - var selectedName: String? = null - private var durRegex: String? = null - private val qrCodeResult = registerForActivityResult(QrCodeResult()) { - it ?: return@registerForActivityResult - showDialogFragment(ImportTxtTocRuleDialog(it)) - } - private val importDoc = registerForActivityResult(HandleFileContract()) { - kotlin.runCatching { - it.uri?.readText(requireContext())?.let { - showDialogFragment(ImportTxtTocRuleDialog(it)) - } - }.onFailure { - toastOnUi("readTextError:${it.localizedMessage}") - } - } - - override fun onStart() { - super.onStart() - } - - override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { - //binding.toolBar.setBackgroundColor(primaryColor) - durRegex = arguments?.getString("tocRegex") - binding.toolBar.setTitle(R.string.txt_toc_rule) - binding.toolBar.inflateMenu(R.menu.txt_toc_rule) - //binding.toolBar.menu.applyTint(requireContext()) - binding.toolBar.setOnMenuItemClickListener(this) - initView() - initData() - } - - private fun initView() = binding.run { - recyclerView.addItemDecoration(VerticalDivider(requireContext())) - recyclerView.adapter = adapter - val itemTouchCallback = ItemTouchCallback(adapter) - itemTouchCallback.isCanDrag = true - ItemTouchHelper(itemTouchCallback).attachToRecyclerView(recyclerView) - tvCancel.setOnClickListener { - dismissAllowingStateLoss() - } - tvOk.setOnClickListener { - adapter.getItems().forEach { tocRule -> - if (selectedName == tocRule.name) { - val callBack = activity as? CallBack - callBack?.onTocRegexDialogResult(tocRule.rule) - dismissAllowingStateLoss() - return@setOnClickListener - } - } - } - } - - private fun initData() { - lifecycleScope.launch { - appDb.txtTocRuleDao.observeAll().catch { - AppLog.put("TXT目录规则对话框获取数据失败\n${it.localizedMessage}", it) - }.flowOn(IO).conflate().collect { tocRules -> - initSelectedName(tocRules) - adapter.setItems(tocRules, adapter.diffItemCallBack) - } - } - } - - private fun initSelectedName(tocRules: List) { - if (selectedName == null && durRegex != null) { - tocRules.forEach { - if (durRegex == it.rule) { - selectedName = it.name - return@forEach - } - } - if (selectedName == null) { - selectedName = "" - } - } - } - - override fun onMenuItemClick(item: MenuItem?): Boolean { - when (item?.itemId) { - R.id.menu_add -> showDialogFragment(TxtTocRuleEditDialog()) - R.id.menu_import_local -> importDoc.launch { - mode = HandleFileContract.FILE - allowExtensions = arrayOf("txt", "json") - } - R.id.menu_import_onLine -> showImportDialog() - R.id.menu_import_qr -> qrCodeResult.launch() - R.id.menu_help -> showHelp("txtTocRuleHelp") - } - return false - } - - override fun saveTxtTocRule(txtTocRule: TxtTocRule) { - //viewModel.update(txtTocRule) - } - - @SuppressLint("InflateParams") - private fun showImportDialog() { - val aCache = ACache.get(cacheDir = false) - val defaultUrl = "https://gitee.com/fisher52/YueDuJson/raw/master/myTxtChapterRule.json" - val cacheUrls: MutableList = aCache - .getAsString(importTocRuleKey) - ?.splitNotBlank(",") - ?.toMutableList() - ?: mutableListOf() - if (!cacheUrls.contains(defaultUrl)) { - cacheUrls.add(0, defaultUrl) - } - requireContext().alert(titleResource = R.string.import_on_line) { - val alertBinding = DialogEditTextBinding.inflate(layoutInflater).apply { - editView.hint = "url" - editView.setFilterValues(cacheUrls) - editView.delCallBack = { - cacheUrls.remove(it) - aCache.put(importTocRuleKey, cacheUrls.joinToString(",")) - } - } - customView { alertBinding.root } - okButton { - val text = alertBinding.editView.text?.toString() - text?.let { - if (it.isAbsUrl() && !cacheUrls.contains(it)) { - cacheUrls.add(0, it) - aCache.put(importTocRuleKey, cacheUrls.joinToString(",")) - } - showDialogFragment(ImportTxtTocRuleDialog(it)) - } - } - cancelButton() - } - } - - inner class TocRegexAdapter(context: Context) : - RecyclerAdapter(context), - ItemTouchCallback.Callback { - - val diffItemCallBack = object : DiffUtil.ItemCallback() { - - override fun areItemsTheSame(oldItem: TxtTocRule, newItem: TxtTocRule): Boolean { - return oldItem.id == newItem.id - } - - override fun areContentsTheSame(oldItem: TxtTocRule, newItem: TxtTocRule): Boolean { - if (oldItem.name != newItem.name) { - return false - } - if (oldItem.enable != newItem.enable) { - return false - } - if (oldItem.example != newItem.example) { - return false - } - return true - } - - override fun getChangePayload(oldItem: TxtTocRule, newItem: TxtTocRule): Any? { - val payload = Bundle() - if (oldItem.name != newItem.name) { - payload.putBoolean("upName", true) - } - if (oldItem.enable != newItem.enable) { - payload.putBoolean("enabled", newItem.enable) - } - if (oldItem.example != newItem.example) { - payload.putBoolean("upExample", true) - } - if (payload.isEmpty) { - return null - } - return payload - } - } - - override fun getViewBinding(parent: ViewGroup): ItemTocRegexBinding { - return ItemTocRegexBinding.inflate(inflater, parent, false) - } - - override fun convert( - holder: ItemViewHolder, - binding: ItemTocRegexBinding, - item: TxtTocRule, - payloads: MutableList - ) { - binding.apply { - if (payloads.isEmpty()) { - //root.setBackgroundColor(context.backgroundColor) - rbRegexName.text = item.name - titleExample.text = item.example - rbRegexName.isChecked = item.name == selectedName - swtEnabled.isChecked = item.enable - } else { - for (i in payloads.indices) { - val bundle = payloads[i] as Bundle - bundle.keySet().forEach { - when (it) { - "upName" -> rbRegexName.text = item.name - "upExample" -> titleExample.text = item.example - "enabled" -> swtEnabled.isChecked = item.enable - "upSelect" -> rbRegexName.isChecked = item.name == selectedName - } - } - } - } - } - } - - override fun registerListener(holder: ItemViewHolder, binding: ItemTocRegexBinding) { - binding.apply { - rbRegexName.setOnCheckedChangeListener { buttonView, isChecked -> - if (buttonView.isPressed && isChecked) { - selectedName = getItem(holder.layoutPosition)?.name - updateItems(0, itemCount - 1, bundleOf("upSelect" to null)) - } - } - swtEnabled.setOnCheckedChangeListener { buttonView, isChecked -> - if (buttonView.isPressed) { - getItem(holder.layoutPosition)?.let { - it.enable = isChecked - //viewModel.update(it) - } - } - } - ivEdit.setOnClickListener { - showDialogFragment(TxtTocRuleEditDialog(getItem(holder.layoutPosition)?.id)) - } - ivDelete.setOnClickListener { - getItem(holder.layoutPosition)?.let { item -> - alert(R.string.draw) { - setMessage(getString(R.string.sure_del) + "\n" + item.name) - noButton() - yesButton { - //viewModel.delete(item) - } - } - } - } - } - } - - private var isMoved = false - - override fun swap(srcPosition: Int, targetPosition: Int): Boolean { - swapItem(srcPosition, targetPosition) - isMoved = true - return super.swap(srcPosition, targetPosition) - } - - override fun onClearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) { - super.onClearView(recyclerView, viewHolder) - if (isMoved) { - for ((index, item) in getItems().withIndex()) { - item.serialNumber = index + 1 - } - //viewModel.update(*getItems().toTypedArray()) - } - isMoved = false - } - } - - interface CallBack { - fun onTocRegexDialogResult(tocRegex: String) {} - } - -} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/book/toc/rule/TxtTocRuleEditDialog.kt b/app/src/main/java/io/legado/app/ui/book/toc/rule/TxtTocRuleEditDialog.kt deleted file mode 100644 index a3a26e473..000000000 --- a/app/src/main/java/io/legado/app/ui/book/toc/rule/TxtTocRuleEditDialog.kt +++ /dev/null @@ -1,147 +0,0 @@ -package io.legado.app.ui.book.toc.rule - -import android.app.Application -import android.os.Bundle -import android.view.MenuItem -import android.view.View -import android.view.ViewGroup -import androidx.appcompat.widget.Toolbar -import androidx.fragment.app.viewModels -import io.legado.app.R -import io.legado.app.base.BaseBottomSheetDialogFragment -import io.legado.app.base.BaseViewModel -import io.legado.app.constant.AppLog -import io.legado.app.data.appDb -import io.legado.app.data.entities.TxtTocRule -import io.legado.app.databinding.DialogTocRegexEditBinding -import io.legado.app.exception.NoStackTraceException -//import io.legado.app.lib.theme.primaryColor -import io.legado.app.utils.* -import io.legado.app.utils.viewbindingdelegate.viewBinding -import kotlinx.coroutines.Dispatchers -import java.util.regex.Pattern -import java.util.regex.PatternSyntaxException - -class TxtTocRuleEditDialog() : BaseBottomSheetDialogFragment(R.layout.dialog_toc_regex_edit), - Toolbar.OnMenuItemClickListener { - - constructor(id: Long?) : this() { - id ?: return - arguments = Bundle().apply { - putLong("id", id) - } - } - - private val binding by viewBinding(DialogTocRegexEditBinding::bind) - private val viewModel by viewModels() - private val callback get() = (parentFragment as? Callback) ?: activity as? Callback - - override fun onStart() { - super.onStart() - setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) - } - - override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { - //binding.toolBar.setBackgroundColor(primaryColor) - initMenu() - viewModel.initData(arguments?.getLong("id")) { - upRuleView(it) - } - } - - private fun initMenu() { - binding.toolBar.inflateMenu(R.menu.txt_toc_rule_edit) - //binding.toolBar.menu.applyTint(requireContext()) - binding.toolBar.setOnMenuItemClickListener(this) - } - - override fun onMenuItemClick(item: MenuItem?): Boolean { - when (item?.itemId) { - R.id.menu_save -> { - val tocRule = getRuleFromView() - if (checkValid(tocRule)) { - callback?.saveTxtTocRule(getRuleFromView()) - dismissAllowingStateLoss() - } - } - R.id.menu_copy_rule -> context?.sendToClip(GSON.toJson(getRuleFromView())) - R.id.menu_paste_rule -> viewModel.pasteRule { - upRuleView(it) - } - } - return true - } - - private fun checkValid(tocRule: TxtTocRule): Boolean { - if (tocRule.name.isEmpty()) { - toastOnUi("名称不能为空") - return false - } - - try { - Pattern.compile(tocRule.rule, Pattern.MULTILINE) - } catch (ex: PatternSyntaxException) { - AppLog.put("正则语法错误或不支持(txt):${ex.localizedMessage}", ex, true) - return false - } - - return true - } - - private fun upRuleView(tocRule: TxtTocRule?) { - binding.tvRuleName.setText(tocRule?.name) - binding.tvRuleRegex.setText(tocRule?.rule) - binding.tvRuleExample.setText(tocRule?.example) - } - - private fun getRuleFromView(): TxtTocRule { - val tocRule = viewModel.tocRule ?: TxtTocRule().apply { - viewModel.tocRule = this - } - binding.run { - tocRule.name = tvRuleName.text.toString() - tocRule.rule = tvRuleRegex.text.toString() - tocRule.example = tvRuleExample.text.toString() - } - return tocRule - } - - class ViewModel(application: Application) : BaseViewModel(application) { - - var tocRule: TxtTocRule? = null - - fun initData(id: Long?, finally: (tocRule: TxtTocRule?) -> Unit) { - if (tocRule != null) return - execute { - if (id == null) return@execute - tocRule = appDb.txtTocRuleDao.get(id) - }.onFinally { - finally.invoke(tocRule) - } - } - - fun pasteRule(success: (TxtTocRule) -> Unit) { - execute(context = Dispatchers.Main) { - val text = context.getClipText() - if (text.isNullOrBlank()) { - throw NoStackTraceException("剪贴板为空") - } - GSON.fromJsonObject(text).getOrNull() - ?: throw NoStackTraceException("格式不对") - }.onSuccess { - success.invoke(it) - }.onError { - context.toastOnUi(it.localizedMessage ?: "Error") - it.printOnDebug() - } - } - - } - - interface Callback { - - fun saveTxtTocRule(txtTocRule: TxtTocRule) - - } - -} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/config/CoverRuleConfigDialog.kt b/app/src/main/java/io/legado/app/ui/config/CoverRuleConfigDialog.kt deleted file mode 100644 index ad901e2c4..000000000 --- a/app/src/main/java/io/legado/app/ui/config/CoverRuleConfigDialog.kt +++ /dev/null @@ -1,66 +0,0 @@ -package io.legado.app.ui.config - -import android.os.Bundle -import android.util.Log -import android.view.View -import androidx.lifecycle.lifecycleScope -import io.legado.app.R -import io.legado.app.base.BaseBottomSheetDialogFragment -import io.legado.app.databinding.DialogCoverRuleConfigBinding -//import io.legado.app.lib.theme.primaryColor -import io.legado.app.model.BookCover -import io.legado.app.utils.GSON -import io.legado.app.utils.toastOnUi -import io.legado.app.utils.viewbindingdelegate.viewBinding -import kotlinx.coroutines.Dispatchers.IO -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import splitties.views.onClick - -class CoverRuleConfigDialog : BaseBottomSheetDialogFragment(R.layout.dialog_cover_rule_config) { - - val binding by viewBinding(DialogCoverRuleConfigBinding::bind) - - override fun onStart() { - super.onStart() - - } - - override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { - //binding.toolBar.setBackgroundColor(primaryColor) - initData() - binding.tvCancel.onClick { - dismissAllowingStateLoss() - } - binding.tvOk.onClick { - val enable = binding.cbEnable.isChecked - val searchUrl = binding.editSearchUrl.text?.toString() - val coverRule = binding.editCoverUrlRule.text?.toString() - if (searchUrl.isNullOrBlank() || coverRule.isNullOrBlank()) { - toastOnUi("搜索url和cover规则不能为空") - } else { - BookCover.CoverRule(enable, searchUrl, coverRule).let { config -> - BookCover.saveCoverRule(config) - } - dismissAllowingStateLoss() - } - } - binding.tvFooterLeft.onClick { - BookCover.delCoverRule() - dismissAllowingStateLoss() - } - } - - private fun initData() { - lifecycleScope.launch { - val rule = withContext(IO) { - BookCover.getCoverRule() - } - Log.e("coverRule", GSON.toJson(rule)) - binding.cbEnable.isChecked = rule.enable - binding.editSearchUrl.setText(rule.searchUrl) - binding.editCoverUrlRule.setText(rule.coverRule) - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/config/DirectLinkUploadConfig.kt b/app/src/main/java/io/legado/app/ui/config/DirectLinkUploadConfig.kt deleted file mode 100644 index 9216d248a..000000000 --- a/app/src/main/java/io/legado/app/ui/config/DirectLinkUploadConfig.kt +++ /dev/null @@ -1,128 +0,0 @@ -package io.legado.app.ui.config - -import android.os.Bundle -import android.view.MenuItem -import android.view.View -import androidx.appcompat.widget.Toolbar -import io.legado.app.R -import io.legado.app.base.BaseBottomSheetDialogFragment -import io.legado.app.databinding.DialogDirectLinkUploadConfigBinding -import io.legado.app.help.DirectLinkUpload -import io.legado.app.lib.dialogs.alert -import io.legado.app.lib.dialogs.selector -//import io.legado.app.lib.theme.primaryColor -import io.legado.app.utils.GSON -import io.legado.app.utils.applyTint -import io.legado.app.utils.fromJsonObject -import io.legado.app.utils.getClipText -import io.legado.app.utils.sendToClip -import io.legado.app.utils.toastOnUi -import io.legado.app.utils.viewbindingdelegate.viewBinding -import splitties.init.appCtx -import splitties.views.onClick - -class DirectLinkUploadConfig : BaseBottomSheetDialogFragment(R.layout.dialog_direct_link_upload_config), - Toolbar.OnMenuItemClickListener { - - private val binding by viewBinding(DialogDirectLinkUploadConfigBinding::bind) - - override fun onStart() { - super.onStart() - //setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) - } - - override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { - //binding.toolBar.setBackgroundColor(primaryColor) - binding.toolBar.inflateMenu(R.menu.direct_link_upload_config) - binding.toolBar.menu.applyTint(requireContext()) - binding.toolBar.setOnMenuItemClickListener(this) - upView(DirectLinkUpload.getRule()) - binding.tvCancel.onClick { - dismiss() - } - binding.tvFooterLeft.onClick { - test() - } - binding.tvOk.onClick { - getRule()?.let { rule -> - DirectLinkUpload.putConfig(rule) - dismiss() - } - } - } - - override fun onMenuItemClick(item: MenuItem?): Boolean { - when (item?.itemId) { - R.id.menu_import_default -> importDefault() - R.id.menu_copy_rule -> getRule()?.let { rule -> - requireContext().sendToClip(GSON.toJson(rule)) - } - - R.id.menu_paste_rule -> runCatching { - requireContext().getClipText()!!.let { - val rule = GSON.fromJsonObject(it).getOrThrow() - upView(rule) - } - }.onFailure { - toastOnUi("剪贴板为空或格式不对") - } - } - return true - } - - private fun upView(rule: DirectLinkUpload.Rule) { - binding.editUploadUrl.setText(rule.uploadUrl) - binding.editDownloadUrlRule.setText(rule.downloadUrlRule) - binding.editSummary.setText(rule.summary) - binding.cbCompress.isChecked = rule.compress - } - - private fun getRule(): DirectLinkUpload.Rule? { - val uploadUrl = binding.editUploadUrl.text?.toString() - val downloadUrlRule = binding.editDownloadUrlRule.text?.toString() - val summary = binding.editSummary.text?.toString() - val compress = binding.cbCompress.isChecked - if (uploadUrl.isNullOrBlank()) { - toastOnUi("上传Url不能为空") - return null - } - if (downloadUrlRule.isNullOrBlank()) { - toastOnUi("下载Url规则不能为空") - return null - } - if (summary.isNullOrBlank()) { - toastOnUi("注释不能为空") - return null - } - return DirectLinkUpload.Rule(uploadUrl, downloadUrlRule, summary, compress) - } - - private fun importDefault() { - requireContext().selector(DirectLinkUpload.defaultRules) { _, rule, _ -> - upView(rule) - } - } - - private fun test() { - val rule = getRule() ?: return - execute { - DirectLinkUpload.upLoad("test.json", "{}", "application/json", rule) - }.onError { - alertTestResult(it.localizedMessage ?: "ERROR") - }.onSuccess { result -> - alertTestResult(result) - } - } - - private fun alertTestResult(result: String) { - alert { - setTitle("result") - setMessage(result) - okButton() - negativeButton(R.string.copy_text) { - appCtx.sendToClip(result) - } - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/config/coverConfig/CoverRuleConfigSheet.kt b/app/src/main/java/io/legado/app/ui/config/coverConfig/CoverRuleConfigSheet.kt index 52ac8d03f..b439be0f8 100644 --- a/app/src/main/java/io/legado/app/ui/config/coverConfig/CoverRuleConfigSheet.kt +++ b/app/src/main/java/io/legado/app/ui/config/coverConfig/CoverRuleConfigSheet.kt @@ -2,105 +2,56 @@ package io.legado.app.ui.config.coverConfig import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Save import androidx.compose.material.icons.filled.SettingsBackupRestore -import androidx.compose.material3.Button -import androidx.compose.material3.Checkbox import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedButton -import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import io.legado.app.R +import io.legado.app.help.DefaultData import io.legado.app.model.BookCover -import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.AppTextField import io.legado.app.ui.widget.components.button.MediumIconButton -import io.legado.app.ui.widget.components.card.GlassCard import io.legado.app.ui.widget.components.checkBox.CheckboxItem import io.legado.app.ui.widget.components.modalBottomSheet.AppModalBottomSheet -import io.legado.app.ui.widget.components.text.AppText import io.legado.app.utils.toastOnUi import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import splitties.init.appCtx -private const val DEFAULT_SEARCH_URL = "data:;base64,{{java.base64Encode(key)}},{\"type\":\"lyc\"}" -private val DEFAULT_COVER_RULE = """ - @js: - var key = java.hexDecodeToString(result); - var url1 = `https://pre-api.tuishujun.com/api/searchBook?search_value=${'$'}{key}&page=1&pageSize=20`; - var url2 = `http://m.ypshuo.com/api/novel/search?keyword=${'$'}{key}&searchType=1&page=1`; - var [rr1, rr2] = java.ajaxAll([url1, url2]).map(r => r.body()); - function jjson(str, rule) { - try { - return com.jayway.jsonpath.JsonPath.read(str, rule); - } catch (e) { - return []; - } - } - rr1 = jjson(rr1, '$.data.data[*]'); - rr2 = jjson(rr2, '$.data.data[*]'); - var na = String(book.name), - au = String(book.author); - function search() { - for (let char of rr1) { - //本地书名包含搜索结果书名 - if (na.includes(char.title + '')) { - let au2 = char.author_nickname + ''; - //作者匹配 - if (au.includes(au2) || au2.includes(au)) { - return char.cover; - } - } - } - for (let char of rr2) { - if (na.includes(char.novel_name + '')) { - let au2 = char.author_name + ''; - if (au.includes(au2) || au2.includes(au)) { - return char.novel_img; - } - } - } - return ''; - } - search() -""".trimIndent() - @OptIn(ExperimentalMaterial3Api::class) @Composable fun CoverRuleConfigSheet( show: Boolean, onDismissRequest: () -> Unit ) { + var ruleState by remember { mutableStateOf(null) } var enable by remember { mutableStateOf(false) } var searchUrl by remember { mutableStateOf("") } var coverRule by remember { mutableStateOf("") } - LaunchedEffect(Unit) { - val rule = withContext(Dispatchers.IO) { - BookCover.getCoverRule() + LaunchedEffect(show) { + if (show) { + val rule = withContext(Dispatchers.IO) { + BookCover.getCoverRule() + } + ruleState = rule + enable = rule.enable + searchUrl = rule.searchUrl + coverRule = rule.coverRule } - enable = rule.enable - searchUrl = rule.searchUrl - coverRule = rule.coverRule } AppModalBottomSheet( @@ -111,8 +62,11 @@ fun CoverRuleConfigSheet( MediumIconButton( imageVector = Icons.Default.SettingsBackupRestore, onClick = { - searchUrl = DEFAULT_SEARCH_URL - coverRule = DEFAULT_COVER_RULE + DefaultData.coverRule.let { + enable = it.enable + searchUrl = it.searchUrl + coverRule = it.coverRule + } appCtx.toastOnUi(R.string.restore_default) } ) @@ -124,8 +78,16 @@ fun CoverRuleConfigSheet( if (searchUrl.isBlank() || coverRule.isBlank()) { appCtx.toastOnUi("搜索url和cover规则不能为空") } else { - BookCover.CoverRule(enable, searchUrl, coverRule).let { config -> - BookCover.saveCoverRule(config) + val newConfig = ruleState?.copy( + enable = enable, + searchUrl = searchUrl, + coverRule = coverRule + ) ?: BookCover.CoverRule(enable, searchUrl, coverRule) + + if (newConfig == DefaultData.coverRule) { + BookCover.delCoverRule() + } else { + BookCover.saveCoverRule(newConfig) } onDismissRequest() } @@ -136,6 +98,7 @@ fun CoverRuleConfigSheet( Column( modifier = Modifier .fillMaxWidth() + .padding(bottom = 24.dp) .verticalScroll(rememberScrollState()), verticalArrangement = Arrangement.spacedBy(8.dp) ) { diff --git a/app/src/main/java/io/legado/app/ui/main/bookshelf/BookItem.kt b/app/src/main/java/io/legado/app/ui/main/bookshelf/BookItem.kt index 038f417ea..7a8220d40 100644 --- a/app/src/main/java/io/legado/app/ui/main/bookshelf/BookItem.kt +++ b/app/src/main/java/io/legado/app/ui/main/bookshelf/BookItem.kt @@ -50,9 +50,9 @@ import io.legado.app.ui.config.themeConfig.ThemeConfig import io.legado.app.ui.theme.LegadoTheme 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.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.image.cover.BookshelfCover +import io.legado.app.ui.widget.components.image.cover.CoilBookCover import io.legado.app.ui.widget.components.text.AppText import io.legado.app.utils.toTimeAgo @@ -214,7 +214,7 @@ fun BookshelfItem( Column( modifier = Modifier .weight(1f) - .padding(top = 4.dp, bottom = 4.dp, end = 4.dp), + .padding(top = 4.dp, bottom = 4.dp, end = 8.dp, start = 4.dp), verticalArrangement = Arrangement.Center ) { Row( @@ -232,7 +232,7 @@ fun BookshelfItem( modifier = Modifier.weight(1f) ) titleEnd?.let { - Box(modifier = Modifier.padding(top = 4.dp)) { + Box(modifier = Modifier.padding(top = 4.dp, start = 4.dp)) { it.invoke() } } @@ -523,7 +523,7 @@ fun BookGroupItemHorizontalCovers( ) { Column( modifier = Modifier - .padding(vertical = 4.dp), + .padding(vertical = 8.dp, horizontal = 4.dp), verticalArrangement = Arrangement.spacedBy(8.dp) ) { Row( diff --git a/app/src/main/java/io/legado/app/ui/main/explore/ExploreScreen.kt b/app/src/main/java/io/legado/app/ui/main/explore/ExploreScreen.kt index 23051211f..ae9eea454 100644 --- a/app/src/main/java/io/legado/app/ui/main/explore/ExploreScreen.kt +++ b/app/src/main/java/io/legado/app/ui/main/explore/ExploreScreen.kt @@ -29,7 +29,6 @@ import androidx.compose.material.icons.filled.Refresh import androidx.compose.material.icons.filled.Search import androidx.compose.material.icons.filled.VerticalAlignTop import androidx.compose.material3.ExperimentalMaterial3Api -import io.legado.app.ui.widget.components.progressIndicator.AppCircularProgressIndicator import androidx.compose.material3.Icon import androidx.compose.material3.ListItem import androidx.compose.material3.ListItemDefaults @@ -41,8 +40,8 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.runtime.setValue import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.rotate @@ -53,23 +52,22 @@ import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import io.legado.app.R import io.legado.app.data.entities.BookSourcePart +import io.legado.app.domain.usecase.ExploreKindUiUseCase import io.legado.app.help.source.getExploreInfoMap -import io.legado.app.ui.widget.components.explore.ExploreKindUiUseCase import io.legado.app.ui.book.search.SearchActivity import io.legado.app.ui.book.search.SearchScope import io.legado.app.ui.book.source.edit.BookSourceEditActivity import io.legado.app.ui.login.SourceLoginActivity -import io.legado.app.ui.config.themeConfig.ThemeConfig import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.theme.LegadoTheme.composeEngine import io.legado.app.ui.theme.ThemeResolver import io.legado.app.ui.theme.adaptiveContentPadding +import io.legado.app.ui.widget.components.EmptyMessage import io.legado.app.ui.widget.components.alert.AppAlertDialog import io.legado.app.ui.widget.components.card.GlassCard import io.legado.app.ui.widget.components.card.TextCard import io.legado.app.ui.widget.components.divider.PillHeaderDivider import io.legado.app.ui.widget.components.explore.ExploreKindMultiTypeItem -import io.legado.app.ui.widget.components.EmptyMessage import io.legado.app.ui.widget.components.lazylist.FastScrollLazyColumn import io.legado.app.ui.widget.components.list.ListScaffold import io.legado.app.ui.widget.components.list.TopFloatingStickyItem @@ -79,7 +77,6 @@ import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem import io.legado.app.ui.widget.components.progressIndicator.AppContainedLoadingIndicator import io.legado.app.ui.widget.components.text.AppText import io.legado.app.utils.startActivity -import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch import org.koin.androidx.compose.koinViewModel import org.koin.compose.koinInject diff --git a/app/src/main/java/io/legado/app/ui/main/explore/ExploreViewModel.kt b/app/src/main/java/io/legado/app/ui/main/explore/ExploreViewModel.kt index 5cb91c8c4..61b027fcb 100644 --- a/app/src/main/java/io/legado/app/ui/main/explore/ExploreViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/main/explore/ExploreViewModel.kt @@ -6,10 +6,10 @@ import io.legado.app.base.BaseViewModel import io.legado.app.data.entities.BookSourcePart import io.legado.app.data.entities.rule.ExploreKind import io.legado.app.data.repository.ExploreRepository +import io.legado.app.domain.usecase.ExploreKindUiUseCase import io.legado.app.help.source.clearExploreKindsCache import io.legado.app.help.source.exploreKinds import io.legado.app.help.source.getExploreInfoMap -import io.legado.app.ui.widget.components.explore.ExploreKindUiUseCase import io.legado.app.ui.widget.components.explore.calculateExploreKindRows import io.legado.app.ui.widget.components.list.ListUiState import kotlinx.collections.immutable.ImmutableList diff --git a/app/src/main/java/io/legado/app/ui/main/rss/RssScreen.kt b/app/src/main/java/io/legado/app/ui/main/rss/RssScreen.kt index 60d0e928f..5ae05fdfb 100644 --- a/app/src/main/java/io/legado/app/ui/main/rss/RssScreen.kt +++ b/app/src/main/java/io/legado/app/ui/main/rss/RssScreen.kt @@ -52,12 +52,12 @@ import io.legado.app.ui.rss.source.edit.RssSourceEditActivity import io.legado.app.ui.rss.source.manage.RssSourceActivity import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.theme.adaptiveContentPadding -import io.legado.app.ui.widget.components.SourceIcon import io.legado.app.ui.widget.components.alert.AppAlertDialog import io.legado.app.ui.widget.components.card.GlassCard import io.legado.app.ui.widget.components.divider.PillDivider import io.legado.app.ui.widget.components.divider.PillHeaderDivider import io.legado.app.ui.widget.components.icon.AppIcon +import io.legado.app.ui.widget.components.image.sourceIcon.SourceIcon import io.legado.app.ui.widget.components.list.ListScaffold import io.legado.app.ui.widget.components.menuItem.MenuItemIcon import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu diff --git a/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesCompose.kt b/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesCompose.kt index 83fc13e89..ba1ef0be5 100644 --- a/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesCompose.kt +++ b/app/src/main/java/io/legado/app/ui/rss/article/RssArticlesCompose.kt @@ -61,7 +61,7 @@ import io.legado.app.ui.theme.adaptiveContentPadding import io.legado.app.ui.widget.components.AppPullToRefresh import io.legado.app.ui.widget.components.EmptyMessage import io.legado.app.ui.widget.components.card.GlassCard -import io.legado.app.ui.widget.components.cover.buildCoverImageRequest +import io.legado.app.ui.widget.components.image.cover.buildCoverImageRequest import io.legado.app.utils.toastOnUi import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.flow.catch diff --git a/app/src/main/java/io/legado/app/ui/rss/favorites/RssFavoritesScreen.kt b/app/src/main/java/io/legado/app/ui/rss/favorites/RssFavoritesScreen.kt index 3c4196125..a60b1ad29 100644 --- a/app/src/main/java/io/legado/app/ui/rss/favorites/RssFavoritesScreen.kt +++ b/app/src/main/java/io/legado/app/ui/rss/favorites/RssFavoritesScreen.kt @@ -33,11 +33,11 @@ import io.legado.app.data.entities.RssStar import io.legado.app.ui.theme.adaptiveContentPadding import io.legado.app.ui.widget.components.ActionItem import io.legado.app.ui.widget.components.EmptyMessage -import io.legado.app.ui.widget.components.SourceIcon import io.legado.app.ui.widget.components.button.SmallIconButton import io.legado.app.ui.widget.components.card.SelectionItemCard 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.image.sourceIcon.SourceIcon import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem import io.legado.app.ui.widget.components.rules.RuleListScaffold import org.koin.androidx.compose.koinViewModel diff --git a/app/src/main/java/io/legado/app/ui/widget/CollapsibleHeader.kt b/app/src/main/java/io/legado/app/ui/widget/components/CollapsibleHeader.kt similarity index 97% rename from app/src/main/java/io/legado/app/ui/widget/CollapsibleHeader.kt rename to app/src/main/java/io/legado/app/ui/widget/components/CollapsibleHeader.kt index f3b765d6c..7acffe944 100644 --- a/app/src/main/java/io/legado/app/ui/widget/CollapsibleHeader.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/CollapsibleHeader.kt @@ -1,4 +1,4 @@ -package io.legado.app.ui.widget +package io.legado.app.ui.widget.components import androidx.compose.animation.core.animateFloatAsState import androidx.compose.foundation.layout.Column @@ -10,7 +10,6 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ExpandMore import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment diff --git a/app/src/main/java/io/legado/app/ui/widget/components/SectionHeader.kt b/app/src/main/java/io/legado/app/ui/widget/components/SectionHeader.kt deleted file mode 100644 index efe474c0d..000000000 --- a/app/src/main/java/io/legado/app/ui/widget/components/SectionHeader.kt +++ /dev/null @@ -1,40 +0,0 @@ -package io.legado.app.ui.widget.components - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp - -@Composable -fun SectionHeader( - // 左侧主标题内容 - titleContent: @Composable () -> Unit, - // 右侧或副标题内容 - detailContent: @Composable (() -> Unit)? = null, - // 主要内容的排列方式 - verticalArrangement: Arrangement.Vertical = Arrangement.Center, - // 定义水平对齐方式 - horizontalArrangement: Arrangement.Horizontal = Arrangement.SpaceBetween, - // 根容器的 Padding - contentPadding: PaddingValues = PaddingValues(horizontal = 16.dp, vertical = 8.dp) -) { - - Row( - modifier = Modifier - .fillMaxWidth() - .padding(contentPadding), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = horizontalArrangement - ) { - titleContent() - detailContent?.let { - it() - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/ui/widget/components/alert/AppAlertDialog.kt b/app/src/main/java/io/legado/app/ui/widget/components/alert/AppAlertDialog.kt index c89858820..b0d049a72 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/alert/AppAlertDialog.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/alert/AppAlertDialog.kt @@ -144,6 +144,7 @@ fun AppAlertDialog( onDismissRequest: () -> Unit, title: String? = null, text: String? = null, + textProvider: @Composable (T.() -> String)? = null, confirmText: String = "确定", onConfirm: ((T) -> Unit)? = null, dismissText: String = "取消", @@ -159,11 +160,17 @@ fun AppAlertDialog( val currentData = cachedData if (currentData != null) { + val currentText = text ?: textProvider?.invoke(currentData) + var cachedText by remember { mutableStateOf(currentText) } + if (currentText != null) { + cachedText = currentText + } + AppAlertDialog( show = data != null, onDismissRequest = onDismissRequest, title = title, - text = text, + text = currentText ?: cachedText, modifier = modifier, confirmText = confirmText, onConfirm = onConfirm?.let { { it(currentData) } }, diff --git a/app/src/main/java/io/legado/app/ui/widget/components/book/SearchBookItem.kt b/app/src/main/java/io/legado/app/ui/widget/components/book/SearchBookItem.kt index 3b873aab5..3d0ff56b1 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/book/SearchBookItem.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/book/SearchBookItem.kt @@ -33,7 +33,7 @@ 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.image.cover.CoilBookCover import io.legado.app.ui.widget.components.text.AppText @OptIn(ExperimentalSharedTransitionApi::class) diff --git a/app/src/main/java/io/legado/app/ui/widget/components/cover/Cover.kt b/app/src/main/java/io/legado/app/ui/widget/components/cover/Cover.kt deleted file mode 100644 index 02bddd7b0..000000000 --- a/app/src/main/java/io/legado/app/ui/widget/components/cover/Cover.kt +++ /dev/null @@ -1,97 +0,0 @@ -package io.legado.app.ui.widget.components.cover - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.RowScope -import androidx.compose.foundation.layout.aspectRatio -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Book -import androidx.compose.material3.Icon -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.unit.dp -import coil.ImageLoader -import coil.compose.AsyncImage -import io.legado.app.ui.theme.LegadoTheme -import org.koin.compose.koinInject - -@Composable -fun Cover( - path: Any?, - modifier: Modifier = Modifier.width(48.dp), - badgeContent: (@Composable RowScope.() -> Unit)? = null, - loadOnlyWifi: Boolean = false, - sourceOrigin: String? = null, - imageLoader: ImageLoader = koinInject(), - onLoadFinish: (() -> Unit)? = null -) { - val context = LocalContext.current - - val boxModifier = modifier - .aspectRatio(3f / 4f) - .clip(RoundedCornerShape(4.dp)) - .background(LegadoTheme.colorScheme.surfaceContainer) - - Box(modifier = boxModifier) { - if (path == null) { - Icon( - Icons.Default.Book, - contentDescription = null, - tint = LegadoTheme.colorScheme.surfaceContainerHighest, - modifier = Modifier - .size(24.dp) - .align(Alignment.Center) - ) - } else { - AsyncImage( - model = buildCoverImageRequest( - context = context, - data = path, - sourceOrigin = sourceOrigin, - loadOnlyWifi = loadOnlyWifi, - crossfade = true, - ) { - listener( - onSuccess = { _, _ -> onLoadFinish?.invoke() }, - onError = { _, _ -> onLoadFinish?.invoke() } - ) - }, - imageLoader = imageLoader, - contentDescription = null, - contentScale = ContentScale.Crop, - modifier = Modifier.fillMaxSize() - ) - } - - if (badgeContent != null) { - Surface( - modifier = Modifier - .align(Alignment.TopEnd) - .padding(2.dp), - shape = RoundedCornerShape(4.dp), - color = LegadoTheme.colorScheme.secondaryContainer, - contentColor = LegadoTheme.colorScheme.onSecondaryContainer, - tonalElevation = 2.dp - ) { - Row( - modifier = Modifier.padding(2.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.Center, - content = badgeContent - ) - } - } - } -} diff --git a/app/src/main/java/io/legado/app/ui/widget/components/explore/ExploreKindMultiTypeItem.kt b/app/src/main/java/io/legado/app/ui/widget/components/explore/ExploreKindMultiTypeItem.kt index a0c79d311..5e7033038 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/explore/ExploreKindMultiTypeItem.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/explore/ExploreKindMultiTypeItem.kt @@ -10,13 +10,9 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.BasicTextField import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.ArrowRight import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight -import androidx.compose.material.icons.automirrored.filled.OpenInNew -import androidx.compose.material.icons.filled.KeyboardArrowDown import androidx.compose.material.icons.filled.Refresh import androidx.compose.material.icons.filled.UnfoldMore -import androidx.compose.material3.Icon import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect @@ -25,32 +21,28 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue -import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp -import io.legado.app.App import io.legado.app.data.entities.rule.ExploreKind -import io.legado.app.ui.widget.components.explore.ExploreKindUiUseCase +import io.legado.app.domain.usecase.ExploreKindUiUseCase import io.legado.app.help.source.getExploreInfoMap -import io.legado.app.ui.config.themeConfig.ThemeConfig +import io.legado.app.ui.theme.LegadoTheme +import io.legado.app.ui.widget.components.icon.AppIcon import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem import io.legado.app.ui.widget.components.text.AppText import io.legado.app.ui.widget.dialog.TextDialog -import io.legado.app.ui.theme.LegadoTheme -import io.legado.app.ui.widget.components.icon.AppIcon import io.legado.app.utils.showDialogFragment import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch -import top.yukonga.miuix.kmp.icon.MiuixIcons -import top.yukonga.miuix.kmp.icon.basic.ArrowUpDown @Composable fun ExploreKindMultiTypeItem( diff --git a/app/src/main/java/io/legado/app/ui/widget/components/cover/BookshelfCover.kt b/app/src/main/java/io/legado/app/ui/widget/components/image/cover/BookshelfCover.kt similarity index 98% rename from app/src/main/java/io/legado/app/ui/widget/components/cover/BookshelfCover.kt rename to app/src/main/java/io/legado/app/ui/widget/components/image/cover/BookshelfCover.kt index 8778dde48..c358942e3 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/cover/BookshelfCover.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/image/cover/BookshelfCover.kt @@ -1,4 +1,4 @@ -package io.legado.app.ui.widget.components.cover +package io.legado.app.ui.widget.components.image.cover import androidx.compose.animation.AnimatedVisibilityScope import androidx.compose.animation.ExperimentalSharedTransitionApi @@ -14,8 +14,8 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import io.legado.app.ui.theme.LegadoTheme -import io.legado.app.ui.widget.components.progressIndicator.AppLinearProgressIndicator import io.legado.app.ui.widget.components.card.TextCard +import io.legado.app.ui.widget.components.progressIndicator.AppLinearProgressIndicator @OptIn(ExperimentalSharedTransitionApi::class) @Composable diff --git a/app/src/main/java/io/legado/app/ui/widget/components/cover/CoilBookCover.kt b/app/src/main/java/io/legado/app/ui/widget/components/image/cover/CoilBookCover.kt similarity index 97% rename from app/src/main/java/io/legado/app/ui/widget/components/cover/CoilBookCover.kt rename to app/src/main/java/io/legado/app/ui/widget/components/image/cover/CoilBookCover.kt index 9714b2408..e65aa82c2 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/cover/CoilBookCover.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/image/cover/CoilBookCover.kt @@ -1,4 +1,4 @@ -package io.legado.app.ui.widget.components.cover +package io.legado.app.ui.widget.components.image.cover import android.graphics.Paint import android.graphics.Typeface @@ -15,7 +15,6 @@ import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons @@ -122,7 +121,9 @@ fun CoilBookCover( contentDescription = null, imageLoader = koinInject(), contentScale = ContentScale.Crop, - modifier = Modifier.fillMaxSize() + modifier = Modifier + .fillMaxSize() + .clip(RoundedCornerShape(4.dp)) ) } @@ -138,7 +139,9 @@ fun CoilBookCover( contentDescription = null, imageLoader = koinInject(), contentScale = ContentScale.Crop, - modifier = Modifier.fillMaxSize(), + modifier = Modifier + .fillMaxSize() + .clip(RoundedCornerShape(4.dp)), onSuccess = { isOnlineCoverLoaded = true onLoadFinish?.invoke() diff --git a/app/src/main/java/io/legado/app/ui/widget/components/cover/CoverImageRequest.kt b/app/src/main/java/io/legado/app/ui/widget/components/image/cover/CoverImageRequest.kt similarity index 90% rename from app/src/main/java/io/legado/app/ui/widget/components/cover/CoverImageRequest.kt rename to app/src/main/java/io/legado/app/ui/widget/components/image/cover/CoverImageRequest.kt index 4bd201ab9..318d3f3b9 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/cover/CoverImageRequest.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/image/cover/CoverImageRequest.kt @@ -1,4 +1,4 @@ -package io.legado.app.ui.widget.components.cover +package io.legado.app.ui.widget.components.image.cover import android.content.Context import coil.request.ImageRequest diff --git a/app/src/main/java/io/legado/app/ui/widget/components/SourceIcon.kt b/app/src/main/java/io/legado/app/ui/widget/components/image/sourceIcon/SourceIcon.kt similarity index 97% rename from app/src/main/java/io/legado/app/ui/widget/components/SourceIcon.kt rename to app/src/main/java/io/legado/app/ui/widget/components/image/sourceIcon/SourceIcon.kt index 24d0f1249..8d50d3995 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/SourceIcon.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/image/sourceIcon/SourceIcon.kt @@ -1,4 +1,4 @@ -package io.legado.app.ui.widget.components +package io.legado.app.ui.widget.components.image.sourceIcon import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize diff --git a/app/src/main/java/io/legado/app/ui/widget/components/tabRow/AppTabRow.kt b/app/src/main/java/io/legado/app/ui/widget/components/tabRow/AppTabRow.kt index c302d1085..8af61683b 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/tabRow/AppTabRow.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/tabRow/AppTabRow.kt @@ -87,6 +87,7 @@ private fun AppTab( text = title, maxLines = 1, overflow = TextOverflow.Ellipsis, + style = LegadoTheme.typography.labelLargeEmphasized, modifier = Modifier.padding(horizontal = 8.dp), color = if (selected) LegadoTheme.colorScheme.primary else LegadoTheme.colorScheme.onSurfaceVariant )