Fixed: Show the downloaded size and total file size in the download notification.

* Displaying the downloaded size and total size in the download notification.
* Displaying the same information in the Download screen UI. We have moved the Download Progress text ("In Progress", "Downloading", "Paused") above the progress bar, and now show the size information in its place.
This commit is contained in:
MohitMaliFtechiz 2025-09-10 21:50:42 +05:30
parent 59030624b3
commit 0539ff4780
2 changed files with 61 additions and 11 deletions

View File

@ -54,6 +54,7 @@ import org.kiwix.kiwixmobile.core.utils.ComposeDimens.ONE_DP
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.SIXTEEN_DP import org.kiwix.kiwixmobile.core.utils.ComposeDimens.SIXTEEN_DP
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.TEN_DP import org.kiwix.kiwixmobile.core.utils.ComposeDimens.TEN_DP
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.TWO_DP import org.kiwix.kiwixmobile.core.utils.ComposeDimens.TWO_DP
import org.kiwix.kiwixmobile.core.zim_manager.Byte
import org.kiwix.kiwixmobile.ui.BookDescription import org.kiwix.kiwixmobile.ui.BookDescription
import org.kiwix.kiwixmobile.ui.BookIcon import org.kiwix.kiwixmobile.ui.BookIcon
import org.kiwix.kiwixmobile.ui.BookTitle import org.kiwix.kiwixmobile.ui.BookTitle
@ -113,6 +114,7 @@ private fun DownloadBookContent(
BookTitle(item.title) BookTitle(item.title)
Spacer(modifier = Modifier.height(TWO_DP)) Spacer(modifier = Modifier.height(TWO_DP))
BookDescription(item.description.orEmpty()) BookDescription(item.description.orEmpty())
DownloadStateText(item)
ContentLoadingProgressBar( ContentLoadingProgressBar(
progressBarStyle = ProgressBarStyle.HORIZONTAL, progressBarStyle = ProgressBarStyle.HORIZONTAL,
modifier = Modifier.padding(horizontal = ONE_DP, vertical = FIVE_DP), modifier = Modifier.padding(horizontal = ONE_DP, vertical = FIVE_DP),
@ -183,17 +185,33 @@ private fun DownloadStateRow(item: LibraryDownloadItem) {
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
Text( Text(
text = item.downloadState.toReadableState(LocalContext.current).toString(), text = item.readableEta.toString(),
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onTertiary, color = MaterialTheme.colorScheme.onTertiary,
modifier = Modifier modifier = Modifier.weight(1f)
.weight(1f)
.testTag(DOWNLOADING_STATE_TEXT_TESTING_TAG)
) )
Text( Text(
text = item.readableEta.toString(), text = getDownloadedSizeText(item.bytesDownloaded, item.totalSizeBytes),
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onTertiary color = MaterialTheme.colorScheme.onTertiary
) )
} }
} }
private fun getDownloadedSizeText(downloadedBytes: Long, totalBytes: Long): String {
if (totalBytes <= 0 || downloadedBytes <= 0) return ""
val downloadedText = Byte(downloadedBytes.toString()).humanReadable
val totalText = Byte(totalBytes.toString()).humanReadable
return "$downloadedText/$totalText"
}
@Composable
private fun DownloadStateText(item: LibraryDownloadItem) {
Text(
text = item.downloadState.toReadableState(LocalContext.current).toString(),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onTertiary,
modifier = Modifier
.testTag(DOWNLOADING_STATE_TEXT_TESTING_TAG)
)
}

View File

