diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 7c9fab506c..6f402b8b06 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -54,6 +54,16 @@
android:theme="@style/FilePickerTheme">
+
+
+
+
@@ -68,9 +78,9 @@
-
-
+
+
+
() {
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)
}
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt
index 0b935c8735..4f8634b871 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt
@@ -5,6 +5,7 @@ import android.content.Intent
import android.content.pm.ActivityInfo
import android.content.res.Configuration
import android.graphics.Color
+import android.net.Uri
import android.os.Build
import android.os.Build.VERSION_CODES.KITKAT
import android.os.Bundle
@@ -224,6 +225,20 @@ class ReaderActivity : BaseRxActivity() {
toast(error.message)
}
+ fun onLongPress(page: Page) {
+ MaterialDialog.Builder(this)
+ .title(getString(R.string.options))
+ .items(R.array.reader_image_options)
+ .itemsIds(R.array.reader_image_options_values)
+ .itemsCallback { materialDialog, view, i, charSequence ->
+ when (i) {
+ 0 -> presenter.setCover(page)
+ 1 -> shareImage(page)
+ 2 -> presenter.savePage(page)
+ }
+ }.show()
+ }
+
fun onChapterAppendError() {
// Ignore
}
@@ -455,6 +470,24 @@ class ReaderActivity : BaseRxActivity() {
}
}
+ /**
+ * Start a share intent that lets user share image
+ *
+ * @param page page object containing image information.
+ */
+ fun shareImage(page: Page) {
+ if (page.status != Page.READY)
+ return
+
+ val shareIntent = Intent().apply {
+ action = Intent.ACTION_SEND
+ putExtra(Intent.EXTRA_STREAM, Uri.parse(page.imagePath))
+ flags = Intent.FLAG_ACTIVITY_NEW_TASK
+ type = "image/jpeg"
+ }
+ startActivity(Intent.createChooser(shareIntent, resources.getText(R.string.action_share)))
+ }
+
/**
* Sets the brightness of the screen. Range is [-75, 100].
* From -75 to -1 a semi-transparent black view is shown at the top with the minimum brightness.
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt
index 69cd6dff15..3f94a3f629 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt
@@ -1,7 +1,10 @@
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
@@ -15,8 +18,10 @@ import eu.kanade.tachiyomi.data.source.SourceManager
import eu.kanade.tachiyomi.data.source.model.Page
import eu.kanade.tachiyomi.data.source.online.OnlineSource
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
+import eu.kanade.tachiyomi.ui.reader.notification.ImageNotifier
import eu.kanade.tachiyomi.util.RetryWithDelay
import eu.kanade.tachiyomi.util.SharedData
+import eu.kanade.tachiyomi.util.toast
import rx.Observable
import rx.Subscription
import rx.android.schedulers.AndroidSchedulers
@@ -24,13 +29,13 @@ import rx.schedulers.Schedulers
import timber.log.Timber
import uy.kohesive.injekt.injectLazy
import java.io.File
+import java.io.IOException
import java.util.*
/**
* Presenter of [ReaderActivity].
*/
class ReaderPresenter : BasePresenter() {
-
/**
* Preferences.
*/
@@ -61,6 +66,11 @@ class ReaderPresenter : BasePresenter() {
*/
val chapterCache: ChapterCache by injectLazy()
+ /**
+ * Cover cache.
+ */
+ val coverCache: CoverCache by injectLazy()
+
/**
* Manga being read.
*/
@@ -88,6 +98,15 @@ class ReaderPresenter : BasePresenter() {
*/
private val source by lazy { sourceManager.get(manga.source)!! }
+ /**
+ * 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.
@@ -364,11 +383,11 @@ class ReaderPresenter : BasePresenter() {
if (chapter.read) {
val removeAfterReadSlots = prefs.removeAfterReadSlots()
when (removeAfterReadSlots) {
- // Setting disabled
+ // Setting disabled
-1 -> { /**Empty function**/ }
- // Remove current read chapter
+ // Remove current read chapter
0 -> deleteChapter(chapter, manga)
- // Remove previous chapter specified by user in settings.
+ // Remove previous chapter specified by user in settings.
else -> getAdjacentChaptersStrategy(chapter, removeAfterReadSlots)
.first?.let { deleteChapter(it, manga) }
}
@@ -384,8 +403,8 @@ class ReaderPresenter : BasePresenter() {
Timber.e(error)
}
}
- .subscribeOn(Schedulers.io())
- .subscribe()
+ .subscribeOn(Schedulers.io())
+ .subscribe()
}
/**
@@ -508,4 +527,65 @@ class ReaderPresenter : BasePresenter() {
db.insertManga(manga).executeAsBlocking()
}
+ /**
+ * Update cover with page file.
+ */
+ internal fun setCover(page: Page) {
+ if (page.status != Page.READY)
+ return
+
+ try {
+ if (manga.favorite) {
+ if (manga.thumbnail_url != null) {
+ coverCache.copyToCache(manga.thumbnail_url!!, File(page.imagePath).inputStream())
+ context.toast(R.string.cover_updated)
+ } else {
+ throw Exception("Image url not found")
+ }
+ } else {
+ context.toast(R.string.notification_first_add_to_library)
+ }
+ } catch (error: Exception) {
+ context.toast(R.string.notification_cover_update_failed)
+ Timber.e(error)
+ }
+ }
+
+ /**
+ * Save page to local storage
+ * @throws IOException
+ */
+ @Throws(IOException::class)
+ internal fun savePage(page: Page) {
+ if (page.status != Page.READY)
+ return
+
+ // Used to show image notification
+ val imageNotifier = ImageNotifier(context)
+
+ // Location of image file.
+ val inputFile = File(page.imagePath)
+
+ // File where the image will be saved.
+ val destFile = File(pictureDirectory, manga.title + " - " + chapter.name +
+ " - " + downloadManager.getImageFilename(page))
+
+ //Remove the notification if already exist (user feedback)
+ imageNotifier.onClear()
+ if (inputFile.exists()) {
+ // Copy file
+ Observable.fromCallable { inputFile.copyTo(destFile, true) }
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(
+ {
+ // Show notification
+ imageNotifier.onComplete(it)
+ },
+ { error ->
+ Timber.e(error)
+ imageNotifier.onError(error.message)
+ })
+ }
+ }
}
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/notification/ImageNotificationReceiver.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/notification/ImageNotificationReceiver.kt
new file mode 100644
index 0000000000..2c2a83d4e3
--- /dev/null
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/notification/ImageNotificationReceiver.kt
@@ -0,0 +1,109 @@
+package eu.kanade.tachiyomi.ui.reader.notification
+
+import android.app.PendingIntent
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.net.Uri
+import android.support.v4.content.FileProvider
+import eu.kanade.tachiyomi.R
+import eu.kanade.tachiyomi.util.notificationManager
+import java.io.File
+
+/**
+ * The BroadcastReceiver of [ImageNotifier]
+ * Intent calls should be made from this class.
+ */
+class ImageNotificationReceiver : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ when (intent.action) {
+ ACTION_SHARE_IMAGE -> {
+ shareImage(context, intent.getStringExtra(EXTRA_FILE_LOCATION))
+ context.notificationManager.cancel(intent.getIntExtra(NOTIFICATION_ID, 5))
+ }
+ ACTION_SHOW_IMAGE ->
+ showImage(context, intent.getStringExtra(EXTRA_FILE_LOCATION))
+ ACTION_DELETE_IMAGE -> {
+ deleteImage(intent.getStringExtra(EXTRA_FILE_LOCATION))
+ context.notificationManager.cancel(intent.getIntExtra(NOTIFICATION_ID, 5))
+ }
+ }
+ }
+
+ /**
+ * Called to delete image
+ * @param path path of file
+ */
+ private fun deleteImage(path: String) {
+ val file = File(path)
+ if (file.exists()) file.delete()
+ }
+
+ /**
+ * Called to start share intent to share image
+ * @param context context of application
+ * @param path path of file
+ */
+ private fun shareImage(context: Context, path: String) {
+ val shareIntent = Intent().apply {
+ action = Intent.ACTION_SEND
+ putExtra(Intent.EXTRA_STREAM, Uri.parse(path))
+ type = "image/jpeg"
+ }
+ context.startActivity(Intent.createChooser(shareIntent, context.resources.getText(R.string.action_share))
+ .apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_MULTIPLE_TASK })
+ }
+
+ /**
+ * Called to show image in gallery application
+ * @param context context of application
+ * @param path path of file
+ */
+ private fun showImage(context: Context, path: String) {
+ val intent = Intent().apply {
+ action = Intent.ACTION_VIEW
+ flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_MULTIPLE_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION
+ val uri = FileProvider.getUriForFile(context,"eu.kanade.tachiyomi.provider",File(path))
+ setDataAndType(uri, "image/*")
+ }
+ context.startActivity(intent)
+ }
+
+ companion object {
+ private const val ACTION_SHARE_IMAGE = "eu.kanade.SHARE_IMAGE"
+
+ private const val ACTION_SHOW_IMAGE = "eu.kanade.SHOW_IMAGE"
+
+ private const val ACTION_DELETE_IMAGE = "eu.kanade.DELETE_IMAGE"
+
+ private const val EXTRA_FILE_LOCATION = "file_location"
+
+ private const val NOTIFICATION_ID = "notification_id"
+
+ internal fun shareImageIntent(context: Context, path: String, notificationId: Int): PendingIntent {
+ val intent = Intent(context, ImageNotificationReceiver::class.java).apply {
+ action = ACTION_SHARE_IMAGE
+ putExtra(EXTRA_FILE_LOCATION, path)
+ putExtra(NOTIFICATION_ID, notificationId)
+ }
+ return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
+ }
+
+ internal fun showImageIntent(context: Context, path: String): PendingIntent {
+ val intent = Intent(context, ImageNotificationReceiver::class.java).apply {
+ action = ACTION_SHOW_IMAGE
+ putExtra(EXTRA_FILE_LOCATION, path)
+ }
+ return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
+ }
+
+ internal fun deleteImageIntent(context: Context, path: String, notificationId: Int): PendingIntent {
+ val intent = Intent(context, ImageNotificationReceiver::class.java).apply {
+ action = ACTION_DELETE_IMAGE
+ putExtra(EXTRA_FILE_LOCATION, path)
+ putExtra(NOTIFICATION_ID, notificationId)
+ }
+ return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
+ }
+ }
+}
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/notification/ImageNotifier.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/notification/ImageNotifier.kt
new file mode 100644
index 0000000000..a4edfcb52e
--- /dev/null
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/notification/ImageNotifier.kt
@@ -0,0 +1,104 @@
+package eu.kanade.tachiyomi.ui.reader.notification
+
+import android.content.Context
+import android.graphics.Bitmap
+import android.media.Image
+import android.support.v4.app.NotificationCompat
+import com.bumptech.glide.Glide
+import com.bumptech.glide.load.engine.DiskCacheStrategy
+import com.bumptech.glide.request.animation.GlideAnimation
+import com.bumptech.glide.request.target.SimpleTarget
+import eu.kanade.tachiyomi.Constants
+import eu.kanade.tachiyomi.R
+import eu.kanade.tachiyomi.util.notificationManager
+import java.io.File
+
+/**
+ * Class used to show BigPictureStyle notifications
+ */
+class ImageNotifier(private val context: Context) {
+ /**
+ * Notification builder.
+ */
+ private val notificationBuilder = NotificationCompat.Builder(context)
+
+ /**
+ * Id of the notification.
+ */
+ private val notificationId: Int
+ get() = Constants.NOTIFICATION_DOWNLOAD_IMAGE_ID
+
+ /**
+ * Called when image download/copy is complete
+ * @param file image file containing downloaded page image
+ */
+ fun onComplete(file: File) {
+
+ Glide.with(context).load(file).asBitmap().diskCacheStrategy(DiskCacheStrategy.NONE).skipMemoryCache(true).into(object : SimpleTarget(720, 1280) {
+ /**
+ * The method that will be called when the resource load has finished.
+ * @param resource the loaded resource.
+ */
+ override fun onResourceReady(resource: Bitmap?, glideAnimation: GlideAnimation?) {
+ if (resource!= null){
+ showCompleteNotification(file, resource)
+ }else{
+ onError(null)
+ }
+ }
+ })
+ }
+
+ private fun showCompleteNotification(file: File, image: Bitmap) {
+ with(notificationBuilder) {
+ setContentTitle(context.getString(R.string.picture_saved))
+ setSmallIcon(R.drawable.ic_insert_photo_white_24dp)
+ setStyle(NotificationCompat.BigPictureStyle().bigPicture(image))
+ setLargeIcon(image)
+ setAutoCancel(true)
+ // Clear old actions if they exist
+ if (!mActions.isEmpty())
+ mActions.clear()
+
+ setContentIntent(ImageNotificationReceiver.showImageIntent(context, file.absolutePath))
+ // Share action
+ addAction(R.drawable.ic_share_grey_24dp,
+ context.getString(R.string.action_share),
+ ImageNotificationReceiver.shareImageIntent(context, file.absolutePath, notificationId))
+ // Delete action
+ addAction(R.drawable.ic_delete_grey_24dp,
+ context.getString(R.string.action_delete),
+ ImageNotificationReceiver.deleteImageIntent(context, file.absolutePath, notificationId))
+ updateNotification()
+
+ }
+ }
+
+ /**
+ * Clears the notification message
+ */
+ fun onClear() {
+ context.notificationManager.cancel(notificationId)
+ }
+
+ private fun updateNotification() {
+ // Displays the progress bar on notification
+ context.notificationManager.notify(notificationId, notificationBuilder.build())
+ }
+
+
+ /**
+ * Called on error while downloading image
+ * @param error string containing error information
+ */
+ fun onError(error: String?) {
+ // Create notification
+ with(notificationBuilder) {
+ setContentTitle(context.getString(R.string.download_notifier_title_error))
+ setContentText(error ?: context.getString(R.string.unknown_error))
+ setSmallIcon(android.R.drawable.ic_menu_report_image)
+ }
+ updateNotification()
+ }
+
+}
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerReader.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerReader.kt
index 6d9a4bb63d..18cf1501c3 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerReader.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerReader.kt
@@ -11,6 +11,7 @@ import eu.kanade.tachiyomi.ui.reader.ReaderChapter
import eu.kanade.tachiyomi.ui.reader.viewer.base.BaseReader
import eu.kanade.tachiyomi.ui.reader.viewer.pager.horizontal.LeftToRightReader
import eu.kanade.tachiyomi.ui.reader.viewer.pager.horizontal.RightToLeftReader
+import eu.kanade.tachiyomi.util.toast
import rx.subscriptions.CompositeSubscription
/**
@@ -185,6 +186,16 @@ abstract class PagerReader : BaseReader() {
}
return true
}
+
+ override fun onLongPress(e: MotionEvent?) {
+ if (isAdded) {
+ val page = adapter.pages.getOrNull(pager.currentItem)
+ if (page != null)
+ readerActivity.onLongPress(page)
+ else
+ context.toast(getString(R.string.unknown_error))
+ }
+ }
})
}
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonReader.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonReader.kt
index f08eecd551..41fb2ac0a9 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonReader.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonReader.kt
@@ -6,9 +6,11 @@ import android.view.*
import android.view.GestureDetector.SimpleOnGestureListener
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
+import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.source.model.Page
import eu.kanade.tachiyomi.ui.reader.ReaderChapter
import eu.kanade.tachiyomi.ui.reader.viewer.base.BaseReader
+import eu.kanade.tachiyomi.util.toast
import eu.kanade.tachiyomi.widget.PreCachingLayoutManager
import rx.subscriptions.CompositeSubscription
@@ -140,12 +142,23 @@ class WebtoonReader : BaseReader() {
}
return true
}
+
+ override fun onLongPress(e: MotionEvent) {
+ if (isAdded) {
+ val child = recycler.findChildViewUnder(e.rawX, e.rawY)
+ val position = recycler.getChildAdapterPosition(child)
+ val page = adapter.pages?.getOrNull(position)
+ if (page != null)
+ readerActivity.onLongPress(page)
+ else
+ context.toast(getString(R.string.unknown_error))
+ }
+ }
})
}
/**
* Called when a new chapter is set in [BaseReader].
- *
* @param chapter the chapter set.
* @param currentPage the initial page to display.
*/
@@ -160,7 +173,6 @@ class WebtoonReader : BaseReader() {
/**
* Called when a chapter is appended in [BaseReader].
- *
* @param chapter the chapter appended.
*/
override fun onChapterAppended(chapter: ReaderChapter) {
@@ -184,7 +196,6 @@ class WebtoonReader : BaseReader() {
/**
* Sets the active page.
- *
* @param pageNumber the index of the page from [pages].
*/
override fun setActivePage(pageNumber: Int) {
diff --git a/app/src/main/res/drawable-hdpi/ic_delete_grey_24dp.png b/app/src/main/res/drawable-hdpi/ic_delete_grey_24dp.png
new file mode 100644
index 0000000000..13d2741f36
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_delete_grey_24dp.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_insert_photo_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_insert_photo_white_24dp.png
new file mode 100644
index 0000000000..25a9576ddd
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_insert_photo_white_24dp.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_share_grey_24dp.png b/app/src/main/res/drawable-hdpi/ic_share_grey_24dp.png
new file mode 100644
index 0000000000..c0b2a80e96
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_share_grey_24dp.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_delete_grey_24dp.png b/app/src/main/res/drawable-mdpi/ic_delete_grey_24dp.png
new file mode 100644
index 0000000000..a0df896860
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_delete_grey_24dp.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_insert_photo_white_24dp.png b/app/src/main/res/drawable-mdpi/ic_insert_photo_white_24dp.png
new file mode 100644
index 0000000000..d474bd577d
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_insert_photo_white_24dp.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_share_grey_24dp.png b/app/src/main/res/drawable-mdpi/ic_share_grey_24dp.png
new file mode 100644
index 0000000000..e2814bdc98
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_share_grey_24dp.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_delete_grey_24dp.png b/app/src/main/res/drawable-xhdpi/ic_delete_grey_24dp.png
new file mode 100644
index 0000000000..4ca7f7c9ad
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_delete_grey_24dp.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_insert_photo_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_insert_photo_white_24dp.png
new file mode 100644
index 0000000000..2642b9e09e
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_insert_photo_white_24dp.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_share_grey_24dp.png b/app/src/main/res/drawable-xhdpi/ic_share_grey_24dp.png
new file mode 100644
index 0000000000..f691067f71
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_share_grey_24dp.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_delete_grey_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_delete_grey_24dp.png
new file mode 100644
index 0000000000..209e555eea
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_delete_grey_24dp.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_insert_photo_white_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_insert_photo_white_24dp.png
new file mode 100644
index 0000000000..f9f1defa6d
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_insert_photo_white_24dp.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_share_grey_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_share_grey_24dp.png
new file mode 100644
index 0000000000..9ed5b4d432
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_share_grey_24dp.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_delete_grey_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_delete_grey_24dp.png
new file mode 100644
index 0000000000..a1b86d06e8
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_delete_grey_24dp.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_insert_photo_white_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_insert_photo_white_24dp.png
new file mode 100644
index 0000000000..2ffdb55f26
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_insert_photo_white_24dp.png differ
diff --git a/app/src/main/res/drawable-xxxhdpi/ic_share_grey_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_share_grey_24dp.png
new file mode 100644
index 0000000000..35b1664aa7
Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_share_grey_24dp.png differ
diff --git a/app/src/main/res/drawable/ic_insert_photo_white_24dp.png b/app/src/main/res/drawable/ic_insert_photo_white_24dp.png
new file mode 100644
index 0000000000..d474bd577d
Binary files /dev/null and b/app/src/main/res/drawable/ic_insert_photo_white_24dp.png differ
diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml
index 100ebec7f6..6e644174da 100644
--- a/app/src/main/res/values/arrays.xml
+++ b/app/src/main/res/values/arrays.xml
@@ -176,4 +176,16 @@
- 3
+
+ - @string/set_as_cover
+ - @string/action_share
+ - @string/action_save
+
+
+
+ - 0
+ - 1
+ - 2
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/keys.xml b/app/src/main/res/values/keys.xml
index ad8de7baab..f3694dc7ad 100644
--- a/app/src/main/res/values/keys.xml
+++ b/app/src/main/res/values/keys.xml
@@ -48,7 +48,6 @@
pref_download_only_over_wifi_key
pref_remove_after_marked_as_read_key
pref_category_remove_after_read_key
-
last_used_category
pref_source_languages
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index b6e9bdb3a6..aff0608169 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -62,6 +62,7 @@
Sort
Install
Share
+ Save
Deleting…
@@ -224,7 +225,6 @@
Status
Source
Genres
- Share…
Check out %1$s! at %2$s
Circular icon
Rounded icon
@@ -272,9 +272,16 @@
This will remove the read date of this chapter. Are you sure?
Reset all chapters for this manga
+
+ Picture saved
+ Saving picture
+ Options
Custom filter
+ Set as cover
+ Cover updated
+ Page copied to %1$s
Downloading…
Downloaded %1$d%%
Page: %1$d
@@ -305,6 +312,7 @@
No new chapters found
New chapters found for:
Failed to update manga:
+ Failed to update cover
Please add the manga to your library before doing this
Sync canceled
Not connected to AC power
diff --git a/app/src/main/res/xml/provider_paths.xml b/app/src/main/res/xml/provider_paths.xml
new file mode 100644
index 0000000000..5817df3bcb
--- /dev/null
+++ b/app/src/main/res/xml/provider_paths.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 5995e49e83..319ddb2e7d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -18,4 +18,4 @@ allprojects {
jcenter()
maven { url "https://jitpack.io" }
}
-}
\ No newline at end of file
+}