|
@@ -1,5 +1,7 @@
|
|
|
package io.legado.app.ui.book.source.manage
|
|
package io.legado.app.ui.book.source.manage
|
|
|
|
|
|
|
|
|
|
+import androidx.activity.compose.rememberLauncherForActivityResult
|
|
|
|
|
+import androidx.activity.result.contract.ActivityResultContracts
|
|
|
import androidx.compose.foundation.background
|
|
import androidx.compose.foundation.background
|
|
|
import androidx.compose.foundation.clickable
|
|
import androidx.compose.foundation.clickable
|
|
|
import androidx.compose.foundation.layout.Arrangement
|
|
import androidx.compose.foundation.layout.Arrangement
|
|
@@ -29,6 +31,7 @@ import androidx.compose.runtime.setValue
|
|
|
import androidx.compose.ui.Alignment
|
|
import androidx.compose.ui.Alignment
|
|
|
import androidx.compose.ui.Modifier
|
|
import androidx.compose.ui.Modifier
|
|
|
import androidx.compose.ui.draw.clip
|
|
import androidx.compose.ui.draw.clip
|
|
|
|
|
+import androidx.compose.ui.platform.LocalContext
|
|
|
import androidx.compose.ui.res.stringResource
|
|
import androidx.compose.ui.res.stringResource
|
|
|
import androidx.compose.ui.text.style.TextAlign
|
|
import androidx.compose.ui.text.style.TextAlign
|
|
|
import androidx.compose.ui.text.style.TextOverflow
|
|
import androidx.compose.ui.text.style.TextOverflow
|
|
@@ -38,6 +41,7 @@ import io.legado.app.R
|
|
|
import io.legado.app.ui.theme.LegadoTheme
|
|
import io.legado.app.ui.theme.LegadoTheme
|
|
|
import io.legado.app.ui.theme.adaptiveContentPadding
|
|
import io.legado.app.ui.theme.adaptiveContentPadding
|
|
|
import io.legado.app.ui.widget.components.ActionItem
|
|
import io.legado.app.ui.widget.components.ActionItem
|
|
|
|
|
+import io.legado.app.ui.widget.components.AppTextField
|
|
|
import io.legado.app.ui.widget.components.DraggableSelectionHandler
|
|
import io.legado.app.ui.widget.components.DraggableSelectionHandler
|
|
|
import io.legado.app.ui.widget.components.GroupManageBottomSheet
|
|
import io.legado.app.ui.widget.components.GroupManageBottomSheet
|
|
|
import io.legado.app.ui.widget.components.SearchBar
|
|
import io.legado.app.ui.widget.components.SearchBar
|
|
@@ -47,14 +51,20 @@ import io.legado.app.ui.widget.components.card.ReorderableSelectionItem
|
|
|
import io.legado.app.ui.widget.components.dialog.TextListInputDialog
|
|
import io.legado.app.ui.widget.components.dialog.TextListInputDialog
|
|
|
import io.legado.app.ui.widget.components.divider.PillDivider
|
|
import io.legado.app.ui.widget.components.divider.PillDivider
|
|
|
import io.legado.app.ui.widget.components.icon.AppIcons
|
|
import io.legado.app.ui.widget.components.icon.AppIcons
|
|
|
|
|
+import io.legado.app.ui.widget.components.importComponents.BaseImportUiState
|
|
|
|
|
+import io.legado.app.ui.widget.components.importComponents.BatchImportDialog
|
|
|
|
|
+import io.legado.app.ui.widget.components.importComponents.ImportStatus
|
|
|
import io.legado.app.ui.widget.components.importComponents.SourceInputDialog
|
|
import io.legado.app.ui.widget.components.importComponents.SourceInputDialog
|
|
|
import io.legado.app.ui.widget.components.lazylist.FastScrollLazyColumn
|
|
import io.legado.app.ui.widget.components.lazylist.FastScrollLazyColumn
|
|
|
import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu
|
|
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.menuItem.RoundDropdownMenuItem
|
|
|
import io.legado.app.ui.widget.components.modalBottomSheet.AppModalBottomSheet
|
|
import io.legado.app.ui.widget.components.modalBottomSheet.AppModalBottomSheet
|
|
|
import io.legado.app.ui.widget.components.rules.RuleListScaffold
|
|
import io.legado.app.ui.widget.components.rules.RuleListScaffold
|
|
|
|
|
+import io.legado.app.ui.widget.components.settingItem.SwitchSettingItem
|
|
|
import io.legado.app.ui.widget.components.text.AppText
|
|
import io.legado.app.ui.widget.components.text.AppText
|
|
|
import io.legado.app.ui.widget.components.topbar.TopBarActionButton
|
|
import io.legado.app.ui.widget.components.topbar.TopBarActionButton
|
|
|
|
|
+import kotlinx.coroutines.flow.Flow
|
|
|
|
|
+import kotlinx.coroutines.flow.collectLatest
|
|
|
import org.koin.androidx.compose.koinViewModel
|
|
import org.koin.androidx.compose.koinViewModel
|
|
|
import sh.calvin.reorderable.rememberReorderableLazyListState
|
|
import sh.calvin.reorderable.rememberReorderableLazyListState
|
|
|
import androidx.compose.foundation.lazy.grid.items as gridItems
|
|
import androidx.compose.foundation.lazy.grid.items as gridItems
|
|
@@ -68,8 +78,6 @@ fun BookSourceRouteScreen(
|
|
|
onLoginSource: (String) -> Unit,
|
|
onLoginSource: (String) -> Unit,
|
|
|
onSearchSource: (String) -> Unit,
|
|
onSearchSource: (String) -> Unit,
|
|
|
onDebugSource: (String) -> Unit,
|
|
onDebugSource: (String) -> Unit,
|
|
|
- onImportLocal: () -> Unit,
|
|
|
|
|
- onImportOnline: (String) -> Unit,
|
|
|
|
|
) {
|
|
) {
|
|
|
val state by viewModel.uiState.collectAsStateWithLifecycle()
|
|
val state by viewModel.uiState.collectAsStateWithLifecycle()
|
|
|
BookSourceScreen(
|
|
BookSourceScreen(
|
|
@@ -81,8 +89,7 @@ fun BookSourceRouteScreen(
|
|
|
onLoginSource,
|
|
onLoginSource,
|
|
|
onSearchSource,
|
|
onSearchSource,
|
|
|
onDebugSource,
|
|
onDebugSource,
|
|
|
- onImportLocal,
|
|
|
|
|
- onImportOnline
|
|
|
|
|
|
|
+ viewModel.effects,
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -97,9 +104,9 @@ fun BookSourceScreen(
|
|
|
onLoginSource: (String) -> Unit,
|
|
onLoginSource: (String) -> Unit,
|
|
|
onSearchSource: (String) -> Unit,
|
|
onSearchSource: (String) -> Unit,
|
|
|
onDebugSource: (String) -> Unit,
|
|
onDebugSource: (String) -> Unit,
|
|
|
- onImportLocal: () -> Unit,
|
|
|
|
|
- onImportOnline: (String) -> Unit,
|
|
|
|
|
|
|
+ effects: Flow<BookSourceEffect>,
|
|
|
) {
|
|
) {
|
|
|
|
|
+ val context = LocalContext.current
|
|
|
val rules = state.items
|
|
val rules = state.items
|
|
|
val selectedIds = state.selectedIds
|
|
val selectedIds = state.selectedIds
|
|
|
val listState = rememberLazyListState()
|
|
val listState = rememberLazyListState()
|
|
@@ -109,6 +116,13 @@ fun BookSourceScreen(
|
|
|
var groupManage by remember { mutableStateOf(false) }
|
|
var groupManage by remember { mutableStateOf(false) }
|
|
|
var showGroupFilterSheet by remember { mutableStateOf(false) }
|
|
var showGroupFilterSheet by remember { mutableStateOf(false) }
|
|
|
var showOnlineImport by remember { mutableStateOf(false) }
|
|
var showOnlineImport by remember { mutableStateOf(false) }
|
|
|
|
|
+ var checkSourceIds by remember { mutableStateOf<Set<String>?>(null) }
|
|
|
|
|
+ var checkSheet by remember { mutableStateOf<CheckSheet?>(null) }
|
|
|
|
|
+ var checkOptionsDraft by remember { mutableStateOf(state.checkOptions) }
|
|
|
|
|
+ var pendingExportIds by remember { mutableStateOf<Set<String>>(emptySet()) }
|
|
|
|
|
+ var showImportOptions by remember { mutableStateOf(false) }
|
|
|
|
|
+ var showCustomGroup by remember { mutableStateOf(false) }
|
|
|
|
|
+ val importSuccess = state.importState as? BaseImportUiState.Success
|
|
|
var dragOrder by remember { mutableStateOf<List<BookSourceItemUi>?>(null) }
|
|
var dragOrder by remember { mutableStateOf<List<BookSourceItemUi>?>(null) }
|
|
|
val displayedRules = dragOrder ?: rules
|
|
val displayedRules = dragOrder ?: rules
|
|
|
val reorderState = rememberReorderableLazyListState(listState) { from, to ->
|
|
val reorderState = rememberReorderableLazyListState(listState) { from, to ->
|
|
@@ -130,11 +144,161 @@ fun BookSourceScreen(
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ val snackbarHostState = remember { SnackbarHostState() }
|
|
|
|
|
+ LaunchedEffect(Unit) {
|
|
|
|
|
+ effects.collectLatest { effect ->
|
|
|
|
|
+ when (effect) {
|
|
|
|
|
+ is BookSourceEffect.ShowSnackbar -> snackbarHostState.showSnackbar(effect.message)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ LaunchedEffect(state.checkProgress) {
|
|
|
|
|
+ val progress = state.checkProgress ?: return@LaunchedEffect
|
|
|
|
|
+ val result = snackbarHostState.showSnackbar(
|
|
|
|
|
+ message = progress,
|
|
|
|
|
+ actionLabel = context.getString(R.string.cancel),
|
|
|
|
|
+ withDismissAction = false,
|
|
|
|
|
+ duration = androidx.compose.material3.SnackbarDuration.Indefinite,
|
|
|
|
|
+ )
|
|
|
|
|
+ if (result == androidx.compose.material3.SnackbarResult.ActionPerformed) {
|
|
|
|
|
+ onIntent(BookSourceIntent.CancelCheck)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ val importDocument =
|
|
|
|
|
+ rememberLauncherForActivityResult(ActivityResultContracts.OpenDocument()) { uri ->
|
|
|
|
|
+ uri?.let {
|
|
|
|
|
+ context.contentResolver.openInputStream(it)?.bufferedReader()?.use { reader ->
|
|
|
|
|
+ onIntent(BookSourceIntent.Import(reader.readText()))
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ val exportDocument =
|
|
|
|
|
+ rememberLauncherForActivityResult(ActivityResultContracts.CreateDocument("application/json")) { uri ->
|
|
|
|
|
+ uri?.let { onIntent(BookSourceIntent.Export(it, pendingExportIds)) }
|
|
|
|
|
+ }
|
|
|
SourceInputDialog(
|
|
SourceInputDialog(
|
|
|
show = showOnlineImport,
|
|
show = showOnlineImport,
|
|
|
title = stringResource(R.string.import_on_line),
|
|
title = stringResource(R.string.import_on_line),
|
|
|
onDismissRequest = { showOnlineImport = false },
|
|
onDismissRequest = { showOnlineImport = false },
|
|
|
- onConfirm = { text -> showOnlineImport = false; onImportOnline(text) })
|
|
|
|
|
|
|
+ onConfirm = { text -> showOnlineImport = false; onIntent(BookSourceIntent.Import(text)) })
|
|
|
|
|
+
|
|
|
|
|
+ BatchImportDialog(
|
|
|
|
|
+ title = stringResource(R.string.import_book_source),
|
|
|
|
|
+ importState = state.importState,
|
|
|
|
|
+ onDismissRequest = { onIntent(BookSourceIntent.CancelImport) },
|
|
|
|
|
+ onConfirm = { onIntent(BookSourceIntent.SaveImportedSources) },
|
|
|
|
|
+ onToggleItem = { onIntent(BookSourceIntent.ToggleImportItem(it)) },
|
|
|
|
|
+ onToggleAll = { onIntent(BookSourceIntent.ToggleImportAll(it)) },
|
|
|
|
|
+ onUpdateItem = { index, source ->
|
|
|
|
|
+ onIntent(
|
|
|
|
|
+ BookSourceIntent.UpdateImportItem(
|
|
|
|
|
+ index,
|
|
|
|
|
+ source
|
|
|
|
|
+ )
|
|
|
|
|
+ )
|
|
|
|
|
+ },
|
|
|
|
|
+ topBarActions = {
|
|
|
|
|
+ Box {
|
|
|
|
|
+ SmallPlainButton(
|
|
|
|
|
+ icon = AppIcons.MoreVert,
|
|
|
|
|
+ contentDescription = stringResource(R.string.menu),
|
|
|
|
|
+ onClick = { showImportOptions = true },
|
|
|
|
|
+ )
|
|
|
|
|
+ RoundDropdownMenu(showImportOptions, { showImportOptions = false }) { dismiss ->
|
|
|
|
|
+ RoundDropdownMenuItem(stringResource(R.string.select_new_source), onClick = {
|
|
|
|
|
+ dismiss(); onIntent(BookSourceIntent.SelectImportStatus(ImportStatus.New))
|
|
|
|
|
+ })
|
|
|
|
|
+ RoundDropdownMenuItem(stringResource(R.string.select_update_source), onClick = {
|
|
|
|
|
+ dismiss(); onIntent(BookSourceIntent.SelectImportStatus(ImportStatus.Update))
|
|
|
|
|
+ })
|
|
|
|
|
+ RoundDropdownMenuItem(
|
|
|
|
|
+ text = stringResource(R.string.keep_original_name),
|
|
|
|
|
+ isSelected = importSuccess?.keepOriginalName == true,
|
|
|
|
|
+ onClick = { onIntent(BookSourceIntent.SetImportKeepName(importSuccess?.keepOriginalName != true)) },
|
|
|
|
|
+ )
|
|
|
|
|
+ RoundDropdownMenuItem(
|
|
|
|
|
+ text = stringResource(R.string.keep_group),
|
|
|
|
|
+ isSelected = importSuccess?.keepOriginalGroup == true,
|
|
|
|
|
+ onClick = { onIntent(BookSourceIntent.SetImportKeepGroup(importSuccess?.keepOriginalGroup != true)) },
|
|
|
|
|
+ )
|
|
|
|
|
+ RoundDropdownMenuItem(
|
|
|
|
|
+ text = stringResource(R.string.keep_enable),
|
|
|
|
|
+ isSelected = importSuccess?.keepOriginalEnable == true,
|
|
|
|
|
+ onClick = { onIntent(BookSourceIntent.SetImportKeepEnable(importSuccess?.keepOriginalEnable != true)) },
|
|
|
|
|
+ )
|
|
|
|
|
+ RoundDropdownMenuItem(stringResource(R.string.diy_source_group), onClick = {
|
|
|
|
|
+ dismiss(); showCustomGroup = true
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ itemTitle = { it.bookSourceName },
|
|
|
|
|
+ itemSubtitle = { it.bookSourceUrl },
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ BookSourceImportGroupDialog(
|
|
|
|
|
+ show = showCustomGroup,
|
|
|
|
|
+ initialGroup = importSuccess?.customGroup.orEmpty(),
|
|
|
|
|
+ initialAdd = importSuccess?.isAddGroup == true,
|
|
|
|
|
+ onDismissRequest = { showCustomGroup = false },
|
|
|
|
|
+ onConfirm = { group, add ->
|
|
|
|
|
+ showCustomGroup = false
|
|
|
|
|
+ onIntent(BookSourceIntent.SetImportCustomGroup(group, add))
|
|
|
|
|
+ },
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ CheckBookSourceSheet(
|
|
|
|
|
+ sourceIds = checkSourceIds.takeIf { checkSheet == CheckSheet.Run },
|
|
|
|
|
+ options = checkOptionsDraft,
|
|
|
|
|
+ onDismissRequest = { checkSheet = null },
|
|
|
|
|
+ onOpenSettings = { checkSheet = CheckSheet.Settings },
|
|
|
|
|
+ onConfirm = { ids, keyword, options ->
|
|
|
|
|
+ checkSheet = null
|
|
|
|
|
+ onIntent(BookSourceIntent.StartCheck(ids, keyword, options))
|
|
|
|
|
+ },
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ CheckSourceBottomSheet(
|
|
|
|
|
+ show = checkSheet == CheckSheet.Settings,
|
|
|
|
|
+ timeoutSeconds = checkOptionsDraft.timeoutSeconds,
|
|
|
|
|
+ checkSearch = checkOptionsDraft.checkSearch,
|
|
|
|
|
+ checkDiscovery = checkOptionsDraft.checkDiscovery,
|
|
|
|
|
+ checkInfo = checkOptionsDraft.checkInfo,
|
|
|
|
|
+ checkCategory = checkOptionsDraft.checkCategory,
|
|
|
|
|
+ checkContent = checkOptionsDraft.checkContent,
|
|
|
|
|
+ onTimeoutChange = { checkOptionsDraft = checkOptionsDraft.copy(timeoutSeconds = it) },
|
|
|
|
|
+ onCheckSearchChange = { enabled ->
|
|
|
|
|
+ checkOptionsDraft = checkOptionsDraft.copy(
|
|
|
|
|
+ checkSearch = enabled,
|
|
|
|
|
+ checkDiscovery = checkOptionsDraft.checkDiscovery || !enabled,
|
|
|
|
|
+ )
|
|
|
|
|
+ },
|
|
|
|
|
+ onCheckDiscoveryChange = { enabled ->
|
|
|
|
|
+ checkOptionsDraft = checkOptionsDraft.copy(
|
|
|
|
|
+ checkDiscovery = enabled,
|
|
|
|
|
+ checkSearch = checkOptionsDraft.checkSearch || !enabled,
|
|
|
|
|
+ )
|
|
|
|
|
+ },
|
|
|
|
|
+ onCheckInfoChange = { enabled ->
|
|
|
|
|
+ checkOptionsDraft = checkOptionsDraft.copy(
|
|
|
|
|
+ checkInfo = enabled,
|
|
|
|
|
+ checkCategory = checkOptionsDraft.checkCategory && enabled,
|
|
|
|
|
+ checkContent = checkOptionsDraft.checkContent && enabled,
|
|
|
|
|
+ )
|
|
|
|
|
+ },
|
|
|
|
|
+ onCheckCategoryChange = { enabled ->
|
|
|
|
|
+ checkOptionsDraft = checkOptionsDraft.copy(
|
|
|
|
|
+ checkCategory = enabled,
|
|
|
|
|
+ checkContent = checkOptionsDraft.checkContent && enabled,
|
|
|
|
|
+ )
|
|
|
|
|
+ },
|
|
|
|
|
+ onCheckContentChange = { checkOptionsDraft = checkOptionsDraft.copy(checkContent = it) },
|
|
|
|
|
+ onConfirm = {
|
|
|
|
|
+ onIntent(BookSourceIntent.UpdateCheckOptions(checkOptionsDraft))
|
|
|
|
|
+ checkSheet = CheckSheet.Run
|
|
|
|
|
+ },
|
|
|
|
|
+ onDismiss = { checkSheet = CheckSheet.Run },
|
|
|
|
|
+ )
|
|
|
|
|
|
|
|
BookSourceGroupFilterSheet(
|
|
BookSourceGroupFilterSheet(
|
|
|
show = showGroupFilterSheet,
|
|
show = showGroupFilterSheet,
|
|
@@ -199,7 +363,7 @@ fun BookSourceScreen(
|
|
|
contentDescription = stringResource(R.string.menu_action_group),
|
|
contentDescription = stringResource(R.string.menu_action_group),
|
|
|
)
|
|
)
|
|
|
},
|
|
},
|
|
|
- snackbarHostState = remember { SnackbarHostState() },
|
|
|
|
|
|
|
+ snackbarHostState = snackbarHostState,
|
|
|
onAddClick = onAddSource,
|
|
onAddClick = onAddSource,
|
|
|
selectionSecondaryActions = listOf(
|
|
selectionSecondaryActions = listOf(
|
|
|
ActionItem(stringResource(R.string.enable_selection)) {
|
|
ActionItem(stringResource(R.string.enable_selection)) {
|
|
@@ -259,6 +423,16 @@ fun BookSourceScreen(
|
|
|
)
|
|
)
|
|
|
)
|
|
)
|
|
|
},
|
|
},
|
|
|
|
|
+ ActionItem(stringResource(R.string.check_book_source)) {
|
|
|
|
|
+ checkSourceIds = selectedIds
|
|
|
|
|
+ checkOptionsDraft = state.checkOptions
|
|
|
|
|
+ checkSheet = CheckSheet.Run
|
|
|
|
|
+ onIntent(BookSourceIntent.SetSelection(emptySet()))
|
|
|
|
|
+ },
|
|
|
|
|
+ ActionItem(stringResource(R.string.export)) {
|
|
|
|
|
+ pendingExportIds = selectedIds
|
|
|
|
|
+ exportDocument.launch("bookSource.json")
|
|
|
|
|
+ },
|
|
|
),
|
|
),
|
|
|
onDeleteSelected = { deleteIds = it as Set<String> },
|
|
onDeleteSelected = { deleteIds = it as Set<String> },
|
|
|
dropDownMenuContent = { dismiss ->
|
|
dropDownMenuContent = { dismiss ->
|
|
@@ -267,7 +441,15 @@ fun BookSourceScreen(
|
|
|
onClick = { dismiss(); groupManage = true })
|
|
onClick = { dismiss(); groupManage = true })
|
|
|
RoundDropdownMenuItem(
|
|
RoundDropdownMenuItem(
|
|
|
text = stringResource(R.string.import_local),
|
|
text = stringResource(R.string.import_local),
|
|
|
- onClick = { dismiss(); onImportLocal() })
|
|
|
|
|
|
|
+ onClick = {
|
|
|
|
|
+ dismiss(); importDocument.launch(
|
|
|
|
|
+ arrayOf(
|
|
|
|
|
+ "application/json",
|
|
|
|
|
+ "text/plain",
|
|
|
|
|
+ "text/*"
|
|
|
|
|
+ )
|
|
|
|
|
+ )
|
|
|
|
|
+ })
|
|
|
RoundDropdownMenuItem(
|
|
RoundDropdownMenuItem(
|
|
|
text = stringResource(R.string.import_on_line),
|
|
text = stringResource(R.string.import_on_line),
|
|
|
onClick = { dismiss(); showOnlineImport = true })
|
|
onClick = { dismiss(); showOnlineImport = true })
|
|
@@ -346,7 +528,10 @@ fun BookSourceScreen(
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
title = item.name,
|
|
title = item.name,
|
|
|
- subtitle = item.group,
|
|
|
|
|
|
|
+ subtitle = listOfNotNull(
|
|
|
|
|
+ item.group,
|
|
|
|
|
+ item.checkMessage
|
|
|
|
|
+ ).joinToString(" · ").ifBlank { null },
|
|
|
isEnabled = item.enabled,
|
|
isEnabled = item.enabled,
|
|
|
isSelected = item.id in selectedIds,
|
|
isSelected = item.id in selectedIds,
|
|
|
canReorder = state.sort == BookSourceSort.Default && !state.groupByDomain,
|
|
canReorder = state.sort == BookSourceSort.Default && !state.groupByDomain,
|
|
@@ -400,6 +585,85 @@ fun BookSourceScreen(
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+@Composable
|
|
|
|
|
+private fun BookSourceImportGroupDialog(
|
|
|
|
|
+ show: Boolean,
|
|
|
|
|
+ initialGroup: String,
|
|
|
|
|
+ initialAdd: Boolean,
|
|
|
|
|
+ onDismissRequest: () -> Unit,
|
|
|
|
|
+ onConfirm: (String, Boolean) -> Unit,
|
|
|
|
|
+) {
|
|
|
|
|
+ var group by remember(show, initialGroup) { mutableStateOf(initialGroup) }
|
|
|
|
|
+ var add by remember(show, initialAdd) { mutableStateOf(initialAdd) }
|
|
|
|
|
+ AppAlertDialog(
|
|
|
|
|
+ show = show,
|
|
|
|
|
+ onDismissRequest = onDismissRequest,
|
|
|
|
|
+ title = stringResource(R.string.diy_source_group),
|
|
|
|
|
+ content = {
|
|
|
|
|
+ Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
|
|
|
|
+ AppTextField(
|
|
|
|
|
+ value = group,
|
|
|
|
|
+ onValueChange = { group = it },
|
|
|
|
|
+ label = stringResource(R.string.group_name),
|
|
|
|
|
+ modifier = Modifier.fillMaxWidth(),
|
|
|
|
|
+ singleLine = true,
|
|
|
|
|
+ )
|
|
|
|
|
+ SwitchSettingItem(
|
|
|
|
|
+ title = stringResource(R.string.add_group),
|
|
|
|
|
+ checked = add,
|
|
|
|
|
+ onCheckedChange = { add = it },
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ confirmText = stringResource(R.string.ok),
|
|
|
|
|
+ onConfirm = { onConfirm(group.trim(), add) },
|
|
|
|
|
+ dismissText = stringResource(R.string.cancel),
|
|
|
|
|
+ onDismiss = onDismissRequest,
|
|
|
|
|
+ )
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+@Composable
|
|
|
|
|
+private fun CheckBookSourceSheet(
|
|
|
|
|
+ sourceIds: Set<String>?,
|
|
|
|
|
+ options: BookSourceCheckOptionsUi,
|
|
|
|
|
+ onDismissRequest: () -> Unit,
|
|
|
|
|
+ onOpenSettings: () -> Unit,
|
|
|
|
|
+ onConfirm: (Set<String>, String, BookSourceCheckOptionsUi) -> Unit,
|
|
|
|
|
+) {
|
|
|
|
|
+ var keyword by remember(sourceIds) { mutableStateOf("我的") }
|
|
|
|
|
+ AppModalBottomSheet(
|
|
|
|
|
+ data = sourceIds,
|
|
|
|
|
+ onDismissRequest = onDismissRequest,
|
|
|
|
|
+ title = stringResource(R.string.check_book_source),
|
|
|
|
|
+ startAction = {
|
|
|
|
|
+ SmallPlainButton(
|
|
|
|
|
+ icon = AppIcons.Settings,
|
|
|
|
|
+ contentDescription = stringResource(R.string.check_source_config),
|
|
|
|
|
+ onClick = onOpenSettings,
|
|
|
|
|
+ )
|
|
|
|
|
+ },
|
|
|
|
|
+ endAction = {
|
|
|
|
|
+ SmallPlainButton(
|
|
|
|
|
+ icon = AppIcons.Check,
|
|
|
|
|
+ contentDescription = stringResource(R.string.check_book_source),
|
|
|
|
|
+ onClick = { sourceIds?.let { onConfirm(it, keyword.trim(), options) } },
|
|
|
|
|
+ )
|
|
|
|
|
+ },
|
|
|
|
|
+ ) {
|
|
|
|
|
+ AppTextField(
|
|
|
|
|
+ value = keyword,
|
|
|
|
|
+ onValueChange = { keyword = it },
|
|
|
|
|
+ label = stringResource(R.string.search_book_key),
|
|
|
|
|
+ modifier = Modifier
|
|
|
|
|
+ .fillMaxWidth()
|
|
|
|
|
+ .padding(bottom = 16.dp),
|
|
|
|
|
+ singleLine = true,
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+private enum class CheckSheet { Run, Settings }
|
|
|
|
|
+
|
|
|
@Composable
|
|
@Composable
|
|
|
private fun BookSourceItemMenu(
|
|
private fun BookSourceItemMenu(
|
|
|
item: BookSourceItemUi,
|
|
item: BookSourceItemUi,
|