Skip to content

Commit

Permalink
Add download media feature
Browse files Browse the repository at this point in the history
  • Loading branch information
HeroBrine1st committed Mar 30, 2024
1 parent 876ddb9 commit 0d171f2
Show file tree
Hide file tree
Showing 10 changed files with 119 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class ActivityInjectionCompanion(
)

val mediaModule = MediaModule(applicationContext)
val downloadManagerModule = DownloadManagerModule(applicationContext)

val databaseModule by applicationInjectionCompanion::databaseModule
val snackbarModule by applicationInjectionCompanion::snackbarModule
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* This file is part of ru.herobrine1st.e621.
*
* ru.herobrine1st.e621 is an android client for https://e621.net
* Copyright (C) 2022-2024 HeroBrine1st Erquilenne <[email protected]>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package ru.herobrine1st.e621.module

import android.app.DownloadManager
import android.content.Context
import android.net.Uri
import android.os.Environment
import ru.herobrine1st.e621.api.model.FileType
import ru.herobrine1st.e621.api.model.NormalizedFile

class DownloadManagerModule(context: Context) {
private val _downloadManager =
context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager

val downloadManager: IDownloadManager = DownloadManagerImpl(_downloadManager)

private class DownloadManagerImpl(val proxy: DownloadManager) :
IDownloadManager {
override fun downloadFile(file: NormalizedFile) {
val url = file.urls.firstNotNullOfOrNull { it }?.let { Uri.parse(it) } ?: return
val request = DownloadManager.Request(url)
request.setTitle(url.pathSegments.last())
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)

val directory = when (file.type) {
FileType.JPG, FileType.PNG, FileType.GIF -> Environment.DIRECTORY_PICTURES
FileType.WEBM -> Environment.DIRECTORY_MOVIES
FileType.SWF, FileType.UNDEFINED -> Environment.DIRECTORY_DOWNLOADS
}

request.setDestinationInExternalPublicDir(
directory,
"E621/${url.pathSegments.last()}"
)
proxy.enqueue(request)
}
}
}

interface IDownloadManager {
fun downloadFile(file: NormalizedFile)
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@ import androidx.compose.runtime.setValue
import com.arkivanov.decompose.ComponentContext
import ru.herobrine1st.e621.api.model.NormalizedFile
import ru.herobrine1st.e621.api.model.Post
import ru.herobrine1st.e621.module.IDownloadManager

class PostMediaComponent(
post: Post,
private val post: Post,
initialFile: NormalizedFile,
private val downloadManager: IDownloadManager,
componentContext: ComponentContext,
) : ComponentContext by componentContext {
val files = post.files
Expand All @@ -38,12 +40,15 @@ class PostMediaComponent(
check(initialFile in files) { "Initial file does not belong to post" }
}


var currentFile by mutableStateOf(initialFile)
private set

fun setFile(file: NormalizedFile) {
check(file in files) { "File does not belong to post" }
currentFile = file
}

fun downloadFile() {
downloadManager.downloadFile(post.normalizedFile)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import ru.herobrine1st.e621.api.model.selectSample
import ru.herobrine1st.e621.api.search.PoolSearchOptions
import ru.herobrine1st.e621.api.search.PostsSearchOptions
import ru.herobrine1st.e621.api.search.SearchOptions
import ru.herobrine1st.e621.module.IDownloadManager
import ru.herobrine1st.e621.navigation.LifecycleScope
import ru.herobrine1st.e621.navigation.component.VideoPlayerComponent
import ru.herobrine1st.e621.navigation.component.posts.handleFavouriteChange
Expand Down Expand Up @@ -86,6 +87,7 @@ class PostComponent(
private val favouritesCache: FavouritesCache,
private val snackbarAdapter: SnackbarAdapter,
private val mediaOkHttpClientProvider: Lazy<OkHttpClient>,
private val downloadManager: IDownloadManager,
) : ComponentContext by componentContext {
private val instance = instanceKeeper.getOrCreate {
Instance(postId, api, exceptionReporter)
Expand Down Expand Up @@ -329,6 +331,11 @@ class PostComponent(
)
}

fun downloadFile() {
val post = (state as? PostState.Ready) ?: return
downloadManager.downloadFile(post.post.normalizedFile)
}

class Instance(
postId: PostId,
api: API,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ class RootComponentImpl(
injectionCompanion.apiModule.api,
injectionCompanion.favouritesCache,
injectionCompanion.snackbarModule.snackbarAdapter,
injectionCompanion.mediaModule.mediaOkHttpClientLazy
injectionCompanion.mediaModule.mediaOkHttpClientLazy,
injectionCompanion.downloadManagerModule.downloadManager
)
)
is Settings -> Child.Settings(SettingsComponent(context))
Expand Down Expand Up @@ -169,6 +170,7 @@ class RootComponentImpl(
PostMediaComponent(
configuration.post,
configuration.initialFile,
injectionCompanion.downloadManagerModule.downloadManager,
context
)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ fun MenuAction(
@Composable
fun ActionBarMenu(
onNavigateToSettings: () -> Unit,
onOpenBlacklistDialog: () -> Unit
onOpenBlacklistDialog: () -> Unit,
additionalMenuActions: @Composable () -> Unit = {},
) {
var openMenu by remember { mutableStateOf(false) }

Expand All @@ -76,6 +77,7 @@ fun ActionBarMenu(
expanded = openMenu,
onDismissRequest = { openMenu = false }
) {
additionalMenuActions()
MenuAction(Icons.Outlined.Block, stringResource(R.string.blacklist)) {
openMenu = false
onOpenBlacklistDialog()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,14 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Animation
import androidx.compose.material.icons.filled.Download
import androidx.compose.material.icons.filled.Image
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.filled.Movie
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LocalContentColor
Expand All @@ -55,6 +60,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import ru.herobrine1st.e621.R
import ru.herobrine1st.e621.api.model.FileType
import ru.herobrine1st.e621.navigation.component.PostMediaComponent
import ru.herobrine1st.e621.ui.component.MAX_SCALE_DEFAULT
import ru.herobrine1st.e621.ui.component.post.PostImage
Expand Down Expand Up @@ -131,22 +137,37 @@ fun PostMediaScreen(
)
Spacer(Modifier.weight(1f))
Box {
var showVariants by remember { mutableStateOf(false) }
IconButton(onClick = { showVariants = true }) {
var showMenu by remember { mutableStateOf(false) }
IconButton(onClick = { showMenu = true }) {
Icon(
Icons.Default.MoreVert,
contentDescription = stringResource(R.string.image_fullscreen_select_image_variant)
)
}
DropdownMenu(
expanded = showVariants,
onDismissRequest = { showVariants = false }
expanded = showMenu,
onDismissRequest = { showMenu = false }
) {
DropdownMenuItem(
text = { Text(stringResource(R.string.download)) },
leadingIcon = { Icon(Icons.Default.Download, null) },
onClick = { component.downloadFile() }
)
HorizontalDivider()
component.files.forEach {
DropdownMenuItem(
text = {
Text(it.name.replaceFirstChar { it.uppercase() })
},
leadingIcon = {
val icon = when (it.type) {
FileType.JPG, FileType.PNG -> Icons.Default.Image
FileType.GIF -> Icons.Default.Animation
FileType.WEBM -> Icons.Default.Movie
FileType.SWF, FileType.UNDEFINED -> return@DropdownMenuItem
}
Icon(icon, null)
},
onClick = {
component.setFile(it)
}
Expand Down
11 changes: 10 additions & 1 deletion app/src/main/java/ru/herobrine1st/e621/ui/screen/post/Post.kt
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,14 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.NavigateNext
import androidx.compose.material.icons.filled.Download
import androidx.compose.material.icons.filled.ExpandMore
import androidx.compose.material.icons.filled.Explicit
import androidx.compose.material.icons.outlined.Error
import androidx.compose.material3.BottomSheetScaffold
import androidx.compose.material3.Button
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
Expand Down Expand Up @@ -171,7 +173,14 @@ fun Post(
actions = {
ActionBarMenu(
onNavigateToSettings = screenSharedState.goToSettings,
onOpenBlacklistDialog = screenSharedState.openBlacklistDialog
onOpenBlacklistDialog = screenSharedState.openBlacklistDialog,
additionalMenuActions = {
DropdownMenuItem(
text = { Text(stringResource(R.string.download)) },
leadingIcon = { Icon(Icons.Default.Download, null) },
onClick = { component.downloadFile() }
)
}
)
},
scrollBehavior = scrollBehavior
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values-ru-rRU/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -162,4 +162,5 @@
<string name="pool_updated_relative_date">Последнее обновление: %s</string>
<string name="pool_is_active">Эта коллекция активна</string>
<string name="pool_is_not_active">Эта коллекция не активна</string>
<string name="download">Загрузить</string>
</resources>
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -161,4 +161,5 @@ You should have received a copy of the GNU General Public License along with thi
<string name="pool_updated_relative_date">Last updated: %s</string>
<string name="pool_is_active">This pool is active</string>
<string name="pool_is_not_active">This pool is not active</string>
<string name="download">Download</string>
</resources>

0 comments on commit 0d171f2

Please sign in to comment.