diff --git a/app/build.gradle b/app/build.gradle
index a87138e69..96386dc2f 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -153,6 +153,8 @@ dependencies {
// Image library
compile 'com.github.bumptech.glide:glide:3.7.0'
compile 'com.github.bumptech.glide:okhttp3-integration:1.4.0@aar'
+ // Transformations
+ compile 'jp.wasabeef:glide-transformations:2.0.1'
// Logging
compile 'com.jakewharton.timber:timber:4.3.0'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index d91c3b2d6..91d0788e7 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -8,6 +8,7 @@
+
+ android:parentActivityName=".ui.main.MainActivity"
+ android:exported="true">
() {
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() {
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()!!)
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoFragment.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoFragment.kt
index 6ab67a923..6279466ce 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoFragment.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoFragment.kt
@@ -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() {
fun newInstance(): MangaInfoFragment {
return MangaInfoFragment()
}
+
}
override fun onCreate(savedState: Bundle?) {
@@ -61,6 +85,7 @@ class MangaInfoFragment : BaseRxFragment() {
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() {
}
}
+ /**
+ * 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) {
+ val modes = intArrayOf(R.string.circular_icon,
+ R.string.rounded_icon,
+ R.string.square_icon,
+ R.string.star_icon)
+
+ fun BitmapRequestBuilder.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.
*
diff --git a/app/src/main/res/drawable/ic_home_white_24dp.xml b/app/src/main/res/drawable/ic_home_white_24dp.xml
new file mode 100644
index 000000000..fafc05e0c
--- /dev/null
+++ b/app/src/main/res/drawable/ic_home_white_24dp.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/mask_star.png b/app/src/main/res/drawable/mask_star.png
new file mode 100644
index 000000000..5d3c11953
Binary files /dev/null and b/app/src/main/res/drawable/mask_star.png differ
diff --git a/app/src/main/res/menu/manga_info.xml b/app/src/main/res/menu/manga_info.xml
index e9aa77c9f..76f105d1d 100644
--- a/app/src/main/res/menu/manga_info.xml
+++ b/app/src/main/res/menu/manga_info.xml
@@ -12,4 +12,8 @@
android:title="@string/action_open_in_browser"
app:showAsAction="never"/>
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index d77e2da59..cb2d60fef 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -51,6 +51,7 @@
Remove
Resume
Open in browser
+ Add to home screen
Change display mode
Set filter
Cancel
@@ -225,6 +226,16 @@
Genres
Share…
Check out %1$s! at %2$s
+ Manga added to home screen
+ Icon type
+ Tachiyomi icon
+ Circular icon
+ Rounded icon
+ Square icon
+ Star icon
+ Shortcut title
+ Icon shape
+ Failed to create shortcut!
Chapters
@@ -305,6 +316,7 @@
Select cover image
Select backup file
+ Select shortcut icon
New update available!