2022-05-07 23:34:55 -04:00
|
|
|
package eu.kanade.presentation.browse
|
2022-04-24 20:35:59 +02:00
|
|
|
|
|
|
|
import androidx.compose.foundation.clickable
|
|
|
|
import androidx.compose.foundation.layout.Column
|
2022-10-10 02:52:56 +07:00
|
|
|
import androidx.compose.foundation.layout.PaddingValues
|
2022-04-24 20:35:59 +02:00
|
|
|
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
|
2022-04-24 15:04:00 -04:00
|
|
|
import androidx.compose.material3.LocalTextStyle
|
2022-04-24 20:35:59 +02:00
|
|
|
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
|
2022-05-07 23:34:55 -04:00
|
|
|
import eu.kanade.presentation.browse.components.BaseSourceItem
|
2022-04-24 20:35:59 +02:00
|
|
|
import eu.kanade.tachiyomi.R
|
2023-07-16 18:43:37 -04:00
|
|
|
import eu.kanade.tachiyomi.ui.browse.source.SourcesScreenModel
|
2022-12-18 03:51:03 +08:00
|
|
|
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreenModel.Listing
|
2022-04-24 20:35:59 +02:00
|
|
|
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
|
2023-02-18 16:33:03 -05:00
|
|
|
import tachiyomi.presentation.core.components.ScrollbarLazyColumn
|
2023-03-28 23:01:22 -04:00
|
|
|
import tachiyomi.presentation.core.components.material.SecondaryItemAlpha
|
2023-02-18 16:03:01 -05:00
|
|
|
import tachiyomi.presentation.core.components.material.padding
|
|
|
|
import tachiyomi.presentation.core.components.material.topSmallPaddingValues
|
2023-02-20 10:12:41 -05:00
|
|
|
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
|
2023-02-18 16:33:03 -05:00
|
|
|
import tachiyomi.presentation.core.util.plus
|
2023-03-20 08:41:44 -04:00
|
|
|
import tachiyomi.source.local.isLocal
|
2022-04-24 20:35:59 +02:00
|
|
|
|
|
|
|
@Composable
|
2022-05-15 17:03:57 -04:00
|
|
|
fun SourcesScreen(
|
2023-07-16 18:43:37 -04:00
|
|
|
state: SourcesScreenModel.State,
|
2022-10-10 02:52:56 +07:00
|
|
|
contentPadding: PaddingValues,
|
2022-12-18 03:51:03 +08:00
|
|
|
onClickItem: (Source, Listing) -> Unit,
|
2022-04-24 20:35:59 +02:00
|
|
|
onClickPin: (Source) -> Unit,
|
2022-11-24 10:28:25 +07:00
|
|
|
onLongClickItem: (Source) -> Unit,
|
2022-04-24 20:35:59 +02:00
|
|
|
) {
|
2022-07-16 20:44:37 +02:00
|
|
|
when {
|
2022-11-24 10:28:25 +07:00
|
|
|
state.isLoading -> LoadingScreen(modifier = Modifier.padding(contentPadding))
|
|
|
|
state.isEmpty -> EmptyScreen(
|
2022-10-10 02:52:56 +07:00
|
|
|
textResource = R.string.source_empty_screen,
|
|
|
|
modifier = Modifier.padding(contentPadding),
|
|
|
|
)
|
2022-07-16 20:44:37 +02:00
|
|
|
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,
|
|
|
|
)
|
|
|
|
}
|
2022-04-24 20:35:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Composable
|
2022-09-18 22:38:44 -04:00
|
|
|
private fun SourceHeader(
|
2022-04-24 20:35:59 +02:00
|
|
|
modifier: Modifier = Modifier,
|
2022-05-10 17:54:52 -04:00
|
|
|
language: String,
|
2022-04-24 20:35:59 +02:00
|
|
|
) {
|
|
|
|
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,
|
2022-04-24 20:35:59 +02:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
@Composable
|
2022-09-18 22:38:44 -04:00
|
|
|
private fun SourceItem(
|
2022-04-24 20:35:59 +02:00
|
|
|
modifier: Modifier = Modifier,
|
2022-04-27 14:36:16 +02:00
|
|
|
source: Source,
|
2022-12-18 03:51:03 +08:00
|
|
|
onClickItem: (Source, Listing) -> Unit,
|
2022-04-24 20:35:59 +02:00
|
|
|
onLongClickItem: (Source) -> Unit,
|
2022-05-10 17:54:52 -04:00
|
|
|
onClickPin: (Source) -> Unit,
|
2022-04-24 20:35:59 +02:00
|
|
|
) {
|
2022-04-27 14:36:16 +02:00
|
|
|
BaseSourceItem(
|
|
|
|
modifier = modifier,
|
|
|
|
source = source,
|
2022-12-18 03:51:03 +08:00
|
|
|
onClickItem = { onClickItem(source, Listing.Popular) },
|
2022-04-27 14:36:16 +02:00
|
|
|
onLongClickItem = { onLongClickItem(source) },
|
2022-10-04 09:05:37 +06:00
|
|
|
action = {
|
2022-04-27 14:36:16 +02:00
|
|
|
if (source.supportsLatest) {
|
2022-12-18 03:51:03 +08:00
|
|
|
TextButton(onClick = { onClickItem(source, Listing.Latest) }) {
|
2022-04-27 14:36:16 +02:00
|
|
|
Text(
|
2022-05-19 17:43:27 -04:00
|
|
|
text = stringResource(R.string.latest),
|
2022-04-27 14:36:16 +02:00
|
|
|
style = LocalTextStyle.current.copy(
|
2022-05-10 17:54:52 -04:00
|
|
|
color = MaterialTheme.colorScheme.primary,
|
|
|
|
),
|
2022-04-27 14:36:16 +02:00
|
|
|
)
|
|
|
|
}
|
2022-04-24 20:35:59 +02:00
|
|
|
}
|
2022-04-27 14:36:16 +02:00
|
|
|
SourcePinButton(
|
|
|
|
isPinned = Pin.Pinned in source.pin,
|
2022-05-10 17:54:52 -04:00
|
|
|
onClick = { onClickPin(source) },
|
2022-04-27 14:36:16 +02:00
|
|
|
)
|
|
|
|
},
|
|
|
|
)
|
2022-04-24 20:35:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Composable
|
2022-09-18 22:38:44 -04:00
|
|
|
private fun SourcePinButton(
|
2022-04-24 20:35:59 +02:00
|
|
|
isPinned: Boolean,
|
2022-05-10 17:54:52 -04:00
|
|
|
onClick: () -> Unit,
|
2022-04-24 20:35:59 +02:00
|
|
|
) {
|
|
|
|
val icon = if (isPinned) Icons.Filled.PushPin else Icons.Outlined.PushPin
|
2023-03-28 23:01:22 -04:00
|
|
|
val tint = if (isPinned) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onBackground.copy(alpha = SecondaryItemAlpha)
|
2022-10-09 15:49:32 -04:00
|
|
|
val description = if (isPinned) R.string.action_unpin else R.string.action_pin
|
2022-04-24 20:35:59 +02:00
|
|
|
IconButton(onClick = onClick) {
|
|
|
|
Icon(
|
|
|
|
imageVector = icon,
|
2022-05-10 17:54:52 -04:00
|
|
|
tint = tint,
|
2022-10-09 15:49:32 -04:00
|
|
|
contentDescription = stringResource(description),
|
2022-04-24 20:35:59 +02:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Composable
|
2022-11-24 10:28:25 +07:00
|
|
|
fun SourceOptionsDialog(
|
2022-04-24 20:35:59 +02:00
|
|
|
source: Source,
|
|
|
|
onClickPin: () -> Unit,
|
|
|
|
onClickDisable: () -> Unit,
|
|
|
|
onDismiss: () -> Unit,
|
|
|
|
) {
|
|
|
|
AlertDialog(
|
|
|
|
title = {
|
2022-07-30 19:55:07 +02:00
|
|
|
Text(text = source.visualName)
|
2022-04-24 20:35:59 +02:00
|
|
|
},
|
|
|
|
text = {
|
|
|
|
Column {
|
|
|
|
val textId = if (Pin.Pinned in source.pin) R.string.action_unpin else R.string.action_pin
|
|
|
|
Text(
|
2022-06-25 11:20:34 -04:00
|
|
|
text = stringResource(textId),
|
2022-04-24 20:35:59 +02:00
|
|
|
modifier = Modifier
|
|
|
|
.clickable(onClick = onClickPin)
|
|
|
|
.fillMaxWidth()
|
2022-05-10 17:54:52 -04:00
|
|
|
.padding(vertical = 16.dp),
|
2022-04-24 20:35:59 +02:00
|
|
|
)
|
2023-04-27 22:47:58 -04:00
|
|
|
if (!source.isLocal()) {
|
2022-04-24 20:35:59 +02:00
|
|
|
Text(
|
2022-05-19 17:43:27 -04:00
|
|
|
text = stringResource(R.string.action_disable),
|
2022-04-24 20:35:59 +02:00
|
|
|
modifier = Modifier
|
|
|
|
.clickable(onClick = onClickDisable)
|
|
|
|
.fillMaxWidth()
|
2022-05-10 17:54:52 -04:00
|
|
|
.padding(vertical = 16.dp),
|
2022-04-24 20:35:59 +02:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
onDismissRequest = onDismiss,
|
|
|
|
confirmButton = {},
|
|
|
|
)
|
|
|
|
}
|
2022-05-02 08:34:58 +06:00
|
|
|
|
2023-07-23 20:03:37 -04:00
|
|
|
sealed interface SourceUiModel {
|
|
|
|
data class Item(val source: Source) : SourceUiModel
|
|
|
|
data class Header(val language: String) : SourceUiModel
|
2022-05-02 08:34:58 +06:00
|
|
|
}
|