Added option to download page or set page as cover

This commit is contained in:
Bram van de Kerkhof
2016-09-27 00:15:21 +02:00
parent 5b1f4f189b
commit 2991906a85
10 changed files with 367 additions and 14 deletions

View File

@@ -184,10 +184,9 @@ class MangaInfoFragment : BaseRxFragment<MangaInfoPresenter>() {
val url = source.mangaDetailsRequest(presenter.manga).url().toString()
val sharingIntent = Intent(Intent.ACTION_SEND).apply {
type = "text/plain"
putExtra(android.content.Intent.EXTRA_SUBJECT, presenter.manga.title)
putExtra(android.content.Intent.EXTRA_TEXT, resources.getString(R.string.share_text, presenter.manga.title, url))
}
startActivity(Intent.createChooser(sharingIntent, resources.getText(R.string.share_subject)))
startActivity(Intent.createChooser(sharingIntent, resources.getText(R.string.action_share)))
} catch (e: Exception) {
context.toast(e.message)
}

View File

@@ -145,6 +145,8 @@ class ReaderActivity : BaseRxActivity<ReaderPresenter>() {
when (item.itemId) {
R.id.action_settings -> ReaderSettingsDialog().show(supportFragmentManager, "settings")
R.id.action_custom_filter -> ReaderCustomFilterDialog().show(supportFragmentManager, "filter")
R.id.action_save_page -> presenter.savePage()
R.id.action_set_as_cover -> presenter.setCover()
else -> return super.onOptionsItemSelected(item)
}
return true
@@ -393,16 +395,16 @@ class ReaderActivity : BaseRxActivity<ReaderPresenter>() {
private fun setRotation(rotation: Int) {
when (rotation) {
// Rotation free
// Rotation free
1 -> requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
// Lock in current rotation
// Lock in current rotation
2 -> {
val currentOrientation = resources.configuration.orientation
setRotation(if (currentOrientation == Configuration.ORIENTATION_PORTRAIT) 3 else 4)
}
// Lock in portrait
// Lock in portrait
3 -> requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
// Lock in landscape
// Lock in landscape
4 -> requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
}
}

View File

@@ -1,15 +1,23 @@
package eu.kanade.tachiyomi.ui.reader
import android.os.Bundle
import android.os.Environment
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.cache.ChapterCache
import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.History
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.MangaSync
import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.download.ImageNotifier
import eu.kanade.tachiyomi.data.mangasync.MangaSyncManager
import eu.kanade.tachiyomi.data.mangasync.UpdateMangaSyncService
import eu.kanade.tachiyomi.data.network.GET
import eu.kanade.tachiyomi.data.network.NetworkHelper
import eu.kanade.tachiyomi.data.network.ProgressListener
import eu.kanade.tachiyomi.data.network.newCallWithProgress
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.source.SourceManager
import eu.kanade.tachiyomi.data.source.model.Page
@@ -17,6 +25,8 @@ import eu.kanade.tachiyomi.data.source.online.OnlineSource
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.util.RetryWithDelay
import eu.kanade.tachiyomi.util.SharedData
import eu.kanade.tachiyomi.util.saveTo
import eu.kanade.tachiyomi.util.toast
import rx.Observable
import rx.Subscription
import rx.android.schedulers.AndroidSchedulers
@@ -24,6 +34,8 @@ import rx.schedulers.Schedulers
import timber.log.Timber
import uy.kohesive.injekt.injectLazy
import java.io.File
import java.io.IOException
import java.io.InputStream
import java.util.*
/**
@@ -31,6 +43,11 @@ import java.util.*
*/
class ReaderPresenter : BasePresenter<ReaderActivity>() {
/**
* Network helper
*/
private val network: NetworkHelper by injectLazy()
/**
* Preferences.
*/
@@ -61,6 +78,11 @@ class ReaderPresenter : BasePresenter<ReaderActivity>() {
*/
val chapterCache: ChapterCache by injectLazy()
/**
* Cover cache.
*/
val coverCache: CoverCache by injectLazy()
/**
* Manga being read.
*/
@@ -88,6 +110,20 @@ class ReaderPresenter : BasePresenter<ReaderActivity>() {
*/
private val source by lazy { sourceManager.get(manga.source)!! }
/**
*
*/
val imageNotifier by lazy { ImageNotifier(context) }
/**
* Directory of pictures
*/
private val pictureDirectory: String by lazy {
Environment.getExternalStorageDirectory().absolutePath + File.separator +
Environment.DIRECTORY_PICTURES + File.separator +
context.getString(R.string.app_name) + File.separator
}
/**
* Chapter list for the active manga. It's retrieved lazily and should be accessed for the first
* time in a background thread to avoid blocking the UI.
@@ -365,7 +401,9 @@ class ReaderPresenter : BasePresenter<ReaderActivity>() {
val removeAfterReadSlots = prefs.removeAfterReadSlots()
when (removeAfterReadSlots) {
// Setting disabled
-1 -> { /**Empty function**/ }
-1 -> {
/**Empty function**/
}
// Remove current read chapter
0 -> deleteChapter(chapter, manga)
// Remove previous chapter specified by user in settings.
@@ -384,8 +422,8 @@ class ReaderPresenter : BasePresenter<ReaderActivity>() {
Timber.e(error)
}
}
.subscribeOn(Schedulers.io())
.subscribe()
.subscribeOn(Schedulers.io())
.subscribe()
}
/**
@@ -508,4 +546,87 @@ class ReaderPresenter : BasePresenter<ReaderActivity>() {
db.insertManga(manga).executeAsBlocking()
}
/**
* Update cover with page file.
*/
internal fun setCover() {
chapter.pages?.get(chapter.last_page_read)?.let {
// Update cover to selected file, show error if something went wrong
try {
if (editCoverWithStream(File(it.imagePath).inputStream(), manga)) {
context.toast(R.string.cover_updated)
} else {
throw Exception("Stream copy failed")
}
} catch(e: Exception) {
context.toast(R.string.notification_manga_update_failed)
Timber.e(e.message)
}
}
}
/**
* Called to copy image to cache
* @param inputStream the new cover.
* @param manga the manga edited.
* @return true if the cover is updated, false otherwise
*/
@Throws(IOException::class)
private fun editCoverWithStream(inputStream: InputStream, manga: Manga): Boolean {
if (manga.thumbnail_url != null && manga.favorite) {
coverCache.copyToCache(manga.thumbnail_url!!, inputStream)
return true
}
return false
}
/**
* Save page to local storage
* @throws IOException
*/
@Throws(IOException::class)
internal fun savePage() {
chapter.pages?.get(chapter.last_page_read)?.let { page ->
// File where the image will be saved
val destFile = File(pictureDirectory, manga.title + " - " + chapter.name +
" - " + downloadManager.getImageFilename(page))
if (destFile.exists()) {
imageNotifier.onComplete(destFile)
} else {
// Progress of the download
var savedProgress = 0
val progressListener = object : ProgressListener {
override fun update(bytesRead: Long, contentLength: Long, done: Boolean) {
val progress = (100 * bytesRead / contentLength).toInt()
if (progress > savedProgress) {
savedProgress = progress
imageNotifier.onProgressChange(progress)
}
}
}
// Download and save the image.
Observable.fromCallable { ->
network.client.newCallWithProgress(GET(page.imageUrl!!), progressListener).execute()
}.map {
response ->
if (response.isSuccessful) {
response.body().source().saveTo(destFile)
imageNotifier.onComplete(destFile)
} else {
response.close()
throw Exception("Unsuccessful response")
}
}
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe({}, { error ->
Timber.e(error.message)
imageNotifier.onError(error.message)
})
}
}
}
}