From 6e370a1e74411379502dae715c98ef7f7f4c3ff3 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Sat, 15 Mar 2025 13:56:54 +0530 Subject: [PATCH] Fixed: The server was not starting automatically after granting notification/storage permissions, whereas it previously started automatically with the XML-based design. * Fixed: The link was not clickable and was only displaying as plain text in the TextView. * Fixed: The TagView UI was not adjusting properly when all tags were displayed. Fixed: The TagView was not positioned at the bottom and had an unintended bottom margin. * Fixed: The fonts and sizes of the date, article size, and description were not aligned with our current XML design. * Fixed: The ZIM files list was not updating on the UI when selecting/deselecting items. * Removed the `activity_zim_host.xml` file from project since it is unused now. --- .../java/org/kiwix/kiwixmobile/ui/BookItem.kt | 43 ++++--- .../java/org/kiwix/kiwixmobile/ui/TagsView.kt | 6 +- .../kiwixmobile/webserver/ZimHostFragment.kt | 29 ++--- .../kiwixmobile/webserver/ZimHostScreen.kt | 51 +++++--- app/src/main/res/layout/activity_zim_host.xml | 113 ------------------ .../core/error/ErrorActivityScreen.kt | 3 +- .../core/ui/components/CrashCheckBox.kt | 3 +- .../kiwixmobile/core/ui/theme/Typography.kt | 8 +- .../kiwixmobile/core/utils/ComposeDimens.kt | 3 +- 9 files changed, 85 insertions(+), 174 deletions(-) delete mode 100644 app/src/main/res/layout/activity_zim_host.xml 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 e7c9843b5..f48bc720c 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/ui/BookItem.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/ui/BookItem.kt @@ -45,13 +45,12 @@ import androidx.compose.ui.text.style.TextOverflow import org.kiwix.kiwixmobile.core.R import org.kiwix.kiwixmobile.core.extensions.faviconToPainter import org.kiwix.kiwixmobile.core.ui.theme.KiwixTheme -import org.kiwix.kiwixmobile.core.utils.ComposeDimens.BOOK_DESCRIPTION_LETTER_SPACING 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.FOURTEEN_SP 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.TWO_DP import org.kiwix.kiwixmobile.core.zim_manager.KiloByte import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.ArticleCount import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.SelectionMode @@ -65,7 +64,6 @@ fun BookItem( onLongClick: ((BookOnDisk) -> Unit)? = null, onMultiSelect: ((BookOnDisk) -> Unit)? = null, selectionMode: SelectionMode = SelectionMode.NORMAL, - onCheckedChange: (Boolean) -> Unit = {} ) { KiwixTheme { Card( @@ -89,7 +87,7 @@ fun BookItem( elevation = CardDefaults.elevatedCardElevation(), colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceContainer) ) { - BookContent(bookOnDisk, selectionMode, onCheckedChange) + BookContent(bookOnDisk, selectionMode, onMultiSelect, onClick) } } } @@ -98,16 +96,17 @@ fun BookItem( private fun BookContent( bookOnDisk: BookOnDisk, selectionMode: SelectionMode, - onCheckedChange: (Boolean) -> Unit + onMultiSelect: ((BookOnDisk) -> Unit)?, + onClick: ((BookOnDisk) -> Unit)?, ) { Row( modifier = Modifier - .padding(SIXTEEN_DP) + .padding(top = SIXTEEN_DP, start = SIXTEEN_DP) .fillMaxWidth(), verticalAlignment = Alignment.CenterVertically ) { if (selectionMode == SelectionMode.MULTI) { - BookCheckbox(bookOnDisk, onCheckedChange) + BookCheckbox(bookOnDisk, selectionMode, onMultiSelect, onClick) } BookIcon(bookOnDisk.book.faviconToPainter()) BookDetails(Modifier.weight(1f), bookOnDisk) @@ -115,10 +114,20 @@ private fun BookContent( } @Composable -private fun BookCheckbox(bookOnDisk: BookOnDisk, onCheckedChange: (Boolean) -> Unit) { +private fun BookCheckbox( + bookOnDisk: BookOnDisk, + selectionMode: SelectionMode, + onMultiSelect: ((BookOnDisk) -> Unit)?, + onClick: ((BookOnDisk) -> Unit)? +) { Checkbox( checked = bookOnDisk.isSelected, - onCheckedChange = onCheckedChange + onCheckedChange = { + when (selectionMode) { + SelectionMode.MULTI -> onMultiSelect?.invoke(bookOnDisk) + SelectionMode.NORMAL -> onClick?.invoke(bookOnDisk) + } + } ) } @@ -138,38 +147,36 @@ private fun BookDetails(modifier: Modifier, bookOnDisk: BookOnDisk) { Column(modifier = modifier.padding(start = SIXTEEN_DP)) { Text( text = bookOnDisk.book.title, - style = MaterialTheme.typography.titleMedium + style = MaterialTheme.typography.titleSmall ) + Spacer(modifier = Modifier.height(TWO_DP)) Text( text = bookOnDisk.book.description.orEmpty(), - style = MaterialTheme.typography.bodySmall.copy( - fontSize = FOURTEEN_SP, - letterSpacing = BOOK_DESCRIPTION_LETTER_SPACING - ), + style = MaterialTheme.typography.bodyMedium, maxLines = 2, overflow = TextOverflow.Ellipsis, color = MaterialTheme.colorScheme.onSecondary ) Row( verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.padding(top = FOUR_DP) + modifier = Modifier.padding(top = FIVE_DP) ) { Text( text = bookOnDisk.book.date, - style = MaterialTheme.typography.bodySmall, + style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onTertiary ) Spacer(modifier = Modifier.width(EIGHT_DP)) Text( text = KiloByte(bookOnDisk.book.size).humanReadable, - style = MaterialTheme.typography.bodySmall, + style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onTertiary ) Spacer(modifier = Modifier.width(EIGHT_DP)) Text( text = ArticleCount(bookOnDisk.book.articleCount.orEmpty()) .toHumanReadable(LocalContext.current), - style = MaterialTheme.typography.bodySmall, + style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onTertiary ) } diff --git a/app/src/main/java/org/kiwix/kiwixmobile/ui/TagsView.kt b/app/src/main/java/org/kiwix/kiwixmobile/ui/TagsView.kt index 16579ebd2..bfe32400b 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/ui/TagsView.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/ui/TagsView.kt @@ -19,7 +19,8 @@ package org.kiwix.kiwixmobile.ui import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.ExperimentalLayoutApi +import androidx.compose.foundation.layout.FlowRow import androidx.compose.material3.MaterialTheme import androidx.compose.material3.SuggestionChip import androidx.compose.material3.SuggestionChipDefaults @@ -36,9 +37,10 @@ import org.kiwix.kiwixmobile.core.zim_manager.KiwixTag.Companion.YesNoValueTag.P import org.kiwix.kiwixmobile.core.zim_manager.KiwixTag.Companion.YesNoValueTag.VideoTag import org.kiwix.kiwixmobile.core.zim_manager.KiwixTag.TagValue.YES +@OptIn(ExperimentalLayoutApi::class) @Composable fun TagsView(tags: List, modifier: Modifier = Modifier) { - Row( + FlowRow( modifier = modifier, horizontalArrangement = Arrangement.spacedBy(EIGHT_DP) ) { diff --git a/app/src/main/java/org/kiwix/kiwixmobile/webserver/ZimHostFragment.kt b/app/src/main/java/org/kiwix/kiwixmobile/webserver/ZimHostFragment.kt index b3b478702..11e0cc5bc 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/webserver/ZimHostFragment.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/webserver/ZimHostFragment.kt @@ -71,7 +71,6 @@ import org.kiwix.kiwixmobile.core.utils.files.Log import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.SelectionMode import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk -import org.kiwix.kiwixmobile.databinding.ActivityZimHostBinding import org.kiwix.kiwixmobile.main.KiwixMainActivity import org.kiwix.kiwixmobile.webserver.wifi_hotspot.HotspotService import org.kiwix.kiwixmobile.webserver.wifi_hotspot.HotspotService.Companion.ACTION_CHECK_IP_ADDRESS @@ -105,7 +104,6 @@ class ZimHostFragment : BaseFragment(), ZimHostCallbacks, ZimHostContract.View { private var ip: String? = null private lateinit var serviceConnection: ServiceConnection private var dialog: Dialog? = null - private var activityZimHostBinding: ActivityZimHostBinding? = null private var isHotspotServiceRunning = false private var serverIpText = mutableStateOf("") private var shareIconItem = mutableStateOf(false to {}) @@ -140,7 +138,7 @@ class ZimHostFragment : BaseFragment(), ZimHostCallbacks, ZimHostContract.View { ActivityResultContracts.RequestPermission() ) { isGranted -> if (isGranted) { - activityZimHostBinding?.startServerButton?.performClick() + startServerButtonClick() } else { if (!ActivityCompat.shouldShowRequestPermissionRationale( requireActivity(), @@ -164,7 +162,7 @@ class ZimHostFragment : BaseFragment(), ZimHostCallbacks, ZimHostContract.View { Map.Entry::value ) if (isGranted) { - activityZimHostBinding?.startServerButton?.performClick() + startServerButtonClick() } else { if (!ActivityCompat.shouldShowRequestPermissionRationale( requireActivity(), @@ -192,7 +190,7 @@ class ZimHostFragment : BaseFragment(), ZimHostCallbacks, ZimHostContract.View { startServerButtonItem = startServerButtonItem.value, selectionMode = SelectionMode.MULTI, onMultiSelect = { select(it) }, - booksList = booksList.value, + booksList = booksList.value ) { NavigationIcon( onClick = { activity?.onBackPressedDispatcher?.onBackPressed() } @@ -207,17 +205,6 @@ class ZimHostFragment : BaseFragment(), ZimHostCallbacks, ZimHostContract.View { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - // - // bookDelegate = - // BookOnDiskDelegate.BookDelegate(sharedPreferenceUtil, multiSelectAction = ::select) - // bookDelegate.selectionMode = SelectionMode.MULTI - // booksAdapter = - // BooksOnDiskAdapter( - // bookDelegate, - // BookOnDiskDelegate.LanguageDelegate - // ) - // - // activityZimHostBinding?.recyclerViewZimHost?.adapter = booksAdapter presenter.attachView(this) serviceConnection = @@ -324,6 +311,10 @@ class ZimHostFragment : BaseFragment(), ZimHostCallbacks, ZimHostContract.View { } it } + // Force recomposition by first setting an empty list before assigning the updated list. + // This is necessary because modifying an object's property doesn't trigger recomposition, + // as Compose still considers the list unchanged. + booksList.value = emptyList() booksList.value = tempBooksList saveHostedBooks(tempBooksList) if (ServerUtils.isServerStarted) { @@ -380,10 +371,6 @@ class ZimHostFragment : BaseFragment(), ZimHostCallbacks, ZimHostContract.View { private fun layoutServerStarted() { serverIpText.value = getString(R.string.server_started_message, ip) - // activityZimHostBinding?.serverTextView?.apply { - // text = getString(R.string.server_started_message, ip) - // movementMethod = LinkMovementMethod.getInstance() - // } configureUrlSharingIcon(true) configureQrIcon(true) startServerButtonItem.value = @@ -419,10 +406,8 @@ class ZimHostFragment : BaseFragment(), ZimHostCallbacks, ZimHostContract.View { override fun onDestroyView() { super.onDestroyView() - activityZimHostBinding?.recyclerViewZimHost?.adapter = null unRegisterHotspotService() presenter.detachView() - activityZimHostBinding = null } private fun unRegisterHotspotService() { diff --git a/app/src/main/java/org/kiwix/kiwixmobile/webserver/ZimHostScreen.kt b/app/src/main/java/org/kiwix/kiwixmobile/webserver/ZimHostScreen.kt index 10b65d002..918a72bbf 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/webserver/ZimHostScreen.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/webserver/ZimHostScreen.kt @@ -18,6 +18,11 @@ package org.kiwix.kiwixmobile.webserver +import android.content.Context +import android.text.method.LinkMovementMethod +import android.text.util.Linkify +import android.view.Gravity +import android.widget.TextView import androidx.compose.foundation.Image import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box @@ -31,16 +36,17 @@ import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.material3.minimumInteractiveComponentSize import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.viewinterop.AndroidView +import androidx.core.text.util.LinkifyCompat import org.kiwix.kiwixmobile.core.R import org.kiwix.kiwixmobile.core.ui.components.KiwixAppBar import org.kiwix.kiwixmobile.core.ui.components.KiwixButton @@ -82,11 +88,18 @@ fun ZimHostScreen( modifier = Modifier.fillMaxWidth().padding(horizontal = SIXTEEN_DP), verticalAlignment = Alignment.CenterVertically ) { - ServerIpText(serverIpText, Modifier.weight(1f)) + ServerIpText(serverIpText, Modifier.weight(1f), LocalContext.current) ShareIcon(shareIconItem) } Box(modifier = Modifier.weight(1f)) { - BookItemList(booksList, selectionMode, qrImageItem, onClick, onLongClick, onMultiSelect) + BookItemList( + booksList, + selectionMode, + qrImageItem, + onClick, + onLongClick, + onMultiSelect + ) } KiwixButton( startServerButtonItem.first, @@ -99,20 +112,28 @@ fun ZimHostScreen( } } +@Suppress("MagicNumber") @Composable -fun ServerIpText( +private fun ServerIpText( serverIpText: String, - modifier: Modifier + modifier: Modifier, + context: Context ) { - Text( - text = serverIpText, - modifier = modifier.minimumInteractiveComponentSize(), - textAlign = TextAlign.Start, - ) + val serverIpTextView = remember { TextView(context) } + AndroidView(factory = { serverIpTextView }, modifier = modifier) { textView -> + textView.apply { + text = serverIpText + textSize = 14F + minHeight = context.resources.getDimensionPixelSize(R.dimen.material_minimum_height_and_width) + gravity = Gravity.CENTER or Gravity.START + LinkifyCompat.addLinks(this, Linkify.WEB_URLS) + movementMethod = LinkMovementMethod.getInstance() + } + } } @Composable -fun ShareIcon(shareIconItem: Pair Unit>) { +private fun ShareIcon(shareIconItem: Pair Unit>) { if (shareIconItem.first) { Image( painter = painterResource(id = R.drawable.ic_share_35dp), @@ -128,7 +149,7 @@ fun ShareIcon(shareIconItem: Pair Unit>) { } @Composable -fun QRImage(qrImageItem: Pair) { +private fun QRImage(qrImageItem: Pair) { if (qrImageItem.first) { Image( painter = qrImageItem.second.toPainter(), @@ -143,7 +164,7 @@ fun QRImage(qrImageItem: Pair) { } @Composable -fun BookItemList( +private fun BookItemList( booksList: List, selectionMode: SelectionMode, qrImageItem: Pair, diff --git a/app/src/main/res/layout/activity_zim_host.xml b/app/src/main/res/layout/activity_zim_host.xml deleted file mode 100644 index ef07b202b..000000000 --- a/app/src/main/res/layout/activity_zim_host.xml +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - -