ReaderScreen saveImage

This commit is contained in:
GG Bond authored and renovate[bot] committed 2024-03-04 12:21:02 +08:00
1 parent 38651eba1d
commit 28160608ec
2 files changed
+61 -2

No files matched your search

@@ -1,9 +1,13 @@
package com.hippo.ehviewer.ui.reader
import android.Manifest
import android.content.ClipData
import android.content.ContentValues
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Environment
import android.provider.MediaStore
import android.webkit.MimeTypeMap
import androidx.compose.material3.SnackbarHostState
import androidx.core.content.FileProvider
@@ -14,10 +18,14 @@ import com.hippo.ehviewer.client.data.GalleryInfo
import com.hippo.ehviewer.gallery.PageLoader2
import com.hippo.ehviewer.util.AppConfig
import com.hippo.ehviewer.util.FileUtils
import com.hippo.ehviewer.util.isAtLeastQ
import com.hippo.ehviewer.util.isAtLeastT
import com.hippo.ehviewer.util.requestPermission
import com.hippo.unifile.asUniFile
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
import eu.kanade.tachiyomi.util.system.logcat
import java.io.File
import kotlinx.datetime.Clock
import splitties.systemservices.clipboardManager
context(PageLoader2)
@@ -67,3 +75,53 @@ suspend fun copy(page: ReaderPage) {
showSnackbar(copied)
}
}
context(SnackbarHostState, Context, PageLoader2)
suspend fun save(page: ReaderPage) {
val granted = isAtLeastQ || requestPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
val cannotSave = getString(R.string.error_cant_save_image)
if (granted) {
val filename = getImageFilename(page.index)
val extension = FileUtils.getExtensionFromFilename(filename)
val mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension) ?: "image/jpeg"
val values = ContentValues()
val realPath: String
values.put(MediaStore.MediaColumns.DISPLAY_NAME, filename)
values.put(MediaStore.Images.Media.DATE_ADDED, Clock.System.now().toEpochMilliseconds())
values.put(MediaStore.MediaColumns.MIME_TYPE, mimeType)
if (isAtLeastQ) {
realPath = Environment.DIRECTORY_PICTURES + File.separator + AppConfig.APP_DIRNAME
values.put(MediaStore.MediaColumns.RELATIVE_PATH, realPath)
values.put(MediaStore.MediaColumns.IS_PENDING, 1)
} else {
val dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
val path = File(dir, AppConfig.APP_DIRNAME)
realPath = path.toString()
if (!FileUtils.ensureDirectory(path)) {
showSnackbar(cannotSave)
return
}
values.put(MediaStore.MediaColumns.DATA, realPath + File.separator + filename)
}
val imageUri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
if (imageUri != null) {
if (!save(page.index, imageUri.asUniFile())) {
try {
contentResolver.delete(imageUri, null, null)
} catch (e: Exception) {
e.logcat(e)
}
showSnackbar(cannotSave)
} else if (isAtLeastQ) {
val contentValues = ContentValues()
contentValues.put(MediaStore.MediaColumns.IS_PENDING, 0)
contentResolver.update(imageUri, contentValues, null, null)
}
showSnackbar(getString(R.string.image_saved, realPath + File.separator + filename))
} else {
showSnackbar(cannotSave)
}
} else {
showSnackbar(getString(R.string.permission_denied))
}
}
@@ -39,6 +39,7 @@ import eu.kanade.tachiyomi.ui.reader.ReaderAppBars
import eu.kanade.tachiyomi.ui.reader.ReaderPageSheetMeta
import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
import eu.kanade.tachiyomi.util.lang.launchIO
import kotlin.coroutines.resume
import kotlinx.coroutines.launch
@Destination
@@ -103,7 +104,7 @@ fun ReaderScreen(info: BaseGalleryInfo, page: Int = -1, navigator: DestinationsN
onSelectPage = { page ->
launch {
dialog { cont ->
fun dispose() = cont.cancel()
fun dispose() = cont.resume(Unit)
val state = rememberModalBottomSheetState()
ModalBottomSheet(
onDismissRequest = { dispose() },
@@ -115,7 +116,7 @@ fun ReaderScreen(info: BaseGalleryInfo, page: Int = -1, navigator: DestinationsN
retryOrigin = { pageLoader.retryPage(page.index, true) },
share = { launchIO { with(pageLoader) { shareImage(page, info) } } },
copy = { launchIO { with(pageLoader) { copy(page) } } },
save = {},
save = { launchIO { with(pageLoader) { save(page) } } },
saveTo = {},
dismiss = { launch { state.hide().also { dispose() } } },
)