@ -65,6 +65,7 @@ import org.kiwix.kiwixmobile.core.Intents
import org.kiwix.kiwixmobile.core.R import org.kiwix.kiwixmobile.core.R
import org.kiwix.kiwixmobile.core.dao.DownloadRoomDao import org.kiwix.kiwixmobile.core.dao.DownloadRoomDao
import org.kiwix.kiwixmobile.core.main.CoreMainActivity import org.kiwix.kiwixmobile.core.main.CoreMainActivity
import org.kiwix.kiwixmobile.core.zim_manager.Byte
import javax.inject.Inject import javax.inject.Inject
const val DOWNLOAD_NOTIFICATION_TITLE = "OPEN_ZIM_FILE" const val DOWNLOAD_NOTIFICATION_TITLE = "OPEN_ZIM_FILE"
@ -117,13 +118,38 @@ class FetchDownloadNotificationManager @Inject constructor(
return when { return when {
downloadNotification.isCompleted -> context.getString(R.string.complete) downloadNotification.isCompleted -> context.getString(R.string.complete)
downloadNotification.isFailed -> context.getString(R.string.download_failed_state) downloadNotification.isFailed -> context.getString(R.string.download_failed_state)
downloadNotification.isPaused -> context.getString(R.string.paused_state) downloadNotification.isPaused -> buildSubtitle(
context.getString(R.string.paused_state),
downloadNotification.downloaded,
downloadNotification.total
)
downloadNotification.isQueued -> context.getString(R.string.resuming_state) downloadNotification.isQueued -> context.getString(R.string.resuming_state)
downloadNotification.etaInMilliSeconds < 0 -> context.getString(R.string.downloading_state) downloadNotification.etaInMilliSeconds < 0 -> context.getString(R.string.downloading_state)
else -> super.getSubtitleText(context, downloadNotification) else -> buildSubtitle(
super.getSubtitleText(context, downloadNotification),
downloadNotification.downloaded,
downloadNotification.total
)
} }
} }
private fun buildSubtitle(
mainText: String,
downloaded: Long,
total: Long
): String {
val sizeText = getDownloadedSizeText(downloaded, total)
return "$mainText$sizeText"
}
private fun getDownloadedSizeText(downloadedBytes: Long, totalBytes: Long): String {
if (downloadedBytes <= 0 || totalBytes <= 0) return ""
val downloadedText = Byte(downloadedBytes.toString()).humanReadable
val totalText = Byte(totalBytes.toString()).humanReadable
return "$downloadedText/$totalText"
}
@RequiresApi(Build.VERSION_CODES.O) @RequiresApi(Build.VERSION_CODES.O)
private fun createChannel(channelId: String, context: Context) = private fun createChannel(channelId: String, context: Context) =
NotificationChannel( NotificationChannel(
@ -250,12 +276,12 @@ class FetchDownloadNotificationManager @Inject constructor(
download: Download download: Download
) { ) {
val notificationBuilder = getNotificationBuilder(download.id, download.id) val notificationBuilder = getNotificationBuilder(download.id, download.id)
val cancelNotification = getCancelNotification(fetch, download, notificationBuilder) val pauseNotification = getPauseNotification(fetch, download, notificationBuilder)
downloadNotificationManager.notify(download.id, cancelNotification) downloadNotificationManager.notify(download.id, pauseNotification)
} }
@Suppress("InjectDispatcher") @Suppress("InjectDispatcher")
private fun getCancelNotification( private fun getPauseNotification(
fetch: Fetch, fetch: Fetch,
download: Download, download: Download,
notificationBuilder: Builder notificationBuilder: Builder
@ -270,7 +296,13 @@ class FetchDownloadNotificationManager @Inject constructor(
return notificationBuilder.setPriority(NotificationCompat.PRIORITY_DEFAULT) return notificationBuilder.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setSmallIcon(android.R.drawable.stat_sys_download_done) .setSmallIcon(android.R.drawable.stat_sys_download_done)
.setContentTitle(notificationTitle) .setContentTitle(notificationTitle)
.setContentText(context.getString(R.string.paused_state)) .setContentText(
buildSubtitle(
context.getString(R.string.paused_state),
download.downloaded,
download.total
)
)
// Set the ongoing true so that could not cancel the pause notification. // Set the ongoing true so that could not cancel the pause notification.
// However, on Android 14 and above user can cancel the notification by swipe right so we // However, on Android 14 and above user can cancel the notification by swipe right so we
// can't control that see https://developer.android.com/about/versions/14/behavior-changes-all#non-dismissable-notifications // can't control that see https://developer.android.com/about/versions/14/behavior-changes-all#non-dismissable-notifications