198 lines
6.9 KiB
Kotlin
Raw Normal View History

package eu.kanade.presentation.browse
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.items
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.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import eu.kanade.presentation.browse.components.BaseSourceItem
import eu.kanade.tachiyomi.R
2022-11-24 10:28:25 +07:00
import eu.kanade.tachiyomi.ui.browse.source.SourcesState
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreenModel.Listing
import eu.kanade.tachiyomi.util.system.LocaleHelper
2023-01-22 11:04:50 -05:00
import tachiyomi.domain.source.model.Pin
import tachiyomi.domain.source.model.Source
import tachiyomi.presentation.core.components.ScrollbarLazyColumn
import tachiyomi.presentation.core.components.material.padding
import tachiyomi.presentation.core.components.material.topSmallPaddingValues
import tachiyomi.presentation.core.screens.EmptyScreen
import tachiyomi.presentation.core.screens.LoadingScreen
2023-02-18 17:04:32 -05:00
import tachiyomi.presentation.core.theme.header
import tachiyomi.presentation.core.util.plus
import tachiyomi.source.local.LocalSource
@Composable
2022-05-15 17:03:57 -04:00
fun SourcesScreen(
2022-11-24 10:28:25 +07:00
state: SourcesState,
contentPadding: PaddingValues,
onClickItem: (Source, Listing) -> Unit,
onClickPin: (Source) -> Unit,
2022-11-24 10:28:25 +07:00
onLongClickItem: (Source) -> Unit,
) {
when {
2022-11-24 10:28:25 +07:00
state.isLoading -> LoadingScreen(modifier = Modifier.padding(contentPadding))
state.isEmpty -> EmptyScreen(
textResource = R.string.source_empty_screen,
modifier = Modifier.padding(contentPadding),
)
else -> {
2022-11-24 10:28:25 +07:00
ScrollbarLazyColumn(
contentPadding = contentPadding + topSmallPaddingValues,
) {
items(
items = state.items,
contentType = {
when (it) {
is SourceUiModel.Header -> "header"
is SourceUiModel.Item -> "item"
}
},
key = {
when (it) {
is SourceUiModel.Header -> it.hashCode()
is SourceUiModel.Item -> "source-${it.source.key()}"
}
},
) { model ->
when (model) {
is SourceUiModel.Header -> {
SourceHeader(
modifier = Modifier.animateItemPlacement(),
language = model.language,
)
}
is SourceUiModel.Item -> SourceItem(
modifier = Modifier.animateItemPlacement(),
source = model.source,
onClickItem = onClickItem,
onLongClickItem = onLongClickItem,
onClickPin = onClickPin,
)
}
}
}
}
}
}
@Composable
private fun SourceHeader(
modifier: Modifier = Modifier,
2022-05-10 17:54:52 -04:00
language: String,
) {
val context = LocalContext.current
Text(
text = LocaleHelper.getSourceDisplayName(language, context),
modifier = modifier
2022-11-13 18:11:51 +01:00
.padding(horizontal = MaterialTheme.padding.medium, vertical = MaterialTheme.padding.small),
2022-05-10 17:54:52 -04:00
style = MaterialTheme.typography.header,
)
}
@Composable
private fun SourceItem(
modifier: Modifier = Modifier,
source: Source,
onClickItem: (Source, Listing) -> Unit,
onLongClickItem: (Source) -> Unit,
2022-05-10 17:54:52 -04:00
onClickPin: (Source) -> Unit,
) {
BaseSourceItem(
modifier = modifier,
source = source,
onClickItem = { onClickItem(source, Listing.Popular) },
onLongClickItem = { onLongClickItem(source) },
action = {
if (source.supportsLatest) {
TextButton(onClick = { onClickItem(source, Listing.Latest) }) {
Text(
2022-05-19 17:43:27 -04:00
text = stringResource(R.string.latest),
style = LocalTextStyle.current.copy(
2022-05-10 17:54:52 -04:00
color = MaterialTheme.colorScheme.primary,
),
)
}
}
SourcePinButton(
isPinned = Pin.Pinned in source.pin,
2022-05-10 17:54:52 -04:00
onClick = { onClickPin(source) },
)
},
)
}
@Composable
private fun SourcePinButton(
isPinned: Boolean,
2022-05-10 17:54:52 -04:00
onClick: () -> Unit,
) {
val icon = if (isPinned) Icons.Filled.PushPin else Icons.Outlined.PushPin
val tint = if (isPinned) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onBackground
val description = if (isPinned) R.string.action_unpin else R.string.action_pin
IconButton(onClick = onClick) {
Icon(
imageVector = icon,
2022-05-10 17:54:52 -04:00
tint = tint,
contentDescription = stringResource(description),
)
}
}
@Composable
2022-11-24 10:28:25 +07:00
fun SourceOptionsDialog(
source: Source,
onClickPin: () -> Unit,
onClickDisable: () -> Unit,
onDismiss: () -> Unit,
) {
AlertDialog(
title = {
Text(text = source.visualName)
},
text = {
Column {
val textId = if (Pin.Pinned in source.pin) R.string.action_unpin else R.string.action_pin
Text(
text = stringResource(textId),
modifier = Modifier
.clickable(onClick = onClickPin)
.fillMaxWidth()
2022-05-10 17:54:52 -04:00
.padding(vertical = 16.dp),
)
if (source.id != LocalSource.ID) {
Text(
2022-05-19 17:43:27 -04:00
text = stringResource(R.string.action_disable),
modifier = Modifier
.clickable(onClick = onClickDisable)
.fillMaxWidth()
2022-05-10 17:54:52 -04:00
.padding(vertical = 16.dp),
)
}
}
},
onDismissRequest = onDismiss,
confirmButton = {},
)
}
sealed class SourceUiModel {
data class Item(val source: Source) : SourceUiModel()
data class Header(val language: String) : SourceUiModel()
}