diff --git a/app/src/main/java/org/kiwix/kiwixmobile/ui/BookItem.kt b/app/src/main/java/org/kiwix/kiwixmobile/ui/BookItem.kt index 4477afd30..4816ae36b 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/ui/BookItem.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/ui/BookItem.kt @@ -18,7 +18,8 @@ package org.kiwix.kiwixmobile.ui -import androidx.compose.foundation.clickable +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -36,97 +37,129 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.dimensionResource +import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp import org.kiwix.kiwixmobile.core.R import org.kiwix.kiwixmobile.core.extensions.faviconToPainter +import org.kiwix.kiwixmobile.core.utils.ComposeDimens.BOOK_ICON_SIZE +import org.kiwix.kiwixmobile.core.utils.ComposeDimens.EIGHT_DP +import org.kiwix.kiwixmobile.core.utils.ComposeDimens.FIVE_DP +import org.kiwix.kiwixmobile.core.utils.ComposeDimens.FOUR_DP +import org.kiwix.kiwixmobile.core.utils.ComposeDimens.SIXTEEN_DP +import org.kiwix.kiwixmobile.core.utils.ComposeDimens.TEN_DP import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.SelectionMode import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk -@Suppress("UnusedParameter", "LongMethod", "ComposableLambdaParameterNaming") +@OptIn(ExperimentalFoundationApi::class) @Composable fun BookItem( bookOnDisk: BookOnDisk, - onClick: (BookOnDisk) -> Unit, - onLongClick: (BookOnDisk) -> Unit, - onMultiSelect: (BookOnDisk) -> Unit, - selectionMode: SelectionMode, - isCheckboxVisible: Boolean = false, - isChecked: Boolean = false, - onCheckedChange: (Boolean) -> Unit = {}, - tags: @Composable () -> Unit = {} + onClick: ((BookOnDisk) -> Unit)? = null, + onLongClick: ((BookOnDisk) -> Unit)? = null, + onMultiSelect: ((BookOnDisk) -> Unit)? = null, + selectionMode: SelectionMode = SelectionMode.NORMAL, + onCheckedChange: (Boolean) -> Unit = {} ) { Card( modifier = Modifier .fillMaxWidth() - .padding(dimensionResource(id = R.dimen.card_margin)) - .clickable { onClick(bookOnDisk) }, + .padding(FIVE_DP) + .combinedClickable( + onClick = { + when (selectionMode) { + SelectionMode.MULTI -> onMultiSelect?.invoke(bookOnDisk) + SelectionMode.NORMAL -> onClick?.invoke(bookOnDisk) + } + }, + onLongClick = { + if (selectionMode == SelectionMode.NORMAL) { + onLongClick?.invoke(bookOnDisk) + } + } + ), shape = MaterialTheme.shapes.medium, elevation = CardDefaults.elevatedCardElevation() ) { - Row( - modifier = Modifier - .padding(dimensionResource(id = R.dimen.activity_horizontal_margin)) - .fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically - ) { - if (isCheckboxVisible) { - Checkbox( - checked = isChecked, - onCheckedChange = onCheckedChange, - modifier = Modifier.padding(end = 10.dp) - ) - } - - Icon( - painter = bookOnDisk.book.faviconToPainter(), - contentDescription = stringResource(R.string.fav_icon), - modifier = Modifier - .size(40.dp) - .padding(end = 10.dp) - ) - - Column( - modifier = Modifier.weight(1f) - ) { - Text( - text = bookOnDisk.book.title, - style = MaterialTheme.typography.titleMedium - ) - Text( - text = bookOnDisk.book.description.orEmpty(), - style = MaterialTheme.typography.bodyMedium, - maxLines = 2, - overflow = TextOverflow.Ellipsis, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.padding(top = 4.dp) - ) { - Text( - text = bookOnDisk.book.date, - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - Spacer(modifier = Modifier.width(8.dp)) - Text( - text = bookOnDisk.book.size, - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - Spacer(modifier = Modifier.width(8.dp)) - Text( - text = bookOnDisk.book.articleCount.orEmpty(), - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - } - Spacer(modifier = Modifier.height(4.dp)) - tags() - } - } + BookContent(bookOnDisk, selectionMode, onCheckedChange) + } +} + +@Composable +private fun BookContent( + bookOnDisk: BookOnDisk, + selectionMode: SelectionMode, + onCheckedChange: (Boolean) -> Unit +) { + Row( + modifier = Modifier.padding(SIXTEEN_DP).fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically + ) { + if (selectionMode == SelectionMode.MULTI) { + BookCheckbox(bookOnDisk, onCheckedChange) + } + BookIcon(bookOnDisk.book.faviconToPainter()) + BookDetails(Modifier.weight(1f), bookOnDisk) + } +} + +@Composable +private fun BookCheckbox(bookOnDisk: BookOnDisk, onCheckedChange: (Boolean) -> Unit) { + Checkbox( + checked = bookOnDisk.isSelected, + onCheckedChange = onCheckedChange, + modifier = Modifier.padding(end = TEN_DP) + ) +} + +@Composable +fun BookIcon(painter: Painter) { + Icon( + painter = painter, + contentDescription = stringResource(R.string.fav_icon), + modifier = Modifier + .size(BOOK_ICON_SIZE) + .padding(end = TEN_DP) + ) +} + +@Composable +private fun BookDetails(modifier: Modifier, bookOnDisk: BookOnDisk) { + Column(modifier = modifier) { + Text( + text = bookOnDisk.book.title, + style = MaterialTheme.typography.titleMedium + ) + Text( + text = bookOnDisk.book.description.orEmpty(), + style = MaterialTheme.typography.bodyMedium, + maxLines = 2, + overflow = TextOverflow.Ellipsis, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.padding(top = FOUR_DP) + ) { + Text( + text = bookOnDisk.book.date, + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + Spacer(modifier = Modifier.width(EIGHT_DP)) + Text( + text = bookOnDisk.book.size, + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + Spacer(modifier = Modifier.width(EIGHT_DP)) + Text( + text = bookOnDisk.book.articleCount.orEmpty(), + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + Spacer(modifier = Modifier.height(FOUR_DP)) + TagsView(bookOnDisk.tags) } } diff --git a/app/src/main/java/org/kiwix/kiwixmobile/ui/LanguageHeader.kt b/app/src/main/java/org/kiwix/kiwixmobile/ui/ZimFilesLanguageHeader.kt similarity index 89% rename from app/src/main/java/org/kiwix/kiwixmobile/ui/LanguageHeader.kt rename to app/src/main/java/org/kiwix/kiwixmobile/ui/ZimFilesLanguageHeader.kt index b08a07b08..e84733fd5 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/ui/LanguageHeader.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/ui/ZimFilesLanguageHeader.kt @@ -24,16 +24,16 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp +import org.kiwix.kiwixmobile.core.utils.ComposeDimens.EIGHT_DP import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.LanguageItem @Composable -fun LanguageHeader(languageItem: LanguageItem) { +fun ZimFilesLanguageHeader(languageItem: LanguageItem) { Text( text = languageItem.text, style = MaterialTheme.typography.titleMedium, modifier = Modifier .fillMaxWidth() - .padding(vertical = 8.dp) + .padding(vertical = EIGHT_DP) ) } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/qr/GenerateQR.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/qr/GenerateQR.kt index 5ec76cd1c..a64d7493f 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/qr/GenerateQR.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/qr/GenerateQR.kt @@ -24,6 +24,8 @@ import com.google.zxing.BarcodeFormat import com.google.zxing.EncodeHintType import com.google.zxing.qrcode.QRCodeWriter import javax.inject.Inject +import androidx.core.graphics.createBitmap +import androidx.core.graphics.set /** * Utility class to generate QR codes. @@ -47,10 +49,10 @@ class GenerateQR @Inject constructor() { it[EncodeHintType.MARGIN] = 1 } val bits = QRCodeWriter().encode(code, BarcodeFormat.QR_CODE, size, size, hints) - return Bitmap.createBitmap(size, size, Bitmap.Config.RGB_565).also { + return createBitmap(size, size, Bitmap.Config.RGB_565).also { for (x in 0 until size) { for (y in 0 until size) { - it.setPixel(x, y, if (bits[x, y]) foregroundColor else backgroundColor) + it[x, y] = if (bits[x, y]) foregroundColor else backgroundColor } } } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/utils/ComposeDimens.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/utils/ComposeDimens.kt index 1175e5b3c..8b58540ba 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/utils/ComposeDimens.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/utils/ComposeDimens.kt @@ -90,4 +90,7 @@ object ComposeDimens { val MINIMUM_HEIGHT_OF_QR_CODE = 76.dp val MAXIMUM_HEIGHT_OF_QR_CODE = 128.dp val MINIMUM_HEIGHT_OF_BOOKS_LIST = 256.dp + + // BookItem dimes + val BOOK_ICON_SIZE = 40.dp }