mirror of
https://github.com/mihonapp/mihon.git
synced 2025-11-12 12:08:56 +01:00
Use Compose in Migrate tab (#7008)
* Use Compose in Migrate tab * Add missing header * Remove unused files * Fix build after rebase * Changes from review comments
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
package eu.kanade.presentation.components
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun LoadingScreen() {
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
CircularProgressIndicator(modifier = Modifier.size(64.dp))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package eu.kanade.presentation.source
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.asPaddingValues
|
||||
import androidx.compose.foundation.layout.navigationBars
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.domain.source.model.Source
|
||||
import eu.kanade.presentation.components.EmptyScreen
|
||||
import eu.kanade.presentation.components.LoadingScreen
|
||||
import eu.kanade.presentation.source.components.BaseSourceItem
|
||||
import eu.kanade.presentation.theme.header
|
||||
import eu.kanade.presentation.util.horizontalPadding
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.browse.migration.sources.MigrationSourcesPresenter
|
||||
|
||||
@Composable
|
||||
fun MigrateSourceScreen(
|
||||
nestedScrollInterop: NestedScrollConnection,
|
||||
presenter: MigrationSourcesPresenter,
|
||||
onClickItem: (Source) -> Unit,
|
||||
onLongClickItem: (Source) -> Unit,
|
||||
) {
|
||||
val state by presenter.state.collectAsState()
|
||||
when {
|
||||
state.isLoading -> LoadingScreen()
|
||||
state.isEmpty -> EmptyScreen(textResource = R.string.information_empty_library)
|
||||
else -> {
|
||||
MigrateSourceList(
|
||||
nestedScrollInterop = nestedScrollInterop,
|
||||
list = state.sources!!,
|
||||
onClickItem = onClickItem,
|
||||
onLongClickItem = onLongClickItem,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun MigrateSourceList(
|
||||
nestedScrollInterop: NestedScrollConnection,
|
||||
list: List<Pair<Source, Long>>,
|
||||
onClickItem: (Source) -> Unit,
|
||||
onLongClickItem: (Source) -> Unit,
|
||||
) {
|
||||
LazyColumn(
|
||||
modifier = Modifier.nestedScroll(nestedScrollInterop),
|
||||
contentPadding = WindowInsets.navigationBars.asPaddingValues(),
|
||||
) {
|
||||
item(key = "title") {
|
||||
Text(
|
||||
text = stringResource(id = R.string.migration_selection_prompt),
|
||||
modifier = Modifier
|
||||
.animateItemPlacement()
|
||||
.padding(horizontal = horizontalPadding, vertical = 8.dp),
|
||||
style = MaterialTheme.typography.header
|
||||
)
|
||||
}
|
||||
|
||||
items(
|
||||
items = list,
|
||||
key = { (source, _) ->
|
||||
source.id
|
||||
}
|
||||
) { (source, count) ->
|
||||
MigrateSourceItem(
|
||||
modifier = Modifier.animateItemPlacement(),
|
||||
source = source,
|
||||
count = count,
|
||||
onClickItem = { onClickItem(source) },
|
||||
onLongClickItem = { onLongClickItem(source) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun MigrateSourceItem(
|
||||
modifier: Modifier = Modifier,
|
||||
source: Source,
|
||||
count: Long,
|
||||
onClickItem: () -> Unit,
|
||||
onLongClickItem: () -> Unit,
|
||||
) {
|
||||
BaseSourceItem(
|
||||
modifier = modifier,
|
||||
source = source,
|
||||
onClickItem = onClickItem,
|
||||
onLongClickItem = onLongClickItem,
|
||||
action = {
|
||||
Text(
|
||||
text = "$count",
|
||||
modifier = Modifier
|
||||
.clip(RoundedCornerShape(4.dp))
|
||||
.background(MaterialTheme.colorScheme.primary)
|
||||
.padding(horizontal = 8.dp, vertical = 2.dp),
|
||||
style = MaterialTheme.typography.bodyMedium.copy(
|
||||
color = MaterialTheme.colorScheme.onPrimary
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -2,9 +2,7 @@ package eu.kanade.presentation.source
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.combinedClickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.asPaddingValues
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
@@ -18,7 +16,6 @@ import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.PushPin
|
||||
import androidx.compose.material.icons.outlined.PushPin
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
@@ -30,18 +27,18 @@ import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.domain.source.model.Pin
|
||||
import eu.kanade.domain.source.model.Source
|
||||
import eu.kanade.presentation.components.EmptyScreen
|
||||
import eu.kanade.presentation.components.LoadingScreen
|
||||
import eu.kanade.presentation.source.components.BaseSourceItem
|
||||
import eu.kanade.presentation.theme.header
|
||||
import eu.kanade.presentation.util.horizontalPadding
|
||||
import eu.kanade.tachiyomi.R
|
||||
@@ -62,7 +59,7 @@ fun SourceScreen(
|
||||
val state by presenter.state.collectAsState()
|
||||
|
||||
when {
|
||||
state.isLoading -> CircularProgressIndicator()
|
||||
state.isLoading -> LoadingScreen()
|
||||
state.hasError -> Text(text = state.error!!.message!!)
|
||||
state.isEmpty -> EmptyScreen(message = "")
|
||||
else -> SourceList(
|
||||
@@ -115,7 +112,7 @@ fun SourceList(
|
||||
}
|
||||
is UiModel.Item -> SourceItem(
|
||||
modifier = Modifier.animateItemPlacement(),
|
||||
item = model.source,
|
||||
source = model.source,
|
||||
onClickItem = onClickItem,
|
||||
onLongClickItem = {
|
||||
setSourceState(it)
|
||||
@@ -160,55 +157,34 @@ fun SourceHeader(
|
||||
@Composable
|
||||
fun SourceItem(
|
||||
modifier: Modifier = Modifier,
|
||||
item: Source,
|
||||
source: Source,
|
||||
onClickItem: (Source) -> Unit,
|
||||
onLongClickItem: (Source) -> Unit,
|
||||
onClickLatest: (Source) -> Unit,
|
||||
onClickPin: (Source) -> Unit
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.combinedClickable(
|
||||
onClick = { onClickItem(item) },
|
||||
onLongClick = { onLongClickItem(item) }
|
||||
)
|
||||
.padding(horizontal = horizontalPadding, vertical = 8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
SourceIcon(source = item)
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = horizontalPadding)
|
||||
.weight(1f)
|
||||
) {
|
||||
Text(
|
||||
text = item.name,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
)
|
||||
Text(
|
||||
text = LocaleHelper.getDisplayName(item.lang),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
style = MaterialTheme.typography.bodySmall
|
||||
)
|
||||
}
|
||||
if (item.supportsLatest) {
|
||||
TextButton(onClick = { onClickLatest(item) }) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.latest),
|
||||
style = LocalTextStyle.current.copy(
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
),
|
||||
)
|
||||
BaseSourceItem(
|
||||
modifier = modifier,
|
||||
source = source,
|
||||
onClickItem = { onClickItem(source) },
|
||||
onLongClickItem = { onLongClickItem(source) },
|
||||
action = { source ->
|
||||
if (source.supportsLatest) {
|
||||
TextButton(onClick = { onClickLatest(source) }) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.latest),
|
||||
style = LocalTextStyle.current.copy(
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
SourcePinButton(
|
||||
isPinned = Pin.Pinned in item.pin,
|
||||
onClick = { onClickPin(item) }
|
||||
)
|
||||
}
|
||||
SourcePinButton(
|
||||
isPinned = Pin.Pinned in source.pin,
|
||||
onClick = { onClickPin(source) }
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package eu.kanade.presentation.source.components
|
||||
|
||||
import androidx.compose.foundation.combinedClickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import eu.kanade.domain.source.model.Source
|
||||
import eu.kanade.presentation.source.SourceIcon
|
||||
import eu.kanade.presentation.util.horizontalPadding
|
||||
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
||||
|
||||
@Composable
|
||||
fun BaseSourceItem(
|
||||
modifier: Modifier = Modifier,
|
||||
source: Source,
|
||||
onClickItem: () -> Unit = {},
|
||||
onLongClickItem: () -> Unit = {},
|
||||
icon: @Composable RowScope.(Source) -> Unit = defaultIcon,
|
||||
action: @Composable RowScope.(Source) -> Unit = {},
|
||||
content: @Composable RowScope.(Source) -> Unit = defaultContent,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.combinedClickable(
|
||||
onClick = onClickItem,
|
||||
onLongClick = onLongClickItem
|
||||
)
|
||||
.padding(horizontal = horizontalPadding, vertical = 8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
icon.invoke(this, source)
|
||||
content.invoke(this, source)
|
||||
action.invoke(this, source)
|
||||
}
|
||||
}
|
||||
|
||||
private val defaultIcon: @Composable RowScope.(Source) -> Unit = { source ->
|
||||
SourceIcon(source = source)
|
||||
}
|
||||
|
||||
private val defaultContent: @Composable RowScope.(Source) -> Unit = { source ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = horizontalPadding)
|
||||
.weight(1f)
|
||||
) {
|
||||
Text(
|
||||
text = source.name,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
)
|
||||
Text(
|
||||
text = LocaleHelper.getDisplayName(source.lang),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
style = MaterialTheme.typography.bodySmall
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user