Reader seekbar back to ignoring gestures
Sharesheet update: Now shows a preview of images shared, a preview of the manga you're sharing on android 10 Sharing via the saved image notification now shows the share sheet
This commit is contained in:
parent
fee4328ad0
commit
d263f03cc7
@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.data.notification
|
|||||||
import android.app.Notification
|
import android.app.Notification
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.ClipData
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
@ -86,12 +87,16 @@ class NotificationReceiver : BroadcastReceiver() {
|
|||||||
val uri = File(path).getUriCompat(context)
|
val uri = File(path).getUriCompat(context)
|
||||||
putExtra(Intent.EXTRA_STREAM, uri)
|
putExtra(Intent.EXTRA_STREAM, uri)
|
||||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||||
|
clipData = ClipData.newRawUri(null, uri)
|
||||||
type = "image/*"
|
type = "image/*"
|
||||||
}
|
}
|
||||||
// Dismiss notification
|
// Close Navigation Shade
|
||||||
dismissNotification(context, notificationId)
|
context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS))
|
||||||
// Launch share activity
|
// Launch share activity
|
||||||
context.startActivity(intent)
|
val shareIntent = Intent.createChooser(intent, context.getString(R.string
|
||||||
|
.action_share))
|
||||||
|
shareIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||||
|
context.startActivity(shareIntent)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -106,8 +111,7 @@ class NotificationReceiver : BroadcastReceiver() {
|
|||||||
val db = DatabaseHelper(context)
|
val db = DatabaseHelper(context)
|
||||||
val manga = db.getManga(mangaId).executeAsBlocking()
|
val manga = db.getManga(mangaId).executeAsBlocking()
|
||||||
val chapter = db.getChapter(chapterId).executeAsBlocking()
|
val chapter = db.getChapter(chapterId).executeAsBlocking()
|
||||||
val it = Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)
|
context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS))
|
||||||
context.sendBroadcast(it)
|
|
||||||
if (manga != null && chapter != null) {
|
if (manga != null && chapter != null) {
|
||||||
val intent = ReaderActivity.newIntent(context, manga, chapter).apply {
|
val intent = ReaderActivity.newIntent(context, manga, chapter).apply {
|
||||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||||
|
@ -20,6 +20,7 @@ import android.widget.Toast
|
|||||||
import com.afollestad.materialdialogs.MaterialDialog
|
import com.afollestad.materialdialogs.MaterialDialog
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
|
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
|
||||||
|
import com.bumptech.glide.request.target.CustomTarget
|
||||||
import com.bumptech.glide.request.target.SimpleTarget
|
import com.bumptech.glide.request.target.SimpleTarget
|
||||||
import com.bumptech.glide.request.transition.Transition
|
import com.bumptech.glide.request.transition.Transition
|
||||||
import com.jakewharton.rxbinding.support.v4.widget.refreshes
|
import com.jakewharton.rxbinding.support.v4.widget.refreshes
|
||||||
@ -46,6 +47,7 @@ import jp.wasabeef.glide.transformations.CropSquareTransformation
|
|||||||
import jp.wasabeef.glide.transformations.MaskTransformation
|
import jp.wasabeef.glide.transformations.MaskTransformation
|
||||||
import kotlinx.android.synthetic.main.manga_info_controller.*
|
import kotlinx.android.synthetic.main.manga_info_controller.*
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
import java.io.File
|
||||||
import java.text.DateFormat
|
import java.text.DateFormat
|
||||||
import java.text.DecimalFormat
|
import java.text.DecimalFormat
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
@ -161,7 +163,7 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
|
|||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.action_open_in_browser -> openInBrowser()
|
R.id.action_open_in_browser -> openInBrowser()
|
||||||
R.id.action_open_in_web_view -> openInWebView()
|
R.id.action_open_in_web_view -> openInWebView()
|
||||||
R.id.action_share -> shareManga()
|
R.id.action_share -> prepareToShareManga()
|
||||||
R.id.action_add_to_home_screen -> addToHomeScreen()
|
R.id.action_add_to_home_screen -> addToHomeScreen()
|
||||||
else -> return super.onOptionsItemSelected(item)
|
else -> return super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
@ -325,15 +327,40 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
|
|||||||
/**
|
/**
|
||||||
* Called to run Intent with [Intent.ACTION_SEND], which show share dialog.
|
* Called to run Intent with [Intent.ACTION_SEND], which show share dialog.
|
||||||
*/
|
*/
|
||||||
private fun shareManga() {
|
private fun prepareToShareManga() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
|
||||||
|
GlideApp.with(activity!!).asBitmap().load(presenter.manga).into(object :
|
||||||
|
CustomTarget<Bitmap>() {
|
||||||
|
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
|
||||||
|
presenter.shareManga(resource)
|
||||||
|
}
|
||||||
|
override fun onLoadCleared(placeholder: Drawable?) {}
|
||||||
|
|
||||||
|
override fun onLoadFailed(errorDrawable: Drawable?) {
|
||||||
|
shareManga()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
else shareManga()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called to run Intent with [Intent.ACTION_SEND], which show share dialog.
|
||||||
|
*/
|
||||||
|
fun shareManga(cover: File? = null) {
|
||||||
val context = view?.context ?: return
|
val context = view?.context ?: return
|
||||||
|
|
||||||
val source = presenter.source as? HttpSource ?: return
|
val source = presenter.source as? HttpSource ?: return
|
||||||
|
val stream = cover?.getUriCompat(context)
|
||||||
try {
|
try {
|
||||||
val url = source.mangaDetailsRequest(presenter.manga).url.toString()
|
val url = source.mangaDetailsRequest(presenter.manga).url.toString()
|
||||||
val intent = Intent(Intent.ACTION_SEND).apply {
|
val intent = Intent(Intent.ACTION_SEND).apply {
|
||||||
type = "text/plain"
|
type = "text/*"
|
||||||
putExtra(Intent.EXTRA_TEXT, url)
|
putExtra(Intent.EXTRA_TEXT, url)
|
||||||
|
putExtra(Intent.EXTRA_TITLE, presenter.manga.title)
|
||||||
|
flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||||
|
if (stream != null) {
|
||||||
|
clipData = ClipData.newRawUri(null, stream)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
startActivity(Intent.createChooser(intent, context.getString(R.string.action_share)))
|
startActivity(Intent.createChooser(intent, context.getString(R.string.action_share)))
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@ -523,11 +550,13 @@ class MangaInfoController : NucleusController<MangaInfoPresenter>(),
|
|||||||
3 -> centerCrop().transform(MaskTransformation(R.drawable.mask_star))
|
3 -> centerCrop().transform(MaskTransformation(R.drawable.mask_star))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.into(object : SimpleTarget<Bitmap>(96, 96) {
|
.into(object : CustomTarget<Bitmap>(96, 96) {
|
||||||
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
|
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
|
||||||
createShortcut(resource)
|
createShortcut(resource)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onLoadCleared(placeholder: Drawable?) { }
|
||||||
|
|
||||||
override fun onLoadFailed(errorDrawable: Drawable?) {
|
override fun onLoadFailed(errorDrawable: Drawable?) {
|
||||||
activity?.toast(R.string.icon_creation_fail)
|
activity?.toast(R.string.icon_creation_fail)
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package eu.kanade.tachiyomi.ui.manga.info
|
package eu.kanade.tachiyomi.ui.manga.info
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import android.graphics.Bitmap
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import com.jakewharton.rxrelay.BehaviorRelay
|
import com.jakewharton.rxrelay.BehaviorRelay
|
||||||
import com.jakewharton.rxrelay.PublishRelay
|
import com.jakewharton.rxrelay.PublishRelay
|
||||||
@ -11,6 +13,8 @@ import eu.kanade.tachiyomi.data.database.models.MangaCategory
|
|||||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||||
|
import eu.kanade.tachiyomi.util.DiskUtil
|
||||||
|
import eu.kanade.tachiyomi.util.ImageUtil
|
||||||
import eu.kanade.tachiyomi.util.isNullOrUnsubscribed
|
import eu.kanade.tachiyomi.util.isNullOrUnsubscribed
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.Subscription
|
import rx.Subscription
|
||||||
@ -18,6 +22,11 @@ import rx.android.schedulers.AndroidSchedulers
|
|||||||
import rx.schedulers.Schedulers
|
import rx.schedulers.Schedulers
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileInputStream
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
import java.io.InputStream
|
||||||
|
import java.io.OutputStream
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -116,6 +125,35 @@ class MangaInfoPresenter(
|
|||||||
toggleFavorite()
|
toggleFavorite()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun shareManga(cover:Bitmap) {
|
||||||
|
val context = Injekt.get<Application>()
|
||||||
|
|
||||||
|
val destDir = File(context.cacheDir, "shared_image")
|
||||||
|
|
||||||
|
Observable.fromCallable { destDir.deleteRecursively() } // Keep only the last shared file
|
||||||
|
.map { saveImage(cover, destDir, manga) }
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribeFirst(
|
||||||
|
{ view, file -> view.shareManga(file) },
|
||||||
|
{ view, error -> view.shareManga() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun saveImage(cover:Bitmap, directory: File, manga: Manga): File? {
|
||||||
|
directory.mkdirs()
|
||||||
|
|
||||||
|
// Build destination file.
|
||||||
|
val filename = DiskUtil.buildValidFilename("${manga.title} - Cover.jpg")
|
||||||
|
|
||||||
|
val destFile = File(directory, filename)
|
||||||
|
val stream: OutputStream = FileOutputStream(destFile)
|
||||||
|
cover.compress(Bitmap.CompressFormat.JPEG,75,stream)
|
||||||
|
stream.flush()
|
||||||
|
stream.close()
|
||||||
|
return destFile
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the default, and user categories.
|
* Get the default, and user categories.
|
||||||
*
|
*
|
||||||
|
@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.ui.reader
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.ProgressDialog
|
import android.app.ProgressDialog
|
||||||
|
import android.content.ClipData
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.ActivityInfo
|
import android.content.pm.ActivityInfo
|
||||||
@ -156,17 +157,6 @@ class ReaderActivity : BaseRxActivity<ReaderPresenter>(),
|
|||||||
|
|
||||||
config = ReaderConfig()
|
config = ReaderConfig()
|
||||||
initializeMenu()
|
initializeMenu()
|
||||||
val container: ViewGroup = findViewById(R.id.reader_container)
|
|
||||||
val readerBHeight = reader_menu_bottom.layoutParams.height
|
|
||||||
container.doOnApplyWindowInsets { _, insets, padding ->
|
|
||||||
val bottomInset = if (Build.VERSION.SDK_INT >= 29)
|
|
||||||
(insets.mandatorySystemGestureInsets.bottom - insets.systemWindowInsetBottom)
|
|
||||||
else 0
|
|
||||||
reader_menu_bottom.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
|
||||||
height = readerBHeight + bottomInset
|
|
||||||
}
|
|
||||||
reader_menu_bottom.updatePaddingRelative(bottom = padding.bottom + bottomInset)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -312,6 +302,9 @@ class ReaderActivity : BaseRxActivity<ReaderPresenter>(),
|
|||||||
systemUi?.show()
|
systemUi?.show()
|
||||||
reader_menu.visibility = View.VISIBLE
|
reader_menu.visibility = View.VISIBLE
|
||||||
reader_menu_bottom.visibility = View.VISIBLE
|
reader_menu_bottom.visibility = View.VISIBLE
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
|
window.navigationBarColor = getResourceColor(R.attr.colorPrimaryDark)
|
||||||
|
}
|
||||||
if (animate) {
|
if (animate) {
|
||||||
if (!menuStickyVisible) {
|
if (!menuStickyVisible) {
|
||||||
val toolbarAnimation = AnimationUtils.loadAnimation(this, R.anim.enter_from_top)
|
val toolbarAnimation = AnimationUtils.loadAnimation(this, R.anim.enter_from_top)
|
||||||
@ -513,6 +506,7 @@ class ReaderActivity : BaseRxActivity<ReaderPresenter>(),
|
|||||||
val intent = Intent(Intent.ACTION_SEND).apply {
|
val intent = Intent(Intent.ACTION_SEND).apply {
|
||||||
putExtra(Intent.EXTRA_STREAM, stream)
|
putExtra(Intent.EXTRA_STREAM, stream)
|
||||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||||
|
clipData = ClipData.newRawUri(null, stream)
|
||||||
type = "image/*"
|
type = "image/*"
|
||||||
}
|
}
|
||||||
startActivity(Intent.createChooser(intent, getString(R.string.action_share)))
|
startActivity(Intent.createChooser(intent, getString(R.string.action_share)))
|
||||||
@ -570,6 +564,9 @@ class ReaderActivity : BaseRxActivity<ReaderPresenter>(),
|
|||||||
setMenuVisibility(false)
|
setMenuVisibility(false)
|
||||||
menuStickyVisible = false
|
menuStickyVisible = false
|
||||||
}
|
}
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
|
window.navigationBarColor = getColor(android.R.color.transparent)
|
||||||
|
}
|
||||||
reader_menu_bottom.visibility = View.GONE
|
reader_menu_bottom.visibility = View.GONE
|
||||||
reader_menu.visibility = View.VISIBLE
|
reader_menu.visibility = View.VISIBLE
|
||||||
val toolbarAnimation = AnimationUtils.loadAnimation(this, R.anim.enter_from_top)
|
val toolbarAnimation = AnimationUtils.loadAnimation(this, R.anim.enter_from_top)
|
||||||
@ -579,9 +576,6 @@ class ReaderActivity : BaseRxActivity<ReaderPresenter>(),
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
toolbar.startAnimation(toolbarAnimation)
|
toolbar.startAnimation(toolbarAnimation)
|
||||||
/*val bottomAnimation = AnimationUtils.loadAnimation(this, R.anim
|
|
||||||
.enter_from_bottom)
|
|
||||||
reader_menu_bottom.startAnimation(bottomAnimation)*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -20,6 +20,8 @@ class ReaderSeekBar @JvmOverloads constructor(
|
|||||||
* Whether the seekbar should draw from right to left.
|
* Whether the seekbar should draw from right to left.
|
||||||
*/
|
*/
|
||||||
var isRTL = false
|
var isRTL = false
|
||||||
|
private val boundingBox: Rect = Rect()
|
||||||
|
private val exclusions = listOf(boundingBox)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the seekbar, translating the canvas if using a right to left reader.
|
* Draws the seekbar, translating the canvas if using a right to left reader.
|
||||||
@ -43,4 +45,14 @@ class ReaderSeekBar @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
return super.onTouchEvent(event)
|
return super.onTouchEvent(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
|
||||||
|
super.onLayout(changed, left, top, right, bottom)
|
||||||
|
if (Build.VERSION.SDK_INT >= 29) {
|
||||||
|
if (changed) {
|
||||||
|
boundingBox.set(left, top, right, bottom)
|
||||||
|
systemGestureExclusionRects = exclusions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user