Skip to content

Commit

Permalink
Feat: Show File Size for Downloaded Episodes
Browse files Browse the repository at this point in the history
  • Loading branch information
Dark25 committed Aug 6, 2024
1 parent 3ff1354 commit 96fecbd
Show file tree
Hide file tree
Showing 11 changed files with 224 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableLongStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
Expand Down Expand Up @@ -69,13 +70,16 @@ import eu.kanade.presentation.entries.components.MissingItemCountListItem
import eu.kanade.presentation.util.formatEpisodeNumber
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.AnimeSource
import eu.kanade.tachiyomi.data.download.anime.AnimeDownloadProvider
import eu.kanade.tachiyomi.data.download.anime.model.AnimeDownload
import eu.kanade.tachiyomi.source.anime.getNameForAnimeInfo
import eu.kanade.tachiyomi.ui.browse.anime.extension.details.AnimeSourcePreferencesScreen
import eu.kanade.tachiyomi.ui.entries.anime.AnimeScreenModel
import eu.kanade.tachiyomi.ui.entries.anime.EpisodeList
import eu.kanade.tachiyomi.util.system.copyToClipboard
import kotlinx.coroutines.delay
import tachiyomi.core.common.util.lang.withIOContext
import tachiyomi.domain.entries.anime.model.Anime
import tachiyomi.domain.items.episode.model.Episode
import tachiyomi.domain.items.episode.service.missingEpisodesCount
Expand All @@ -90,6 +94,7 @@ import tachiyomi.presentation.core.components.material.Scaffold
import tachiyomi.presentation.core.i18n.stringResource
import tachiyomi.presentation.core.util.shouldExpandFAB
import tachiyomi.source.local.entries.anime.isLocal
import uy.kohesive.injekt.injectLazy
import java.time.Instant
import java.util.concurrent.TimeUnit

