Share logic for saving page/cover (#6787)

* Use MediaStore on newer Android Q or newer

* Use flow instead of Observable

* Review comment fixes

* Use suspended function instead of flow
This commit is contained in:
Andreas
2022-03-19 21:46:23 +01:00
committed by GitHub
parent ddb856edc7
commit 1163aa4e4e
10 changed files with 265 additions and 143 deletions
@@ -44,6 +44,8 @@ import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.download.DownloadService
import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.saver.Image
import eu.kanade.tachiyomi.data.saver.Location
import eu.kanade.tachiyomi.data.track.EnhancedTrackService
import eu.kanade.tachiyomi.data.track.TrackService
import eu.kanade.tachiyomi.data.track.model.TrackSearch
@@ -85,7 +87,7 @@ import eu.kanade.tachiyomi.ui.webview.WebViewActivity
import eu.kanade.tachiyomi.util.chapter.NoChaptersException
import eu.kanade.tachiyomi.util.hasCustomCover
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.storage.getUriCompat
import eu.kanade.tachiyomi.util.lang.launchUI
import eu.kanade.tachiyomi.util.system.logcat
import eu.kanade.tachiyomi.util.system.toShareIntent
import eu.kanade.tachiyomi.util.system.toast
@@ -775,26 +777,47 @@ class MangaController :
fun shareCover() {
try {
val manga = manga!!
val activity = activity!!
useCoverAsBitmap(activity) { coverBitmap ->
val cover = presenter.shareCover(activity, coverBitmap)
val uri = cover.getUriCompat(activity)
startActivity(uri.toShareIntent(activity))
viewScope.launchIO {
val uri = presenter.saveImage(
image = Image.Cover(
bitmap = coverBitmap,
name = manga.title,
location = Location.Cache
)
)
launchUI {
startActivity(uri.toShareIntent(activity))
}
}
}
} catch (e: Exception) {
} catch (e: Throwable) {
logcat(LogPriority.ERROR, e)
activity?.toast(R.string.error_sharing_cover)
activity?.toast(R.string.error_saving_cover)
}
}
fun saveCover() {
try {
val manga = manga!!
val activity = activity!!
useCoverAsBitmap(activity) { coverBitmap ->
presenter.saveCover(activity, coverBitmap)
activity.toast(R.string.cover_saved)
viewScope.launchIO {
presenter.saveImage(
image = Image.Cover(
bitmap = coverBitmap,
name = manga.title,
location = Location.Pictures.create()
)
)
launchUI {
activity.toast(R.string.cover_saved)
}
}
}
} catch (e: Exception) {
} catch (e: Throwable) {
logcat(LogPriority.ERROR, e)
activity?.toast(R.string.error_saving_cover)
}
@@ -19,6 +19,8 @@ import eu.kanade.tachiyomi.data.database.models.toMangaInfo
import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.saver.Image
import eu.kanade.tachiyomi.data.saver.ImageSaver
import eu.kanade.tachiyomi.data.track.EnhancedTrackService
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.data.track.TrackService
@@ -39,10 +41,6 @@ import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.prepUpdateCover
import eu.kanade.tachiyomi.util.removeCovers
import eu.kanade.tachiyomi.util.shouldDownloadNewChapters
import eu.kanade.tachiyomi.util.storage.DiskUtil
import eu.kanade.tachiyomi.util.storage.getPicturesDir
import eu.kanade.tachiyomi.util.storage.getTempShareDir
import eu.kanade.tachiyomi.util.system.ImageUtil
import eu.kanade.tachiyomi.util.system.logcat
import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.updateCoverLastModified
@@ -58,7 +56,7 @@ import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.File
import uy.kohesive.injekt.injectLazy
import java.util.Date
class MangaPresenter(
@@ -110,6 +108,8 @@ class MangaPresenter(
private val loggedServices by lazy { trackManager.services.filter { it.isLogged } }
private val imageSaver: ImageSaver by injectLazy()
private var trackSubscription: Subscription? = null
private var searchTrackerJob: Job? = null
private var refreshTrackersJob: Job? = null
@@ -338,44 +338,13 @@ class MangaPresenter(
}
/**
* Save manga cover Bitmap to temporary share directory.
* Save manga cover Bitmap to picture or temporary share directory.
*
* @param context for the temporary share directory
* @param coverBitmap the cover to save (as Bitmap)
* @return cover File in temporary share directory
* @param image the image with specified location
* @return flow Flow which emits the Uri which specifies where the image is saved when
*/
fun shareCover(context: Context, coverBitmap: Bitmap): File {
return saveCover(getTempShareDir(context), coverBitmap)
}
/**
* Save manga cover to pictures directory of the device.
*
* @param context for the pictures directory of the user
* @param coverBitmap the cover to save (as Bitmap)
* @return cover File in pictures directory
*/
fun saveCover(context: Context, coverBitmap: Bitmap) {
saveCover(getPicturesDir(context), coverBitmap)
}
/**
* Save a manga cover Bitmap to a new File in a given directory.
* Overwrites file if it already exists.
*
* @param directory The directory in which the new file will be created
* @param coverBitmap The manga cover to save
* @return the newly created File
*/
private fun saveCover(directory: File, coverBitmap: Bitmap): File {
directory.mkdirs()
val filename = DiskUtil.buildValidFilename("${manga.title}.${ImageUtil.ImageType.PNG}")
val destFile = File(directory, filename)
destFile.outputStream().use { desFileOutputStream ->
coverBitmap.compress(Bitmap.CompressFormat.PNG, 100, desFileOutputStream)
}
return destFile
suspend fun saveImage(image: Image): Uri {
return imageSaver.save(image)
}
/**