Эх сурвалжийг харах

Added code to prevent OutOfMemory error. Made notification optional. Can now save image on long press. Bug fixes

Bram van de Kerkhof 8 жил өмнө
parent
commit
4975787afa

+ 13 - 1
app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt

@@ -47,6 +47,8 @@ class DownloadManager(
     private val threadsSubject = BehaviorSubject.create<Int>()
     private var threadsSubscription: Subscription? = null
 
+    private var notificationSubscription: Subscription? = null
+
     val queue = DownloadQueue()
 
     val imageFilenameRegex = "[^\\sa-zA-Z0-9.-]".toRegex()
@@ -66,6 +68,12 @@ class DownloadManager(
                     downloadNotifier.multipleDownloadThreads = it > 1
                 }
 
+        notificationSubscription = preferences.showMangaDownloadNotification().asObservable()
+                .subscribe {
+                    downloadNotifier.onClear()
+                    downloadNotifier.showNotification = it
+                }
+
         downloadsSubscription = downloadsQueueSubject.flatMap { Observable.from(it) }
                 .lift(DynamicConcurrentMergeOperator<Download, Download>({ downloadChapter(it) }, threadsSubject))
                 .onBackpressureBuffer()
@@ -107,6 +115,10 @@ class DownloadManager(
             threadsSubscription?.unsubscribe()
         }
 
+        if (notificationSubscription != null) {
+            notificationSubscription?.unsubscribe()
+        }
+
     }
 
     // Create a download object for every chapter and add them to the downloads queue