Expand All @@ -104,6 +109,9 @@ fun AnimeScreen(
episodeSwipeEndAction: LibraryPreferences.EpisodeSwipeAction,
showNextEpisodeAirTime: Boolean,
alwaysUseExternalPlayer: Boolean,
// AM (FILE_SIZE) -->
showFileSize: Boolean,
// <-- AM (FILE_SIZE)
onBackClicked: () -> Unit,
onEpisodeClicked: (episode: Episode, alt: Boolean) -> Unit,
onDownloadEpisode: ((List<EpisodeList.Item>, EpisodeDownloadAction) -> Unit)?,
Expand Down Expand Up @@ -169,6 +177,9 @@ fun AnimeScreen(
episodeSwipeEndAction = episodeSwipeEndAction,
showNextEpisodeAirTime = showNextEpisodeAirTime,
alwaysUseExternalPlayer = alwaysUseExternalPlayer,
// AM (FILE_SIZE) -->
showFileSize = showFileSize,
// <-- AM (FILE_SIZE)
onBackClicked = onBackClicked,
onEpisodeClicked = onEpisodeClicked,
onDownloadEpisode = onDownloadEpisode,
Expand Down Expand Up @@ -211,6 +222,9 @@ fun AnimeScreen(
episodeSwipeEndAction = episodeSwipeEndAction,
showNextEpisodeAirTime = showNextEpisodeAirTime,
alwaysUseExternalPlayer = alwaysUseExternalPlayer,
// AM (FILE_SIZE) -->
showFileSize = showFileSize,
// <-- AM (FILE_SIZE)
onBackClicked = onBackClicked,
onEpisodeClicked = onEpisodeClicked,
onDownloadEpisode = onDownloadEpisode,
Expand Down Expand Up @@ -258,6 +272,9 @@ private fun AnimeScreenSmallImpl(
episodeSwipeEndAction: LibraryPreferences.EpisodeSwipeAction,
showNextEpisodeAirTime: Boolean,
alwaysUseExternalPlayer: Boolean,
// AM (FILE_SIZE) -->
showFileSize: Boolean,
// <-- AM (FILE_SIZE)
onBackClicked: () -> Unit,
onEpisodeClicked: (Episode, Boolean) -> Unit,
onDownloadEpisode: ((List<EpisodeList.Item>, EpisodeDownloadAction) -> Unit)?,
Expand Down Expand Up @@ -532,6 +549,10 @@ private fun AnimeScreenSmallImpl(

sharedEpisodeItems(
anime = state.anime,
// AM (FILE_SIZE) -->
source = state.source,
showFileSize = showFileSize,
// <-- AM (FILE_SIZE)
episodes = listItem,
isAnyEpisodeSelected = episodes.fastAny { it.selected },
episodeSwipeStartAction = episodeSwipeStartAction,
Expand All @@ -558,6 +579,9 @@ fun AnimeScreenLargeImpl(
episodeSwipeEndAction: LibraryPreferences.EpisodeSwipeAction,
showNextEpisodeAirTime: Boolean,
alwaysUseExternalPlayer: Boolean,
// AM (FILE_SIZE) -->
showFileSize: Boolean,
// <-- AM (FILE_SIZE)
onBackClicked: () -> Unit,
onEpisodeClicked: (Episode, Boolean) -> Unit,
onDownloadEpisode: ((List<EpisodeList.Item>, EpisodeDownloadAction) -> Unit)?,
Expand Down Expand Up @@ -821,6 +845,10 @@ fun AnimeScreenLargeImpl(

sharedEpisodeItems(
anime = state.anime,
// AM (FILE_SIZE) -->
source = state.source,
showFileSize = showFileSize,
// <-- AM (FILE_SIZE)
episodes = listItem,
isAnyEpisodeSelected = episodes.fastAny { it.selected },
episodeSwipeStartAction = episodeSwipeStartAction,
Expand Down Expand Up @@ -891,6 +919,10 @@ private fun SharedAnimeBottomActionMenu(

private fun LazyListScope.sharedEpisodeItems(
anime: Anime,
// AM (FILE_SIZE) -->
source: AnimeSource,
showFileSize: Boolean,
// <-- AM (FILE_SIZE)
episodes: List<EpisodeList>,
isAnyEpisodeSelected: Boolean,
episodeSwipeStartAction: LibraryPreferences.EpisodeSwipeAction,
Expand All @@ -917,6 +949,26 @@ private fun LazyListScope.sharedEpisodeItems(
MissingItemCountListItem(count = episodeItem.count)
}
is EpisodeList.Item -> {
// AM (FILE_SIZE) -->
var fileSizeAsync: Long? by remember { mutableStateOf(episodeItem.fileSize) }
val isEpisodeDownloaded = episodeItem.downloadState == AnimeDownload.State.DOWNLOADED
if (isEpisodeDownloaded && showFileSize && fileSizeAsync == null) {
LaunchedEffect(episodeItem, Unit) {
fileSizeAsync = withIOContext {
animeDownloadProvider.getEpisodeFileSize(
episodeItem.episode.name,
episodeItem.episode.url,
episodeItem.episode.scanlator,
// AM (CUSTOM_INFORMATION) -->
anime.ogTitle,
// <-- AM (CUSTOM_INFORMATION)
source,
)
}
episodeItem.fileSize = fileSizeAsync
}
}
// <-- AM (FILE_SIZE)
AnimeEpisodeListItem(
title = if (anime.displayMode == Anime.EPISODE_DISPLAY_NUMBER) {
stringResource(
Expand Down Expand Up @@ -965,6 +1017,9 @@ private fun LazyListScope.sharedEpisodeItems(
onEpisodeSwipe = {
onEpisodeSwipe(episodeItem, it)
},
// AM (FILE_SIZE) -->
fileSize = fileSizeAsync,
// <-- AM (FILE_SIZE)
)
}
}
Expand Down Expand Up @@ -1014,3 +1069,6 @@ private fun formatTime(milliseconds: Long, useDayFormat: Boolean = false): Strin
)
}
}
// AM (FILE_SIZE) -->
private val animeDownloadProvider: AnimeDownloadProvider by injectLazy()
// <-- AM (FILE_SIZE)
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ fun AnimeEpisodeListItem(
onClick: () -> Unit,
onDownloadClick: ((EpisodeDownloadAction) -> Unit)?,
onEpisodeSwipe: (LibraryPreferences.EpisodeSwipeAction) -> Unit,
// AM (FILE_SIZE) -->
fileSize: Long?,
// <-- AM (FILE_SIZE)
modifier: Modifier = Modifier,
) {
val start = getSwipeAction(
Expand Down Expand Up @@ -181,6 +184,9 @@ fun AnimeEpisodeListItem(
downloadStateProvider = downloadStateProvider,
downloadProgressProvider = downloadProgressProvider,
onClick = { onDownloadClick?.invoke(it) },
// AM (FILE_SIZE) -->
fileSize = fileSize,
// <-- AM (FILE_SIZE)
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package eu.kanade.presentation.entries.anime.components

import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.CheckCircle
Expand All @@ -25,6 +26,7 @@ import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import eu.kanade.presentation.components.ArrowModifier
import eu.kanade.presentation.components.DropdownMenu
import eu.kanade.presentation.components.IndicatorModifier
Expand Down Expand Up @@ -52,6 +54,9 @@ fun EpisodeDownloadIndicator(
downloadStateProvider: () -> AnimeDownload.State,
downloadProgressProvider: () -> Int,
onClick: (EpisodeDownloadAction) -> Unit,
// AM (FILE_SIZE) -->
fileSize: Long?,
// <-- AM (FILE_SIZE)
modifier: Modifier = Modifier,
) {
when (val downloadState = downloadStateProvider()) {
Expand All @@ -66,10 +71,16 @@ fun EpisodeDownloadIndicator(
downloadState = downloadState,
downloadProgressProvider = downloadProgressProvider,
onClick = onClick,
// AM (FILE_SIZE) -->
fileSize = fileSize,
// <-- AM (FILE_SIZE)
)
AnimeDownload.State.DOWNLOADED -> DownloadedIndicator(
enabled = enabled,
modifier = modifier,
// AM (FILE_SIZE) -->
fileSize = fileSize,
// <-- AM (FILE_SIZE)
onClick = onClick,
)
AnimeDownload.State.ERROR -> ErrorIndicator(
Expand Down Expand Up @@ -113,6 +124,9 @@ private fun DownloadingIndicator(
downloadState: AnimeDownload.State,
downloadProgressProvider: () -> Int,
onClick: (EpisodeDownloadAction) -> Unit,
// AM (FILE_SIZE) -->
fileSize: Long?,
// <-- AM (FILE_SIZE)
modifier: Modifier = Modifier,
) {
var isMenuExpanded by remember { mutableStateOf(false) }
Expand Down Expand Up @@ -192,8 +206,24 @@ private fun DownloadedIndicator(
enabled: Boolean,
modifier: Modifier = Modifier,
onClick: (EpisodeDownloadAction) -> Unit,
// AM (FILE_SIZE) -->
fileSize: Long?,
// <-- AM (FILE_SIZE)
) {
var isMenuExpanded by remember { mutableStateOf(false) }

// AM (FILE_SIZE) -->
if (fileSize != null) {
Text(
text = "${fileSize / 1024 / 1024}MB",
maxLines = 1,
style = MaterialTheme.typography.bodyMedium
.copy(color = MaterialTheme.colorScheme.primary, fontSize = 12.sp),
modifier = Modifier.padding(all = 10.dp),
)
}
// <-- AM (FILE_SIZE)

Box(
modifier = modifier
.size(IconButtonTokens.StateLayerSize)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import androidx.compose.material3.SegmentedButtonDefaults
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
Expand Down Expand Up @@ -52,6 +53,7 @@ import eu.kanade.presentation.util.relativeTimeSpanString
import eu.kanade.tachiyomi.data.backup.create.BackupCreateJob
import eu.kanade.tachiyomi.data.backup.restore.BackupRestoreJob
import eu.kanade.tachiyomi.data.cache.ChapterCache
import eu.kanade.tachiyomi.data.download.anime.AnimeDownloadCache
import eu.kanade.tachiyomi.data.sync.SyncDataJob
import eu.kanade.tachiyomi.data.sync.SyncManager
import eu.kanade.tachiyomi.data.sync.service.GoogleDriveService
Expand All @@ -61,6 +63,8 @@ import eu.kanade.tachiyomi.util.system.DeviceUtil
import eu.kanade.tachiyomi.util.system.toast
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.persistentMapOf
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.launch
import logcat.LogPriority
import tachiyomi.core.common.i18n.stringResource
Expand All @@ -77,6 +81,7 @@ import tachiyomi.presentation.core.util.collectAsState
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get


@Suppress("TooManyFunctions")
object SettingsDataScreen : SearchableSettings {

Expand Down Expand Up @@ -109,9 +114,10 @@ object SettingsDataScreen : SearchableSettings {
return persistentListOf(
getStorageLocationPref(storagePreferences = storagePreferences),
Preference.PreferenceItem.InfoPreference(stringResource(MR.strings.pref_storage_location_info)),

getBackupAndRestoreGroup(backupPreferences = backupPreferences),
getDataGroup(),
// AM (FILE_SIZE) -->
getDataGroup(storagePreferences = storagePreferences),
// <-- AM (FILE_SIZE)
) + getSyncPreferences(syncPreferences = syncPreferences, syncService = syncService)
}

Expand Down Expand Up @@ -188,7 +194,6 @@ object SettingsDataScreen : SearchableSettings {
private fun getBackupAndRestoreGroup(backupPreferences: BackupPreferences): Preference.PreferenceGroup {
val context = LocalContext.current
val navigator = LocalNavigator.currentOrThrow

val lastAutoBackup by backupPreferences.lastAutoBackupTimestamp().collectAsState()

val chooseBackup = rememberLauncherForActivityResult(
Expand Down Expand Up @@ -280,7 +285,7 @@ object SettingsDataScreen : SearchableSettings {
}

@Composable
private fun getDataGroup(): Preference.PreferenceGroup {
private fun getDataGroup(storagePreferences: StoragePreferences): Preference.PreferenceGroup {
val context = LocalContext.current
val navigator = LocalNavigator.currentOrThrow
val scope = rememberCoroutineScope()
Expand All @@ -290,6 +295,18 @@ object SettingsDataScreen : SearchableSettings {
var cacheReadableSizeSema by remember { mutableIntStateOf(0) }
val cacheReadableSize = remember(cacheReadableSizeSema) { chapterCache.readableSize }

// AM (FILE_SIZE) -->
LaunchedEffect(Unit) {
storagePreferences.showEpisodeFileSize().changes()
.drop(1)
.collectLatest { value ->
if (value) {
Injekt.get<AnimeDownloadCache>().invalidateCache()
}
}
}
// <-- AM (FILE_SIZE)

return Preference.PreferenceGroup(
title = stringResource(MR.strings.pref_storage_usage),
preferenceItems = persistentListOf(
Expand All @@ -306,6 +323,13 @@ object SettingsDataScreen : SearchableSettings {
)
},

// AM (FILE_SIZE) -->
Preference.PreferenceItem.SwitchPreference(
pref = storagePreferences.showEpisodeFileSize(),
title = stringResource(MR.strings.pref_show_downloaded_episode_file_size),
),
// <-- AM (FILE_SIZE)

Preference.PreferenceItem.TextPreference(
title = stringResource(MR.strings.label_storage),
icon = Icons.Outlined.Storage,
Expand Down
Loading

0 comments on commit 96fecbd

Please sign in to comment.