Convert settings main and search views to full Compose
This commit is contained in:
parent
761635b572
commit
f5c7aa1142
@ -1,13 +1,18 @@
|
|||||||
package eu.kanade.presentation.components
|
package eu.kanade.presentation.components
|
||||||
|
|
||||||
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.RowScope
|
import androidx.compose.foundation.layout.RowScope
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.statusBars
|
import androidx.compose.foundation.layout.statusBars
|
||||||
|
import androidx.compose.foundation.text.BasicTextField
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.ArrowBack
|
import androidx.compose.material.icons.filled.ArrowBack
|
||||||
import androidx.compose.material.icons.filled.Close
|
import androidx.compose.material.icons.filled.Close
|
||||||
import androidx.compose.material.icons.filled.MoreVert
|
import androidx.compose.material.icons.filled.MoreVert
|
||||||
|
import androidx.compose.material.icons.outlined.ArrowBack
|
||||||
|
import androidx.compose.material.icons.outlined.Close
|
||||||
import androidx.compose.material3.DropdownMenuItem
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
@ -18,18 +23,23 @@ import androidx.compose.material3.TopAppBarDefaults
|
|||||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||||
import androidx.compose.material3.surfaceColorAtElevation
|
import androidx.compose.material3.surfaceColorAtElevation
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.derivedStateOf
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
|
import androidx.compose.ui.focus.focusRequester
|
||||||
|
import androidx.compose.ui.graphics.SolidColor
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AppBar(
|
fun AppBar(
|
||||||
@ -206,6 +216,51 @@ fun AppBarActions(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SearchToolbar(
|
||||||
|
searchQuery: String,
|
||||||
|
onChangeSearchQuery: (String) -> Unit,
|
||||||
|
onClickCloseSearch: () -> Unit,
|
||||||
|
onClickResetSearch: () -> Unit,
|
||||||
|
incognitoMode: Boolean = false,
|
||||||
|
downloadedOnlyMode: Boolean = false,
|
||||||
|
scrollBehavior: TopAppBarScrollBehavior? = null,
|
||||||
|
) {
|
||||||
|
val focusRequester = remember { FocusRequester.Default }
|
||||||
|
AppBar(
|
||||||
|
titleContent = {
|
||||||
|
BasicTextField(
|
||||||
|
value = searchQuery,
|
||||||
|
onValueChange = onChangeSearchQuery,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.focusRequester(focusRequester),
|
||||||
|
textStyle = MaterialTheme.typography.bodyMedium.copy(color = MaterialTheme.colorScheme.onBackground),
|
||||||
|
singleLine = true,
|
||||||
|
cursorBrush = SolidColor(MaterialTheme.colorScheme.onBackground),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
navigationIcon = Icons.Outlined.ArrowBack,
|
||||||
|
navigateUp = onClickCloseSearch,
|
||||||
|
actions = {
|
||||||
|
AnimatedVisibility(visible = searchQuery.isNotEmpty()) {
|
||||||
|
IconButton(onClick = onClickResetSearch) {
|
||||||
|
Icon(Icons.Outlined.Close, contentDescription = stringResource(R.string.action_reset))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isActionMode = false,
|
||||||
|
downloadedOnlyMode = downloadedOnlyMode,
|
||||||
|
incognitoMode = incognitoMode,
|
||||||
|
scrollBehavior = scrollBehavior,
|
||||||
|
)
|
||||||
|
LaunchedEffect(focusRequester) {
|
||||||
|
// TODO: https://issuetracker.google.com/issues/204502668
|
||||||
|
delay(100)
|
||||||
|
focusRequester.requestFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sealed interface AppBar {
|
sealed interface AppBar {
|
||||||
sealed interface AppBarAction
|
sealed interface AppBarAction
|
||||||
|
|
||||||
|
@ -1,30 +1,18 @@
|
|||||||
package eu.kanade.presentation.history.components
|
package eu.kanade.presentation.history.components
|
||||||
|
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.text.BasicTextField
|
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.outlined.ArrowBack
|
|
||||||
import androidx.compose.material.icons.outlined.Close
|
|
||||||
import androidx.compose.material.icons.outlined.DeleteSweep
|
import androidx.compose.material.icons.outlined.DeleteSweep
|
||||||
import androidx.compose.material.icons.outlined.Search
|
import androidx.compose.material.icons.outlined.Search
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.focus.FocusRequester
|
|
||||||
import androidx.compose.ui.focus.focusRequester
|
|
||||||
import androidx.compose.ui.graphics.SolidColor
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import eu.kanade.presentation.components.AppBar
|
import eu.kanade.presentation.components.AppBar
|
||||||
|
import eu.kanade.presentation.components.SearchToolbar
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.ui.recent.history.HistoryPresenter
|
import eu.kanade.tachiyomi.ui.recent.history.HistoryPresenter
|
||||||
import eu.kanade.tachiyomi.ui.recent.history.HistoryState
|
import eu.kanade.tachiyomi.ui.recent.history.HistoryState
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun HistoryToolbar(
|
fun HistoryToolbar(
|
||||||
@ -42,7 +30,7 @@ fun HistoryToolbar(
|
|||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
HistorySearchToolbar(
|
SearchToolbar(
|
||||||
searchQuery = state.searchQuery!!,
|
searchQuery = state.searchQuery!!,
|
||||||
onChangeSearchQuery = { state.searchQuery = it },
|
onChangeSearchQuery = { state.searchQuery = it },
|
||||||
onClickCloseSearch = { state.searchQuery = null },
|
onClickCloseSearch = { state.searchQuery = null },
|
||||||
@ -76,46 +64,3 @@ fun HistoryRegularToolbar(
|
|||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun HistorySearchToolbar(
|
|
||||||
searchQuery: String,
|
|
||||||
onChangeSearchQuery: (String) -> Unit,
|
|
||||||
onClickCloseSearch: () -> Unit,
|
|
||||||
onClickResetSearch: () -> Unit,
|
|
||||||
incognitoMode: Boolean,
|
|
||||||
downloadedOnlyMode: Boolean,
|
|
||||||
) {
|
|
||||||
val focusRequester = remember { FocusRequester.Default }
|
|
||||||
AppBar(
|
|
||||||
titleContent = {
|
|
||||||
BasicTextField(
|
|
||||||
value = searchQuery,
|
|
||||||
onValueChange = onChangeSearchQuery,
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.focusRequester(focusRequester),
|
|
||||||
textStyle = MaterialTheme.typography.bodyMedium.copy(color = MaterialTheme.colorScheme.onBackground),
|
|
||||||
singleLine = true,
|
|
||||||
cursorBrush = SolidColor(MaterialTheme.colorScheme.onBackground),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
navigationIcon = Icons.Outlined.ArrowBack,
|
|
||||||
navigateUp = onClickCloseSearch,
|
|
||||||
actions = {
|
|
||||||
AnimatedVisibility(visible = searchQuery.isNotEmpty()) {
|
|
||||||
IconButton(onClick = onClickResetSearch) {
|
|
||||||
Icon(Icons.Outlined.Close, contentDescription = stringResource(R.string.action_reset))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
isActionMode = false,
|
|
||||||
downloadedOnlyMode = downloadedOnlyMode,
|
|
||||||
incognitoMode = incognitoMode,
|
|
||||||
)
|
|
||||||
LaunchedEffect(focusRequester) {
|
|
||||||
// TODO: https://issuetracker.google.com/issues/204502668
|
|
||||||
delay(100)
|
|
||||||
focusRequester.requestFocus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,12 +1,8 @@
|
|||||||
package eu.kanade.presentation.library.components
|
package eu.kanade.presentation.library.components
|
||||||
|
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.text.BasicTextField
|
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.outlined.Close
|
|
||||||
import androidx.compose.material.icons.outlined.FilterList
|
import androidx.compose.material.icons.outlined.FilterList
|
||||||
import androidx.compose.material.icons.outlined.FlipToBack
|
import androidx.compose.material.icons.outlined.FlipToBack
|
||||||
import androidx.compose.material.icons.outlined.Refresh
|
import androidx.compose.material.icons.outlined.Refresh
|
||||||
@ -19,22 +15,17 @@ import androidx.compose.material3.MaterialTheme
|
|||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.focus.FocusRequester
|
|
||||||
import androidx.compose.ui.focus.focusRequester
|
|
||||||
import androidx.compose.ui.graphics.SolidColor
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import eu.kanade.presentation.components.AppBar
|
import eu.kanade.presentation.components.AppBar
|
||||||
import eu.kanade.presentation.components.Pill
|
import eu.kanade.presentation.components.Pill
|
||||||
|
import eu.kanade.presentation.components.SearchToolbar
|
||||||
import eu.kanade.presentation.library.LibraryState
|
import eu.kanade.presentation.library.LibraryState
|
||||||
import eu.kanade.presentation.theme.active
|
import eu.kanade.presentation.theme.active
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LibraryToolbar(
|
fun LibraryToolbar(
|
||||||
@ -57,14 +48,14 @@ fun LibraryToolbar(
|
|||||||
onClickSelectAll = onClickSelectAll,
|
onClickSelectAll = onClickSelectAll,
|
||||||
onClickInvertSelection = onClickInvertSelection,
|
onClickInvertSelection = onClickInvertSelection,
|
||||||
)
|
)
|
||||||
state.searchQuery != null -> LibrarySearchToolbar(
|
state.searchQuery != null -> SearchToolbar(
|
||||||
searchQuery = state.searchQuery!!,
|
searchQuery = state.searchQuery!!,
|
||||||
incognitoMode = incognitoMode,
|
|
||||||
downloadedOnlyMode = downloadedOnlyMode,
|
|
||||||
onChangeSearchQuery = { state.searchQuery = it },
|
onChangeSearchQuery = { state.searchQuery = it },
|
||||||
onClickCloseSearch = { state.searchQuery = null },
|
onClickCloseSearch = { state.searchQuery = null },
|
||||||
onClickResetSearch = { state.searchQuery = "" },
|
onClickResetSearch = { state.searchQuery = "" },
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
|
incognitoMode = incognitoMode,
|
||||||
|
downloadedOnlyMode = downloadedOnlyMode,
|
||||||
)
|
)
|
||||||
else -> LibraryRegularToolbar(
|
else -> LibraryRegularToolbar(
|
||||||
title = title,
|
title = title,
|
||||||
@ -152,49 +143,6 @@ fun LibrarySelectionToolbar(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun LibrarySearchToolbar(
|
|
||||||
searchQuery: String,
|
|
||||||
incognitoMode: Boolean,
|
|
||||||
downloadedOnlyMode: Boolean,
|
|
||||||
onChangeSearchQuery: (String) -> Unit,
|
|
||||||
onClickCloseSearch: () -> Unit,
|
|
||||||
onClickResetSearch: () -> Unit,
|
|
||||||
scrollBehavior: TopAppBarScrollBehavior?,
|
|
||||||
) {
|
|
||||||
val focusRequester = remember { FocusRequester.Default }
|
|
||||||
AppBar(
|
|
||||||
navigateUp = onClickCloseSearch,
|
|
||||||
titleContent = {
|
|
||||||
BasicTextField(
|
|
||||||
value = searchQuery,
|
|
||||||
onValueChange = onChangeSearchQuery,
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.focusRequester(focusRequester),
|
|
||||||
textStyle = MaterialTheme.typography.bodyMedium.copy(color = MaterialTheme.colorScheme.onBackground),
|
|
||||||
singleLine = true,
|
|
||||||
cursorBrush = SolidColor(MaterialTheme.colorScheme.onBackground),
|
|
||||||
)
|
|
||||||
LaunchedEffect(focusRequester) {
|
|
||||||
// TODO: https://issuetracker.google.com/issues/204502668
|
|
||||||
delay(100)
|
|
||||||
focusRequester.requestFocus()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
actions = {
|
|
||||||
AnimatedVisibility(visible = searchQuery.isNotEmpty()) {
|
|
||||||
IconButton(onClick = onClickResetSearch) {
|
|
||||||
Icon(Icons.Outlined.Close, contentDescription = stringResource(R.string.action_reset))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
incognitoMode = incognitoMode,
|
|
||||||
downloadedOnlyMode = downloadedOnlyMode,
|
|
||||||
scrollBehavior = scrollBehavior,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
data class LibraryToolbarTitle(
|
data class LibraryToolbarTitle(
|
||||||
val text: String,
|
val text: String,
|
||||||
val numberOfManga: Int? = null,
|
val numberOfManga: Int? = null,
|
||||||
|
@ -4,31 +4,58 @@ import androidx.annotation.StringRes
|
|||||||
import androidx.compose.foundation.layout.WindowInsets
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
import androidx.compose.foundation.layout.asPaddingValues
|
import androidx.compose.foundation.layout.asPaddingValues
|
||||||
import androidx.compose.foundation.layout.navigationBars
|
import androidx.compose.foundation.layout.navigationBars
|
||||||
|
import androidx.compose.foundation.layout.statusBarsPadding
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.outlined.Search
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.painter.Painter
|
import androidx.compose.ui.graphics.painter.Painter
|
||||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import eu.kanade.presentation.components.AppBar
|
||||||
|
import eu.kanade.presentation.components.AppBarActions
|
||||||
import eu.kanade.presentation.components.PreferenceRow
|
import eu.kanade.presentation.components.PreferenceRow
|
||||||
|
import eu.kanade.presentation.components.Scaffold
|
||||||
import eu.kanade.presentation.components.ScrollbarLazyColumn
|
import eu.kanade.presentation.components.ScrollbarLazyColumn
|
||||||
|
import eu.kanade.presentation.util.plus
|
||||||
|
import eu.kanade.tachiyomi.R
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SettingsMainScreen(
|
fun SettingsMainScreen(
|
||||||
nestedScrollInterop: NestedScrollConnection,
|
navigateUp: () -> Unit,
|
||||||
sections: List<SettingsSection>,
|
sections: List<SettingsSection>,
|
||||||
|
onClickSearch: () -> Unit,
|
||||||
) {
|
) {
|
||||||
ScrollbarLazyColumn(
|
Scaffold(
|
||||||
modifier = Modifier.nestedScroll(nestedScrollInterop),
|
modifier = Modifier.statusBarsPadding(),
|
||||||
contentPadding = WindowInsets.navigationBars.asPaddingValues(),
|
topBar = {
|
||||||
) {
|
AppBar(
|
||||||
sections.map {
|
title = stringResource(R.string.label_settings),
|
||||||
item {
|
navigateUp = navigateUp,
|
||||||
PreferenceRow(
|
actions = {
|
||||||
title = stringResource(it.titleRes),
|
AppBarActions(
|
||||||
painter = it.painter,
|
listOf(
|
||||||
onClick = it.onClick,
|
AppBar.Action(
|
||||||
)
|
title = stringResource(R.string.action_search),
|
||||||
|
icon = Icons.Outlined.Search,
|
||||||
|
onClick = onClickSearch,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
) { paddingValues ->
|
||||||
|
ScrollbarLazyColumn(
|
||||||
|
contentPadding = paddingValues + WindowInsets.navigationBars.asPaddingValues(),
|
||||||
|
) {
|
||||||
|
sections.map {
|
||||||
|
item {
|
||||||
|
PreferenceRow(
|
||||||
|
title = stringResource(it.titleRes),
|
||||||
|
painter = it.painter,
|
||||||
|
onClick = it.onClick,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,19 +7,23 @@ import androidx.compose.foundation.layout.asPaddingValues
|
|||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.navigationBars
|
import androidx.compose.foundation.layout.navigationBars
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.statusBarsPadding
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import eu.kanade.presentation.components.Scaffold
|
||||||
import eu.kanade.presentation.components.ScrollbarLazyColumn
|
import eu.kanade.presentation.components.ScrollbarLazyColumn
|
||||||
|
import eu.kanade.presentation.components.SearchToolbar
|
||||||
import eu.kanade.presentation.util.horizontalPadding
|
import eu.kanade.presentation.util.horizontalPadding
|
||||||
|
import eu.kanade.presentation.util.plus
|
||||||
import eu.kanade.tachiyomi.ui.setting.SettingsController
|
import eu.kanade.tachiyomi.ui.setting.SettingsController
|
||||||
import eu.kanade.tachiyomi.ui.setting.search.SettingsSearchHelper
|
import eu.kanade.tachiyomi.ui.setting.search.SettingsSearchHelper
|
||||||
import eu.kanade.tachiyomi.ui.setting.search.SettingsSearchPresenter
|
import eu.kanade.tachiyomi.ui.setting.search.SettingsSearchPresenter
|
||||||
@ -27,24 +31,39 @@ import kotlin.reflect.full.createInstance
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SettingsSearchScreen(
|
fun SettingsSearchScreen(
|
||||||
nestedScroll: NestedScrollConnection,
|
navigateUp: () -> Unit,
|
||||||
presenter: SettingsSearchPresenter,
|
presenter: SettingsSearchPresenter,
|
||||||
onClickResult: (SettingsController) -> Unit,
|
onClickResult: (SettingsController) -> Unit,
|
||||||
) {
|
) {
|
||||||
val results by presenter.state.collectAsState()
|
val results by presenter.state.collectAsState()
|
||||||
|
var query by remember { mutableStateOf("") }
|
||||||
|
|
||||||
val scrollState = rememberLazyListState()
|
Scaffold(
|
||||||
ScrollbarLazyColumn(
|
modifier = Modifier.statusBarsPadding(),
|
||||||
modifier = Modifier
|
topBar = {
|
||||||
.nestedScroll(nestedScroll),
|
SearchToolbar(
|
||||||
contentPadding = WindowInsets.navigationBars.asPaddingValues(),
|
searchQuery = query,
|
||||||
state = scrollState,
|
onChangeSearchQuery = {
|
||||||
) {
|
query = it
|
||||||
items(
|
presenter.searchSettings(it)
|
||||||
items = results,
|
},
|
||||||
key = { it.key.toString() },
|
onClickCloseSearch = navigateUp,
|
||||||
) { result ->
|
onClickResetSearch = { query = "" },
|
||||||
SearchResult(result, onClickResult)
|
)
|
||||||
|
|
||||||
|
// TODO: search placeholder
|
||||||
|
// Text(stringResource(R.string.action_search_settings))
|
||||||
|
},
|
||||||
|
) { paddingValues ->
|
||||||
|
ScrollbarLazyColumn(
|
||||||
|
contentPadding = paddingValues + WindowInsets.navigationBars.asPaddingValues(),
|
||||||
|
) {
|
||||||
|
items(
|
||||||
|
items = results,
|
||||||
|
key = { it.key.toString() },
|
||||||
|
) { result ->
|
||||||
|
SearchResult(result, onClickResult)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -299,8 +299,6 @@ class PreferencesHelper(val context: Context) {
|
|||||||
|
|
||||||
fun defaultUserAgent() = flowPrefs.getString(Keys.defaultUserAgent, "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:103.0) Gecko/20100101 Firefox/103.0")
|
fun defaultUserAgent() = flowPrefs.getString(Keys.defaultUserAgent, "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:103.0) Gecko/20100101 Firefox/103.0")
|
||||||
|
|
||||||
fun lastSearchQuerySearchSettings() = flowPrefs.getString("last_search_query", "")
|
|
||||||
|
|
||||||
fun filterChapterByRead() = prefs.getInt(Keys.defaultChapterFilterByRead, DomainManga.SHOW_ALL.toInt())
|
fun filterChapterByRead() = prefs.getInt(Keys.defaultChapterFilterByRead, DomainManga.SHOW_ALL.toInt())
|
||||||
|
|
||||||
fun filterChapterByDownloaded() = prefs.getInt(Keys.defaultChapterFilterByDownloaded, DomainManga.SHOW_ALL.toInt())
|
fun filterChapterByDownloaded() = prefs.getInt(Keys.defaultChapterFilterByDownloaded, DomainManga.SHOW_ALL.toInt())
|
||||||
|
@ -51,28 +51,6 @@ abstract class ComposeController<P : Presenter<*>>(bundle: Bundle? = null) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Basic Compose controller without a presenter.
|
|
||||||
*/
|
|
||||||
abstract class BasicComposeController :
|
|
||||||
BaseController<ComposeControllerBinding>(),
|
|
||||||
ComposeContentController {
|
|
||||||
|
|
||||||
override fun createBinding(inflater: LayoutInflater) =
|
|
||||||
ComposeControllerBinding.inflate(inflater)
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View) {
|
|
||||||
super.onViewCreated(view)
|
|
||||||
|
|
||||||
binding.root.apply {
|
|
||||||
setComposeContent {
|
|
||||||
val nestedScrollInterop = rememberNestedScrollInteropConnection()
|
|
||||||
ComposeContent(nestedScrollInterop)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic Compose controller without a presenter.
|
* Basic Compose controller without a presenter.
|
||||||
*/
|
*/
|
||||||
|
@ -37,7 +37,7 @@ class ExtensionDetailsPresenter(
|
|||||||
|
|
||||||
presenterScope.launchIO {
|
presenterScope.launchIO {
|
||||||
extensionManager.getInstalledExtensionsFlow()
|
extensionManager.getInstalledExtensionsFlow()
|
||||||
.map { it.firstOrNull { pkg-> pkg.pkgName == pkgName } }
|
.map { it.firstOrNull { pkg -> pkg.pkgName == pkgName } }
|
||||||
.collectLatest { extension ->
|
.collectLatest { extension ->
|
||||||
// If extension is null it's most likely uninstalled
|
// If extension is null it's most likely uninstalled
|
||||||
if (extension == null) {
|
if (extension == null) {
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
package eu.kanade.tachiyomi.ui.setting
|
package eu.kanade.tachiyomi.ui.setting
|
||||||
|
|
||||||
import android.view.Menu
|
|
||||||
import android.view.MenuInflater
|
|
||||||
import android.view.MenuItem
|
|
||||||
import androidx.appcompat.widget.SearchView
|
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.outlined.ChromeReaderMode
|
import androidx.compose.material.icons.outlined.ChromeReaderMode
|
||||||
import androidx.compose.material.icons.outlined.Code
|
import androidx.compose.material.icons.outlined.Code
|
||||||
@ -15,25 +11,18 @@ import androidx.compose.material.icons.outlined.Sync
|
|||||||
import androidx.compose.material.icons.outlined.Tune
|
import androidx.compose.material.icons.outlined.Tune
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
||||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import eu.kanade.presentation.more.settings.SettingsMainScreen
|
import eu.kanade.presentation.more.settings.SettingsMainScreen
|
||||||
import eu.kanade.presentation.more.settings.SettingsSection
|
import eu.kanade.presentation.more.settings.SettingsSection
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.ui.base.controller.BasicFullComposeController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.BasicComposeController
|
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.pushController
|
import eu.kanade.tachiyomi.ui.base.controller.pushController
|
||||||
import eu.kanade.tachiyomi.ui.setting.search.SettingsSearchController
|
import eu.kanade.tachiyomi.ui.setting.search.SettingsSearchController
|
||||||
import uy.kohesive.injekt.injectLazy
|
|
||||||
|
|
||||||
class SettingsMainController : BasicComposeController() {
|
class SettingsMainController : BasicFullComposeController() {
|
||||||
|
|
||||||
private val preferences: PreferencesHelper by injectLazy()
|
|
||||||
|
|
||||||
override fun getTitle() = resources?.getString(R.string.label_settings)
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun ComposeContent(nestedScrollInterop: NestedScrollConnection) {
|
override fun ComposeContent() {
|
||||||
val settingsSections = listOf(
|
val settingsSections = listOf(
|
||||||
SettingsSection(
|
SettingsSection(
|
||||||
titleRes = R.string.pref_category_general,
|
titleRes = R.string.pref_category_general,
|
||||||
@ -88,34 +77,9 @@ class SettingsMainController : BasicComposeController() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
SettingsMainScreen(
|
SettingsMainScreen(
|
||||||
nestedScrollInterop = nestedScrollInterop,
|
navigateUp = router::popCurrentController,
|
||||||
sections = settingsSections,
|
sections = settingsSections,
|
||||||
)
|
onClickSearch = { router.pushController(SettingsSearchController()) },
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
|
||||||
inflater.inflate(R.menu.settings_main, menu)
|
|
||||||
|
|
||||||
// Initialize search option.
|
|
||||||
val searchItem = menu.findItem(R.id.action_search)
|
|
||||||
val searchView = searchItem.actionView as SearchView
|
|
||||||
searchView.maxWidth = Int.MAX_VALUE
|
|
||||||
|
|
||||||
// Change hint to show global search.
|
|
||||||
searchView.queryHint = applicationContext?.getString(R.string.action_search_settings)
|
|
||||||
|
|
||||||
searchItem.setOnActionExpandListener(
|
|
||||||
object : MenuItem.OnActionExpandListener {
|
|
||||||
override fun onMenuItemActionExpand(item: MenuItem): Boolean {
|
|
||||||
preferences.lastSearchQuerySearchSettings().set("") // reset saved search query
|
|
||||||
router.pushController(SettingsSearchController())
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onMenuItemActionCollapse(item: MenuItem): Boolean {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,80 +1,20 @@
|
|||||||
package eu.kanade.tachiyomi.ui.setting.search
|
package eu.kanade.tachiyomi.ui.setting.search
|
||||||
|
|
||||||
import android.view.Menu
|
|
||||||
import android.view.MenuInflater
|
|
||||||
import android.view.MenuItem
|
|
||||||
import androidx.appcompat.widget.SearchView
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
|
||||||
import eu.kanade.presentation.more.settings.SettingsSearchScreen
|
import eu.kanade.presentation.more.settings.SettingsSearchScreen
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.ui.base.controller.FullComposeController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.ComposeController
|
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.pushController
|
import eu.kanade.tachiyomi.ui.base.controller.pushController
|
||||||
|
|
||||||
class SettingsSearchController : ComposeController<SettingsSearchPresenter>() {
|
class SettingsSearchController : FullComposeController<SettingsSearchPresenter>() {
|
||||||
|
|
||||||
private lateinit var searchView: SearchView
|
|
||||||
|
|
||||||
init {
|
|
||||||
setHasOptionsMenu(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getTitle() = presenter.query
|
|
||||||
|
|
||||||
override fun createPresenter() = SettingsSearchPresenter()
|
override fun createPresenter() = SettingsSearchPresenter()
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun ComposeContent(nestedScrollInterop: NestedScrollConnection) {
|
override fun ComposeContent() {
|
||||||
SettingsSearchScreen(
|
SettingsSearchScreen(
|
||||||
nestedScroll = nestedScrollInterop,
|
navigateUp = router::popCurrentController,
|
||||||
presenter = presenter,
|
presenter = presenter,
|
||||||
onClickResult = { controller ->
|
onClickResult = { router.pushController(it) },
|
||||||
searchView.query.let {
|
|
||||||
presenter.setLastSearchQuerySearchSettings(it.toString())
|
|
||||||
}
|
|
||||||
router.pushController(controller)
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
|
||||||
inflater.inflate(R.menu.settings_main, menu)
|
|
||||||
|
|
||||||
// Initialize search menu
|
|
||||||
val searchItem = menu.findItem(R.id.action_search)
|
|
||||||
searchView = searchItem.actionView as SearchView
|
|
||||||
searchView.maxWidth = Int.MAX_VALUE
|
|
||||||
searchView.queryHint = applicationContext?.getString(R.string.action_search_settings)
|
|
||||||
|
|
||||||
searchItem.expandActionView()
|
|
||||||
|
|
||||||
searchItem.setOnActionExpandListener(
|
|
||||||
object : MenuItem.OnActionExpandListener {
|
|
||||||
override fun onMenuItemActionExpand(item: MenuItem): Boolean {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onMenuItemActionCollapse(item: MenuItem): Boolean {
|
|
||||||
router.popCurrentController()
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
searchView.setOnQueryTextListener(
|
|
||||||
object : SearchView.OnQueryTextListener {
|
|
||||||
override fun onQueryTextSubmit(query: String?): Boolean {
|
|
||||||
presenter.searchSettings(query)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onQueryTextChange(newText: String?): Boolean {
|
|
||||||
presenter.searchSettings(newText)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
searchView.setQuery(presenter.getLastSearchQuerySearchSettings(), true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -23,14 +23,6 @@ class SettingsSearchPresenter(
|
|||||||
SettingsSearchHelper.initPreferenceSearchResults(preferences.context)
|
SettingsSearchHelper.initPreferenceSearchResults(preferences.context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getLastSearchQuerySearchSettings(): String {
|
|
||||||
return preferences.lastSearchQuerySearchSettings().get()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setLastSearchQuerySearchSettings(query: String) {
|
|
||||||
preferences.lastSearchQuerySearchSettings().set(query)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun searchSettings(query: String?) {
|
fun searchSettings(query: String?) {
|
||||||
_state.value = if (!query.isNullOrBlank()) {
|
_state.value = if (!query.isNullOrBlank()) {
|
||||||
SettingsSearchHelper.getFilteredResults(query)
|
SettingsSearchHelper.getFilteredResults(query)
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/action_search"
|
|
||||||
android:icon="@drawable/ic_search_24dp"
|
|
||||||
android:title="@string/action_search"
|
|
||||||
app:actionViewClass="eu.kanade.tachiyomi.widget.TachiyomiSearchView"
|
|
||||||
app:iconTint="?attr/colorOnSurface"
|
|
||||||
app:showAsAction="collapseActionView|ifRoom" />
|
|
||||||
|
|
||||||
</menu>
|
|
Loading…
Reference in New Issue
Block a user