@@ -188,7 +200,7 @@ class DownloadManager(
         DiskUtils.createDirectory(download.directory)
 
         val pageListObservable: Observable<List<Page>> = if (download.pages == null)
-            // Pull page list from network and add them to download object
+        // Pull page list from network and add them to download object
             download.source.fetchPageListFromNetwork(download.chapter)
                     .doOnNext { pages ->
                         download.pages = pages

+ 30 - 22
app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadNotifier.kt

@@ -7,6 +7,7 @@ import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.download.model.Download
 import eu.kanade.tachiyomi.data.download.model.DownloadQueue
 import eu.kanade.tachiyomi.util.notificationManager
+import eu.kanade.tachiyomi.util.toast
 
 /**
  * DownloadNotifier is used to show notifications when downloading one or multiple chapters.
@@ -40,6 +41,11 @@ class DownloadNotifier(private val context: Context) {
      */
     internal var multipleDownloadThreads = false
 
+    /**
+     * Value determining if notification should be shown
+     */
+    internal var showNotification = true
+
     /**
      * Called when download progress changes.
      * Note: Only accepted when multi download active.
@@ -47,9 +53,8 @@ class DownloadNotifier(private val context: Context) {
      * @param queue the queue containing downloads.
      */
     internal fun onProgressChange(queue: DownloadQueue) {
-        if (multipleDownloadThreads) {
+        if (multipleDownloadThreads && showNotification)
             doOnProgressChange(null, queue)
-        }
     }
 
     /**
@@ -60,9 +65,8 @@ class DownloadNotifier(private val context: Context) {
      * @param queue the queue containing downloads
      */
     internal fun onProgressChange(download: Download, queue: DownloadQueue) {
-        if (!multipleDownloadThreads) {
+        if (!multipleDownloadThreads && showNotification)
             doOnProgressChange(download, queue)
-        }
     }
 
     /**
@@ -86,7 +90,7 @@ class DownloadNotifier(private val context: Context) {
         }
 
         // Create notification
-        with (notificationBuilder) {
+        with(notificationBuilder) {
             // Check if icon needs refresh
             if (!isDownloading) {
                 setSmallIcon(android.R.drawable.stat_sys_download)
@@ -127,17 +131,18 @@ class DownloadNotifier(private val context: Context) {
      * @param download download object containing download information
      */
     private fun onComplete(download: Download?) {
-        // Create notification.
-        with(notificationBuilder) {
-            setContentTitle(download?.chapter?.name ?: context.getString(R.string.app_name))
-            setContentText(context.getString(R.string.update_check_notification_download_complete))
-            setSmallIcon(android.R.drawable.stat_sys_download_done)
-            setProgress(0, 0, false)
-        }
-
-        // Show notification.
-        context.notificationManager.notify(notificationId, notificationBuilder.build())
+        if (showNotification) {
+            // Create notification.
+            with(notificationBuilder) {
+                setContentTitle(download?.chapter?.name ?: context.getString(R.string.app_name))
+                setContentText(context.getString(R.string.update_check_notification_download_complete))
+                setSmallIcon(android.R.drawable.stat_sys_download_done)
+                setProgress(0, 0, false)
+            }
 
+            // Show notification.
+            context.notificationManager.notify(notificationId, notificationBuilder.build())
+        }
         // Reset initial values
         isDownloading = false
         initialQueueSize = 0
@@ -158,14 +163,17 @@ class DownloadNotifier(private val context: Context) {
      */
     internal fun onError(error: String? = null, chapter: String? = null) {
         // Create notification
-        with(notificationBuilder) {
-            setContentTitle(chapter ?: context.getString(R.string.download_notifier_title_error))
-            setContentText(error ?: context.getString(R.string.download_notifier_unkown_error))
-            setSmallIcon(android.R.drawable.stat_sys_warning)
-            setProgress(0, 0, false)
+        if (showNotification) {
+            with(notificationBuilder) {
+                setContentTitle(chapter ?: context.getString(R.string.download_notifier_title_error))
+                setContentText(error ?: context.getString(R.string.download_notifier_unkown_error))
+                setSmallIcon(android.R.drawable.stat_sys_warning)
+                setProgress(0, 0, false)
+            }
+            context.notificationManager.notify(Constants.NOTIFICATION_DOWNLOAD_CHAPTER_ERROR_ID, notificationBuilder.build())
+        } else {
+            context.toast(error ?: context.getString(R.string.download_notifier_unkown_error))
         }
-        context.notificationManager.notify(Constants.NOTIFICATION_DOWNLOAD_CHAPTER_ERROR_ID, notificationBuilder.build())
-
         // Reset download information
         onClear()
         isDownloading = false

+ 6 - 20
app/src/main/java/eu/kanade/tachiyomi/data/download/ImageNotifier.kt

@@ -1,11 +1,10 @@
 package eu.kanade.tachiyomi.data.download
 
 import android.content.Context
-import android.graphics.Bitmap
-import android.graphics.BitmapFactory
 import android.support.v4.app.NotificationCompat
 import eu.kanade.tachiyomi.Constants
 import eu.kanade.tachiyomi.R
+import eu.kanade.tachiyomi.util.decodeSampledBitmap
 import eu.kanade.tachiyomi.util.notificationManager
 import java.io.File
 
@@ -52,9 +51,9 @@ class ImageNotifier(private val context: Context) {
 
     /**
      * Called when image download is complete
-     * @param bitmap image file containing downloaded page image
+     * @param file image file containing downloaded page image
      */
-    fun onComplete(bitmap: Bitmap, file: File) {
+    fun onComplete(file: File) {
         with(notificationBuilder) {
             if (isDownloading) {
                 setProgress(0, 0, false)
@@ -62,8 +61,8 @@ class ImageNotifier(private val context: Context) {
             }
             setContentTitle(context.getString(R.string.picture_saved))
             setSmallIcon(R.drawable.ic_insert_photo_black_24dp)
-            setLargeIcon(bitmap)
-            setStyle(NotificationCompat.BigPictureStyle().bigPicture(bitmap))
+            setLargeIcon(file.decodeSampledBitmap(100, 100))
+            setStyle(NotificationCompat.BigPictureStyle().bigPicture(file.decodeSampledBitmap(1024, 1024)))
             setAutoCancel(true)
 
             // Clear old actions if they exist
@@ -84,10 +83,6 @@ class ImageNotifier(private val context: Context) {
         context.notificationManager.notify(notificationId, notificationBuilder.build())
     }
 
-    fun onComplete(file: File) {
-        onComplete(convertToBitmap(file), file)
-    }
-
     /**
      * Clears the notification message
      */
@@ -112,13 +107,4 @@ class ImageNotifier(private val context: Context) {
         isDownloading = false
     }
 
-    /**
-     * Converts file to bitmap
-     */
-    fun convertToBitmap(image: File): Bitmap {
-        val options = BitmapFactory.Options()
-        options.inPreferredConfig = Bitmap.Config.ARGB_8888
-        return BitmapFactory.decodeFile(image.absolutePath, options)
-    }
-
-}
+}

+ 4 - 0
app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt

@@ -72,6 +72,10 @@ class PreferenceKeys(context: Context) {
 
     val removeAfterMarkedAsRead = context.getString(R.string.pref_remove_after_marked_as_read_key)
 
+    val showMangaDownloadNotification = context.getString(R.string.pref_notifications_manga_download_key)
+
+    val showSavePageNotification = context.getString(R.string.pref_notifications_single_page_key)
+
     val libraryUpdateInterval = context.getString(R.string.pref_library_update_interval_key)
 
     val libraryUpdateRestriction = context.getString(R.string.pref_library_update_restriction_key)

+ 4 - 0
app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt

@@ -122,6 +122,10 @@ class PreferencesHelper(context: Context) {
 
     fun removeAfterMarkedAsRead() = prefs.getBoolean(keys.removeAfterMarkedAsRead, false)
 
+    fun showMangaDownloadNotification() = rxPrefs.getBoolean(keys.showMangaDownloadNotification, true)
+
+    fun showSavePageNotification() = prefs.getBoolean(keys.showSavePageNotification, false)
+
     fun libraryUpdateInterval() = rxPrefs.getInteger(keys.libraryUpdateInterval, 0)
 
     fun libraryUpdateRestriction() = prefs.getStringSet(keys.libraryUpdateRestriction, emptySet())

+ 16 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt

@@ -145,8 +145,6 @@ 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
@@ -230,6 +228,22 @@ class ReaderActivity : BaseRxActivity<ReaderPresenter>() {
         // Ignore
     }
 
+    fun onLongPress() {
+        MaterialDialog.Builder(this).apply {
+            title = "Choose"
+            items(R.array.reader_image_options)
+                    .itemsIds(R.array.reader_image_options_values)
+            itemsCallback { materialDialog, view, i, charSequence ->
+                when (i) {
+                    0 -> presenter.setCover()
+                    1 -> presenter.shareImage()
+                    2 -> presenter.savePage()
+                }
+
+            }.show()
+        }
+    }
+
     /**
      * Called from the presenter at startup, allowing to prepare the selected reader.
      */

+ 23 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt

@@ -1,5 +1,7 @@
 package eu.kanade.tachiyomi.ui.reader
 
+import android.content.Intent
+import android.net.Uri
 import android.os.Bundle
 import android.os.Environment
 import eu.kanade.tachiyomi.R
@@ -576,6 +578,19 @@ class ReaderPresenter : BasePresenter<ReaderActivity>() {
         return false
     }
 
+    fun shareImage() {
+        chapter.pages?.get(chapter.last_page_read)?.let { page ->
+            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"
+            }
+            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 })
+        }
+    }
+
     /**
      * Save page to local storage
      * @throws IOException
@@ -595,7 +610,10 @@ class ReaderPresenter : BasePresenter<ReaderActivity>() {
 
             //Check if file doesn't already exist
             if (destFile.exists()) {
-                imageNotifier.onComplete(destFile)
+                if (prefs.showSavePageNotification())
+                    imageNotifier.onComplete(destFile)
+                else
+                    context.toast(context.getString(R.string.page_downloaded, destFile.path))
             } else {
                 if (inputFile.exists()) {
                     // Copy file
@@ -606,7 +624,10 @@ class ReaderPresenter : BasePresenter<ReaderActivity>() {
                                     { imageNotifier.onComplete(it) },
                                     { error ->
                                         Timber.e(error.message)
-                                        imageNotifier.onError(error.message)
+                                        if (prefs.showSavePageNotification())
+                                            imageNotifier.onError(error.message)
+                                        else
+                                            context.toast(error.message)
                                     })
                 }
             }

+ 5 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerReader.kt

@@ -185,6 +185,11 @@ abstract class PagerReader : BaseReader() {
                 }
                 return true
             }
+
+            override fun onLongPress(e: MotionEvent?) {
+                super.onLongPress(e)
+                readerActivity.onLongPress()
+            }
         })
     }
 

+ 5 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonReader.kt

@@ -140,6 +140,11 @@ class WebtoonReader : BaseReader() {
                 }
                 return true
             }
+
+            override fun onLongPress(e: MotionEvent?) {
+                super.onLongPress(e)
+                readerActivity.onLongPress()
+            }
         })
     }
 

+ 40 - 0
app/src/main/java/eu/kanade/tachiyomi/util/FileExtensions.kt

@@ -0,0 +1,40 @@
+package eu.kanade.tachiyomi.util
+
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
+import java.io.File
+
+fun File.decodeSampledBitmap(reqWidth: Int, reqHeight: Int): Bitmap {
+    // First decode with inJustDecodeBounds=true to check dimensions
+    val options = BitmapFactory.Options()
+    options.inJustDecodeBounds = true
+    BitmapFactory.decodeFile(this.absolutePath, options)
+
+    // Calculate inSampleSize
+    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight)
+
+    // Decode bitmap with inSampleSize set
+    options.inJustDecodeBounds = false;
+    return BitmapFactory.decodeFile(this.absolutePath, options)
+}
+
+fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int {
+    // Raw height and width of image
+    val height = options.outHeight
+    val width = options.outWidth
+    var inSampleSize = 1
+
+    if (height > reqHeight || width > reqWidth) {
+
+        val halfHeight = height / 2
+        val halfWidth = width / 2
+
+        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
+        // height and width larger than the requested height and width.
+        while (halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth) {
+            inSampleSize *= 2
+        }
+    }
+
+    return inSampleSize
+}

+ 12 - 0
app/src/main/res/values/arrays.xml

@@ -174,4 +174,16 @@
         <item>3</item>
     </string-array>
 
+    <string-array name="reader_image_options">
+        <item>@string/set_as_cover</item>
+        <item>@string/share_image</item>
+        <item>@string/save_image</item>
+    </string-array>
+
+    <string-array name="reader_image_options_values">
+        <item>0</item>
+        <item>1</item>
+        <item>2</item>
+    </string-array>
+
 </resources>

+ 2 - 1
app/src/main/res/values/keys.xml

@@ -48,7 +48,8 @@
     <string name="pref_download_only_over_wifi_key">pref_download_only_over_wifi_key</string>
     <string name="pref_remove_after_marked_as_read_key">pref_remove_after_marked_as_read_key</string>
     <string name="pref_category_remove_after_read_key">pref_category_remove_after_read_key</string>
-
+    <string name="pref_notifications_single_page_key">notifications_single_page</string>
+    <string name="pref_notifications_manga_download_key">notifications_manga_download</string>
     <string name="pref_last_used_category_key">last_used_category</string>
 
     <string name="pref_source_languages">pref_source_languages</string>

+ 5 - 0
app/src/main/res/values/strings.xml

@@ -281,6 +281,11 @@
 
     <!-- Reader activity -->
     <string name="custom_filter">Custom filter</string>
+    <string name="set_as_cover">Set as cover</string>
+    <string name="share_image">Share image</string>
+    <string name="save_image">Save image</string>
+    <string name="cover_updated">Cover updated</string>
+    <string name="page_downloaded">Page copied to %1$s</string>
     <string name="downloading">Downloading…</string>
     <string name="download_progress">Downloaded %1$d%%</string>
     <string name="chapter_progress">Page: %1$d</string>

+ 15 - 0
app/src/main/res/xml/pref_downloads.xml

@@ -40,6 +40,21 @@
             android:summary="%s"
             android:title="@string/pref_remove_after_read" />
 
+        <PreferenceCategory
+            android:persistent="false"
+            android:title="@string/pref_notifications" />
+
+        <SwitchPreference
+            android:defaultValue="true"
+            android:key="@string/pref_notifications_manga_download_key"
+            android:title="@string/pref_notifications_manga_download" />
+
+        <SwitchPreference
+            android:defaultValue="false"
+            android:key="@string/pref_notifications_single_page_key"
+            android:title="@string/pref_notifications_single_page" />
+
+
     </PreferenceScreen>
 
 </PreferenceScreen>