Open from homescreen/add shortcut to launcher (#435)

* Add very basic "Add to homescreen" action in manga info fragment.

* Fix open from homescreen opening current manga (if a manga is open).
Code cleanup.

* Improve fix for "Opening from homescreen opens currently open manga if a manga is currently open" and fix "Going back to the main app via a Manga opened through a shortcut repeats the launcher open animation".

* Implement custom icons, add star icon and optimize some things.

* Remove Tachiyomi and custom image icon types.

* Move icon creation task into an observable.
Added some extra error handling.
This commit is contained in:
Andy Bao
2016-09-29 12:38:29 -04:00
committed by inorichi
parent a81609fd2c
commit d352405ba6
8 changed files with 135 additions and 1 deletions

View File

@ -24,6 +24,7 @@ class MangaActivity : BaseRxActivity<MangaPresenter>() {
const val FROM_CATALOGUE_EXTRA = "from_catalogue"
const val MANGA_EXTRA = "manga"
const val FROM_LAUNCHER_EXTRA = "from_launcher"
const val INFO_FRAGMENT = 0
const val CHAPTERS_FRAGMENT = 1
const val MYANIMELIST_FRAGMENT = 2
@ -47,6 +48,11 @@ class MangaActivity : BaseRxActivity<MangaPresenter>() {
super.onCreate(savedState)
setContentView(R.layout.activity_manga)
val fromLauncher = intent.getBooleanExtra(FROM_LAUNCHER_EXTRA, false)
//Remove any current manga if we are launching from launcher
if(fromLauncher) SharedData.remove(MangaEvent::class.java)
presenter.setMangaEvent(SharedData.getOrPut(MangaEvent::class.java) {
val id = intent.getLongExtra(MANGA_EXTRA, 0)
MangaEvent(presenter.db.getManga(id).executeAsBlocking()!!)

View File

@ -1,21 +1,44 @@
package eu.kanade.tachiyomi.ui.manga.info
import android.app.Activity
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.drawable.BitmapDrawable
import android.net.Uri
import android.os.Bundle
import android.support.customtabs.CustomTabsIntent
import android.support.design.widget.Snackbar
import android.util.SparseArray
import android.view.*
import com.afollestad.materialdialogs.MaterialDialog
import com.bumptech.glide.BitmapRequestBuilder
import com.bumptech.glide.BitmapTypeRequest
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.resource.bitmap.CenterCrop
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.source.Source
import eu.kanade.tachiyomi.data.source.online.OnlineSource
import eu.kanade.tachiyomi.ui.base.fragment.BaseRxFragment
import eu.kanade.tachiyomi.ui.library.LibraryFragment
import eu.kanade.tachiyomi.ui.manga.MangaActivity
import eu.kanade.tachiyomi.util.getResourceColor
import eu.kanade.tachiyomi.util.toast
import jp.wasabeef.glide.transformations.CropCircleTransformation
import jp.wasabeef.glide.transformations.CropSquareTransformation
import jp.wasabeef.glide.transformations.MaskTransformation
import jp.wasabeef.glide.transformations.RoundedCornersTransformation
import kotlinx.android.synthetic.main.fragment_manga_info.*
import kotlinx.android.synthetic.main.item_download.*
import nucleus.factory.RequiresPresenter
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
import timber.log.Timber
import java.io.IOException
import kotlin.concurrent.thread
/**
* Fragment that shows manga information.
@ -34,6 +57,7 @@ class MangaInfoFragment : BaseRxFragment<MangaInfoPresenter>() {
fun newInstance(): MangaInfoFragment {
return MangaInfoFragment()
}
}
override fun onCreate(savedState: Bundle?) {
@ -61,6 +85,7 @@ class MangaInfoFragment : BaseRxFragment<MangaInfoPresenter>() {
when (item.itemId) {
R.id.action_open_in_browser -> openInBrowser()
R.id.action_share -> shareManga()
R.id.action_add_to_home_screen -> addToHomeScreen()
else -> return super.onOptionsItemSelected(item)
}
return true
@ -178,6 +203,80 @@ class MangaInfoFragment : BaseRxFragment<MangaInfoPresenter>() {
}
}
/**
* Add the manga to the home screen
*/
fun addToHomeScreen() {
val shortcutIntent = activity.intent
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
.putExtra(MangaActivity.FROM_LAUNCHER_EXTRA, true)
val addIntent = Intent()
addIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent)
.action = "com.android.launcher.action.INSTALL_SHORTCUT"
//Set shortcut title
MaterialDialog.Builder(activity)
.title(R.string.shortcut_title)
.input("", presenter.manga.title, { md, text ->
//Set shortcut title
addIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, text.toString())
reshapeIconBitmap(addIntent,
Glide.with(context).load(presenter.manga).asBitmap())
})
.negativeText(android.R.string.cancel)
.onNegative { materialDialog, dialogAction -> materialDialog.cancel() }
.show()
}
fun reshapeIconBitmap(addIntent: Intent, request: BitmapTypeRequest<out Any>) {
val modes = intArrayOf(R.string.circular_icon,
R.string.rounded_icon,
R.string.square_icon,
R.string.star_icon)
fun BitmapRequestBuilder<out Any, Bitmap>.toIcon(): Bitmap {
return this.into(96, 96).get()
}
MaterialDialog.Builder(activity)
.title(R.string.icon_shape)
.negativeText(android.R.string.cancel)
.items(modes.map { getString(it) })
.itemsCallback { dialog, view, i, charSequence ->
Observable.fromCallable {
// i = 0: Circular icon
// i = 1: Rounded icon
// i = 2: Square icon
// i = 3: Star icon (because boredom)
when (i) {
0 -> request.transform(CropCircleTransformation(context)).toIcon()
1 -> request.transform(RoundedCornersTransformation(context, 5, 0)).toIcon()
2 -> request.transform(CropSquareTransformation(context)).toIcon()
3 -> request.transform(CenterCrop(context), MaskTransformation(context, R.drawable.mask_star)).toIcon()
else -> null
}
}.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ if (it != null) createShortcut(addIntent, it) },
{ context.toast(R.string.icon_creation_fail) })
}.show()
}
fun createShortcut(addIntent: Intent, icon: Bitmap) {
//Send shortcut intent
addIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON, icon)
context.sendBroadcast(addIntent)
//Go to launcher to show this shiny new shortcut!
val startMain = Intent(Intent.ACTION_MAIN)
startMain.addCategory(Intent.CATEGORY_HOME)
.flags = Intent.FLAG_ACTIVITY_NEW_TASK
activity.runOnUiThread {
startActivity(startMain)
}
}
/**
* Update FAB with correct drawable.
*