Added option to download page or set page as cover (#481)
* Added option to download page or set page as cover * Removed network call now copies from page image * Format fix + notification feedback * Added code to prevent OutOfMemory error. Made notification optional. Can now save image on long press. Bug fixes * Now uses glide for notification * Fixed webtoon page * Fixes + API 16 support * fixes * Fixed API 24 FileProvider error * Added page.ready check * Indention
@ -54,6 +54,16 @@
|
||||
android:theme="@style/FilePickerTheme">
|
||||
</activity>
|
||||
|
||||
<provider
|
||||
android:name="android.support.v4.content.FileProvider"
|
||||
android:authorities="eu.kanade.tachiyomi.provider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/provider_paths"/>
|
||||
</provider>
|
||||
|
||||
<service android:name=".data.library.LibraryUpdateService"
|
||||
android:exported="false"/>
|
||||
|
||||
@ -68,9 +78,9 @@
|
||||
|
||||
<receiver android:name=".data.updater.UpdateNotificationReceiver"/>
|
||||
|
||||
<receiver
|
||||
android:name=".data.library.LibraryUpdateService$CancelUpdateReceiver">
|
||||
</receiver>
|
||||
<receiver android:name=".data.library.LibraryUpdateService$CancelUpdateReceiver" />
|
||||
|
||||
<receiver android:name=".ui.reader.notification.ImageNotificationReceiver" />
|
||||
|
||||
<meta-data
|
||||
android:name="eu.kanade.tachiyomi.data.glide.AppGlideModule"
|
||||
|
@ -5,4 +5,5 @@ object Constants {
|
||||
const val NOTIFICATION_UPDATER_ID = 2
|
||||
const val NOTIFICATION_DOWNLOAD_CHAPTER_ID = 3
|
||||
const val NOTIFICATION_DOWNLOAD_CHAPTER_ERROR_ID = 4
|
||||
const val NOTIFICATION_DOWNLOAD_IMAGE_ID = 5
|
||||
}
|
||||
|
@ -297,7 +297,7 @@ class DownloadManager(
|
||||
}
|
||||
|
||||
// Get the filename for an image given the page
|
||||
private fun getImageFilename(page: Page): String {
|
||||
fun getImageFilename(page: Page): String {
|
||||
val url = page.imageUrl
|
||||
val number = String.format("%03d", page.pageNumber + 1)
|
||||
|
||||
|
@ -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.
|
||||
@ -47,10 +48,9 @@ class DownloadNotifier(private val context: Context) {
|
||||
* @param queue the queue containing downloads.
|
||||
*/
|
||||
internal fun onProgressChange(queue: DownloadQueue) {
|
||||
if (multipleDownloadThreads) {
|
||||
if (multipleDownloadThreads)
|
||||
doOnProgressChange(null, queue)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when download progress changes
|
||||
@ -60,10 +60,9 @@ class DownloadNotifier(private val context: Context) {
|
||||
* @param queue the queue containing downloads
|
||||
*/
|
||||
internal fun onProgressChange(download: Download, queue: DownloadQueue) {
|
||||
if (!multipleDownloadThreads) {
|
||||
if (!multipleDownloadThreads)
|
||||
doOnProgressChange(download, queue)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show notification progress of chapter
|
||||
@ -86,7 +85,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)
|
||||
@ -165,7 +164,6 @@ class DownloadNotifier(private val context: Context) {
|
||||
setProgress(0, 0, false)
|
||||
}
|
||||
context.notificationManager.notify(Constants.NOTIFICATION_DOWNLOAD_CHAPTER_ERROR_ID, notificationBuilder.build())
|
||||
|
||||
// Reset download information
|
||||
onClear()
|
||||
isDownloading = false
|
||||
|
@ -184,10 +184,9 @@ class MangaInfoFragment : BaseRxFragment<MangaInfoPresenter>() {
|
||||
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)
|
||||
}
|
||||
|
@ -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<ReaderPresenter>() {
|
||||
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<ReaderPresenter>() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
@ -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<ReaderActivity>() {
|
||||
|
||||
/**
|
||||
* Preferences.
|
||||
*/
|
||||
@ -61,6 +66,11 @@ class ReaderPresenter : BasePresenter<ReaderActivity>() {
|
||||
*/
|
||||
val chapterCache: ChapterCache by injectLazy()
|
||||
|
||||
/**
|
||||
* Cover cache.
|
||||
*/
|
||||
val coverCache: CoverCache by injectLazy()
|
||||
|
||||
/**
|
||||
* Manga being read.
|
||||
*/
|
||||
@ -88,6 +98,15 @@ class ReaderPresenter : BasePresenter<ReaderActivity>() {
|
||||
*/
|
||||
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.
|
||||
@ -508,4 +527,65 @@ class ReaderPresenter : BasePresenter<ReaderActivity>() {
|
||||
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)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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<Bitmap>(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<in Bitmap>?) {
|
||||
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()
|
||||
}
|
||||
|
||||
}
|
@ -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))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
BIN
app/src/main/res/drawable-hdpi/ic_delete_grey_24dp.png
Normal file
After Width: | Height: | Size: 485 B |
BIN
app/src/main/res/drawable-hdpi/ic_insert_photo_white_24dp.png
Normal file
After Width: | Height: | Size: 247 B |
BIN
app/src/main/res/drawable-hdpi/ic_share_grey_24dp.png
Normal file
After Width: | Height: | Size: 928 B |
BIN
app/src/main/res/drawable-mdpi/ic_delete_grey_24dp.png
Normal file
After Width: | Height: | Size: 367 B |
BIN
app/src/main/res/drawable-mdpi/ic_insert_photo_white_24dp.png
Normal file
After Width: | Height: | Size: 185 B |
BIN
app/src/main/res/drawable-mdpi/ic_share_grey_24dp.png
Normal file
After Width: | Height: | Size: 554 B |
BIN
app/src/main/res/drawable-xhdpi/ic_delete_grey_24dp.png
Normal file
After Width: | Height: | Size: 594 B |
BIN
app/src/main/res/drawable-xhdpi/ic_insert_photo_white_24dp.png
Normal file
After Width: | Height: | Size: 304 B |
BIN
app/src/main/res/drawable-xhdpi/ic_share_grey_24dp.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_delete_grey_24dp.png
Normal file
After Width: | Height: | Size: 695 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_insert_photo_white_24dp.png
Normal file
After Width: | Height: | Size: 450 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_share_grey_24dp.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
app/src/main/res/drawable-xxxhdpi/ic_delete_grey_24dp.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
app/src/main/res/drawable-xxxhdpi/ic_insert_photo_white_24dp.png
Normal file
After Width: | Height: | Size: 570 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_share_grey_24dp.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
app/src/main/res/drawable/ic_insert_photo_white_24dp.png
Normal file
After Width: | Height: | Size: 185 B |
@ -176,4 +176,16 @@
|
||||
<item>3</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="reader_image_options">
|
||||
<item>@string/set_as_cover</item>
|
||||
<item>@string/action_share</item>
|
||||
<item>@string/action_save</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="reader_image_options_values">
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
</string-array>
|
||||
|
||||
</resources>
|
@ -48,7 +48,6 @@
|
||||
<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_last_used_category_key">last_used_category</string>
|
||||
|
||||
<string name="pref_source_languages">pref_source_languages</string>
|
||||
|
@ -62,6 +62,7 @@
|
||||
<string name="action_sort">Sort</string>
|
||||
<string name="action_install">Install</string>
|
||||
<string name="action_share">Share</string>
|
||||
<string name="action_save">Save</string>
|
||||
|
||||
<!-- Operations -->
|
||||
<string name="deleting">Deleting…</string>
|
||||
@ -224,7 +225,6 @@
|
||||
<string name="manga_info_status_label">Status</string>
|
||||
<string name="manga_info_source_label">Source</string>
|
||||
<string name="manga_info_genres_label">Genres</string>
|
||||
<string name="share_subject">Share…</string>
|
||||
<string name="share_text">Check out %1$s! at %2$s</string>
|
||||
<string name="circular_icon">Circular icon</string>
|
||||
<string name="rounded_icon">Rounded icon</string>
|
||||
@ -272,9 +272,16 @@
|
||||
<string name="dialog_remove_recently_description">This will remove the read date of this chapter. Are you sure?</string>
|
||||
<string name="dialog_remove_recently_reset">Reset all chapters for this manga</string>
|
||||
|
||||
<!-- Image notifier -->
|
||||
<string name="picture_saved">Picture saved</string>
|
||||
<string name="saving_picture">Saving picture</string>
|
||||
<string name="options">Options</string>
|
||||
|
||||
<!-- Reader activity -->
|
||||
<string name="custom_filter">Custom filter</string>
|
||||
<string name="set_as_cover">Set as cover</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>
|
||||
@ -305,6 +312,7 @@
|
||||
<string name="notification_no_new_chapters">No new chapters found</string>
|
||||
<string name="notification_new_chapters">New chapters found for:</string>
|
||||
<string name="notification_manga_update_failed">Failed to update manga:</string>
|
||||
<string name="notification_cover_update_failed">Failed to update cover</string>
|
||||
<string name="notification_first_add_to_library">Please add the manga to your library before doing this</string>
|
||||
<string name="notification_not_connected_to_ac_title">Sync canceled</string>
|
||||
<string name="notification_not_connected_to_ac_body">Not connected to AC power</string>
|
||||
|
4
app/src/main/res/xml/provider_paths.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<paths>
|
||||
<external-path name="pictures" path="Pictures" />
|
||||
</paths>
|