Dependency update
This commit is contained in:
@@ -27,10 +27,7 @@ import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.github.piasy.biv.BigImageViewer
|
||||
import com.github.piasy.biv.loader.fresco.FrescoImageLoader
|
||||
import com.google.android.gms.common.GooglePlayServicesNotAvailableException
|
||||
import com.google.android.gms.common.GooglePlayServicesRepairableException
|
||||
import com.google.android.gms.security.ProviderInstaller
|
||||
@@ -117,8 +114,6 @@ class Pupil : Application(), DIAware {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
BigImageViewer.initialize(FrescoImageLoader.with(this))
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
|
||||
|
||||
@@ -1,238 +0,0 @@
|
||||
/*
|
||||
* Pupil, Hitomi.la viewer for Android
|
||||
* Copyright (C) 2019 tom5079
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package xyz.quaver.pupil.adapters
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.Animatable
|
||||
import android.net.Uri
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
||||
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
import android.widget.ImageView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
||||
import com.facebook.drawee.backends.pipeline.Fresco
|
||||
import com.facebook.drawee.controller.BaseControllerListener
|
||||
import com.facebook.drawee.drawable.ScalingUtils
|
||||
import com.facebook.drawee.interfaces.DraweeController
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import com.facebook.imagepipeline.image.ImageInfo
|
||||
import com.github.piasy.biv.view.BigImageView
|
||||
import com.github.piasy.biv.view.ImageShownCallback
|
||||
import com.github.piasy.biv.view.ImageViewFactory
|
||||
import xyz.quaver.pupil.R
|
||||
import xyz.quaver.pupil.databinding.ReaderItemBinding
|
||||
import java.io.File
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
data class ReaderItem(
|
||||
val progress: Float,
|
||||
val image: Uri?
|
||||
)
|
||||
|
||||
class ReaderAdapter : ListAdapter<ReaderItem, ReaderAdapter.ViewHolder>(ReaderItemDiffCallback()) {
|
||||
var onItemClickListener : (() -> (Unit))? = null
|
||||
var fullscreen = false
|
||||
|
||||
inner class ViewHolder(private val binding: ReaderItemBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||
init {
|
||||
with (binding.image) {
|
||||
setImageViewFactory(FrescoImageViewFactory().apply {
|
||||
updateView = { imageInfo ->
|
||||
if (!fullscreen) {
|
||||
binding.root.layoutParams.height = imageInfo.height
|
||||
layoutParams.height = imageInfo.height
|
||||
|
||||
(mainView as? SimpleDraweeView)?.aspectRatio = imageInfo.width / imageInfo.height.toFloat()
|
||||
}
|
||||
}
|
||||
})
|
||||
setImageShownCallback(object: ImageShownCallback {
|
||||
override fun onMainImageShown() {
|
||||
binding.progressGroup.visibility = View.INVISIBLE
|
||||
|
||||
binding.root.layoutParams.height = if (fullscreen)
|
||||
MATCH_PARENT
|
||||
else
|
||||
WRAP_CONTENT
|
||||
}
|
||||
|
||||
override fun onThumbnailShown() {}
|
||||
})
|
||||
|
||||
setFailureImage(ContextCompat.getDrawable(itemView.context, R.drawable.image_broken_variant))
|
||||
setOnClickListener {
|
||||
onItemClickListener?.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
binding.root.setOnClickListener {
|
||||
onItemClickListener?.invoke()
|
||||
}
|
||||
|
||||
binding.readerItemProgressbar.max = 100
|
||||
}
|
||||
|
||||
fun bind(position: Int) {
|
||||
recycle()
|
||||
|
||||
binding.root.layoutParams.height = MATCH_PARENT
|
||||
|
||||
binding.readerIndex.text = (position+1).toString()
|
||||
|
||||
val (progress, image) = getItem(position)
|
||||
|
||||
binding.progressGroup.visibility = View.VISIBLE
|
||||
|
||||
if (image != null) {
|
||||
binding.root.background = null
|
||||
binding.image.showImage(image)
|
||||
} else {
|
||||
binding.root.setBackgroundResource(R.drawable.reader_item_boundary)
|
||||
|
||||
if (progress == Float.NEGATIVE_INFINITY)
|
||||
binding.image.showImage(Uri.EMPTY)
|
||||
else
|
||||
binding.readerItemProgressbar.progress = progress.roundToInt()
|
||||
}
|
||||
}
|
||||
|
||||
fun recycle() {
|
||||
binding.image.mainView.run {
|
||||
when (this) {
|
||||
is SubsamplingScaleImageView -> recycle()
|
||||
is SimpleDraweeView -> recycle()
|
||||
is ImageView -> setImageBitmap(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
return ViewHolder(ReaderItemBinding.inflate(LayoutInflater.from(parent.context), parent, false))
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
holder.bind(position)
|
||||
}
|
||||
|
||||
override fun onViewRecycled(holder: ViewHolder) {
|
||||
super.onViewRecycled(holder)
|
||||
holder.recycle()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ReaderItemDiffCallback : DiffUtil.ItemCallback<ReaderItem>() {
|
||||
override fun areItemsTheSame(oldItem: ReaderItem, newItem: ReaderItem) =
|
||||
true
|
||||
|
||||
override fun areContentsTheSame(oldItem: ReaderItem, newItem: ReaderItem) =
|
||||
oldItem == newItem
|
||||
}
|
||||
|
||||
class FrescoImageViewFactory : ImageViewFactory() {
|
||||
var updateView: ((ImageInfo) -> Unit)? = null
|
||||
|
||||
override fun createAnimatedImageView(
|
||||
context: Context, imageType: Int,
|
||||
initScaleType: Int
|
||||
): View {
|
||||
val view = SimpleDraweeView(context)
|
||||
view.hierarchy.actualImageScaleType = scaleType(initScaleType)
|
||||
return view
|
||||
}
|
||||
|
||||
override fun loadAnimatedContent(
|
||||
view: View, imageType: Int,
|
||||
imageFile: File
|
||||
) {
|
||||
if (view is SimpleDraweeView) {
|
||||
val controller: DraweeController = Fresco.newDraweeControllerBuilder()
|
||||
.setOldController(view.controller)
|
||||
.setUri(Uri.parse("file://" + imageFile.absolutePath))
|
||||
.setAutoPlayAnimations(true)
|
||||
.setControllerListener(object: BaseControllerListener<ImageInfo>() {
|
||||
override fun onIntermediateImageSet(id: String?, imageInfo: ImageInfo?) {
|
||||
imageInfo?.let { updateView?.invoke(it) }
|
||||
}
|
||||
|
||||
override fun onFinalImageSet(id: String?, imageInfo: ImageInfo?, animatable: Animatable?) {
|
||||
imageInfo?.let { updateView?.invoke(it) }
|
||||
}
|
||||
})
|
||||
.build()
|
||||
view.controller = controller
|
||||
}
|
||||
}
|
||||
|
||||
override fun createThumbnailView(
|
||||
context: Context,
|
||||
scaleType: ImageView.ScaleType, willLoadFromNetwork: Boolean
|
||||
): View {
|
||||
return if (willLoadFromNetwork) {
|
||||
val thumbnailView = SimpleDraweeView(context)
|
||||
thumbnailView.hierarchy.actualImageScaleType = scaleType(scaleType)
|
||||
thumbnailView
|
||||
} else {
|
||||
super.createThumbnailView(context, scaleType, false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun loadThumbnailContent(view: View, thumbnail: Uri) {
|
||||
if (view is SimpleDraweeView) {
|
||||
val controller: DraweeController = Fresco.newDraweeControllerBuilder()
|
||||
.setOldController(view.controller)
|
||||
.setUri(thumbnail)
|
||||
.build()
|
||||
view.controller = controller
|
||||
}
|
||||
}
|
||||
|
||||
private fun scaleType(value: Int): ScalingUtils.ScaleType {
|
||||
return when (value) {
|
||||
BigImageView.INIT_SCALE_TYPE_CENTER -> ScalingUtils.ScaleType.CENTER
|
||||
BigImageView.INIT_SCALE_TYPE_CENTER_CROP -> ScalingUtils.ScaleType.CENTER_CROP
|
||||
BigImageView.INIT_SCALE_TYPE_CENTER_INSIDE -> ScalingUtils.ScaleType.CENTER_INSIDE
|
||||
BigImageView.INIT_SCALE_TYPE_FIT_END -> ScalingUtils.ScaleType.FIT_END
|
||||
BigImageView.INIT_SCALE_TYPE_FIT_START -> ScalingUtils.ScaleType.FIT_START
|
||||
BigImageView.INIT_SCALE_TYPE_FIT_XY -> ScalingUtils.ScaleType.FIT_XY
|
||||
BigImageView.INIT_SCALE_TYPE_FIT_CENTER -> ScalingUtils.ScaleType.FIT_CENTER
|
||||
else -> ScalingUtils.ScaleType.FIT_CENTER
|
||||
}
|
||||
}
|
||||
|
||||
private fun scaleType(scaleType: ImageView.ScaleType): ScalingUtils.ScaleType {
|
||||
return when (scaleType) {
|
||||
ImageView.ScaleType.CENTER -> ScalingUtils.ScaleType.CENTER
|
||||
ImageView.ScaleType.CENTER_CROP -> ScalingUtils.ScaleType.CENTER_CROP
|
||||
ImageView.ScaleType.CENTER_INSIDE -> ScalingUtils.ScaleType.CENTER_INSIDE
|
||||
ImageView.ScaleType.FIT_END -> ScalingUtils.ScaleType.FIT_END
|
||||
ImageView.ScaleType.FIT_START -> ScalingUtils.ScaleType.FIT_START
|
||||
ImageView.ScaleType.FIT_XY -> ScalingUtils.ScaleType.FIT_XY
|
||||
ImageView.ScaleType.FIT_CENTER -> ScalingUtils.ScaleType.FIT_CENTER
|
||||
else -> ScalingUtils.ScaleType.FIT_CENTER
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Pupil, Hitomi.la viewer for Android
|
||||
* Copyright (C) 2019 tom5079
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package xyz.quaver.pupil.adapters
|
||||
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.facebook.drawee.drawable.ScalingUtils
|
||||
import com.facebook.drawee.view.SimpleDraweeView
|
||||
import xyz.quaver.pupil.R
|
||||
|
||||
class ThumbnailAdapter(var thumbnails: List<String>) : RecyclerView.Adapter<ThumbnailAdapter.ViewHolder>() {
|
||||
|
||||
class ViewHolder(val view: SimpleDraweeView) : RecyclerView.ViewHolder(view) {
|
||||
|
||||
init {
|
||||
view.hierarchy.actualImageScaleType = ScalingUtils.ScaleType.FIT_CENTER
|
||||
}
|
||||
|
||||
fun bind(image: String) {
|
||||
view.setImageURI(image)
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
view.controller = null
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
return ViewHolder(SimpleDraweeView(parent.context).apply {
|
||||
layoutParams = ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
resources.getDimensionPixelSize(R.dimen.gallery_dialog_preview_height)
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
holder.bind(thumbnails[position])
|
||||
}
|
||||
|
||||
override fun getItemCount() = thumbnails.size
|
||||
|
||||
override fun onViewRecycled(holder: ViewHolder) {
|
||||
holder.clear()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Pupil, Hitomi.la viewer for Android
|
||||
* Copyright (C) 2020 tom5079
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package xyz.quaver.pupil.adapters
|
||||
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import kotlin.math.min
|
||||
|
||||
class ThumbnailPageAdapter(private val thumbnails: List<String>) : RecyclerView.Adapter<ThumbnailPageAdapter.ViewHolder>() {
|
||||
|
||||
class ViewHolder(val view: RecyclerView) : RecyclerView.ViewHolder(view)
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
return ViewHolder(RecyclerView(parent.context).apply {
|
||||
this.layoutManager = GridLayoutManager(parent.context, 3)
|
||||
this.adapter = ThumbnailAdapter(listOf())
|
||||
layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
|
||||
})
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
(holder.view.adapter as ThumbnailAdapter).apply {
|
||||
thumbnails = this@ThumbnailPageAdapter.thumbnails.slice(9*position until min(9*position+9, this@ThumbnailPageAdapter.thumbnails.size))
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount() = if (thumbnails.isEmpty()) 0 else thumbnails.size/9 + if (thumbnails.size%9 != 0) 1 else 0
|
||||
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
import org.kodein.di.*
|
||||
|
||||
@Database(entities = [History::class, Bookmark::class], version = 1)
|
||||
@Database(entities = [History::class, Bookmark::class], version = 1, exportSchema = false)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
abstract fun historyDao(): HistoryDao
|
||||
abstract fun bookmarkDao(): BookmarkDao
|
||||
|
||||
@@ -21,9 +21,6 @@ package xyz.quaver.pupil.sources
|
||||
import android.app.Application
|
||||
import android.os.Parcelable
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.lifecycle.*
|
||||
import io.ktor.http.*
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import org.kodein.di.*
|
||||
|
||||
@@ -19,11 +19,6 @@
|
||||
package xyz.quaver.pupil.sources
|
||||
|
||||
import android.app.Application
|
||||
import io.ktor.client.*
|
||||
import io.ktor.client.features.*
|
||||
import io.ktor.client.features.get
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.client.statement.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -52,6 +52,7 @@ import org.kodein.di.DIAware
|
||||
import org.kodein.di.android.closestDI
|
||||
import org.kodein.log.LoggerFactory
|
||||
import org.kodein.log.newLogger
|
||||
import xyz.quaver.graphics.subsampledimage.SubSampledImage
|
||||
import xyz.quaver.pupil.R
|
||||
import xyz.quaver.pupil.ui.composable.FloatingActionButtonState
|
||||
import xyz.quaver.pupil.ui.composable.MultipleFloatingActionButton
|
||||
@@ -134,29 +135,8 @@ class ReaderActivity : ComponentActivity(), DIAware {
|
||||
verticalArrangement = Arrangement.spacedBy(32.dp)
|
||||
) {
|
||||
items(images) { image ->
|
||||
Image(
|
||||
modifier = Modifier.fillMaxWidth().heightIn(128.dp, 1000.dp),
|
||||
painter = rememberImagePainter(
|
||||
ImageRequest.Builder(this@ReaderActivity)
|
||||
.data(image)
|
||||
.headers(
|
||||
Headers.headersOf(
|
||||
*(source!!.getHeadersForImage(model.itemID.value!!, image).entries.fold(arrayOf()) { acc, entry ->
|
||||
acc + entry.key + entry.value
|
||||
})
|
||||
).also {
|
||||
logger.debug {
|
||||
image
|
||||
}
|
||||
logger.debug {
|
||||
it.toString()
|
||||
}
|
||||
}
|
||||
)
|
||||
.transformations(BlurTransformation(this@ReaderActivity, 1f))
|
||||
.build()
|
||||
),
|
||||
contentDescription = null
|
||||
SubSampledImage(
|
||||
modifier = Modifier.fillMaxWidth().heightIn(128.dp, 1000.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,10 +21,7 @@ package xyz.quaver.pupil.ui.viewmodel
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
import androidx.lifecycle.*
|
||||
import io.ktor.client.request.*
|
||||
import kotlinx.coroutines.*
|
||||
import org.kodein.di.DIAware
|
||||
import org.kodein.di.android.x.closestDI
|
||||
@@ -32,12 +29,10 @@ import org.kodein.di.direct
|
||||
import org.kodein.di.instance
|
||||
import org.kodein.log.LoggerFactory
|
||||
import org.kodein.log.newLogger
|
||||
import xyz.quaver.pupil.adapters.ReaderItem
|
||||
import xyz.quaver.pupil.db.AppDatabase
|
||||
import xyz.quaver.pupil.db.Bookmark
|
||||
import xyz.quaver.pupil.db.History
|
||||
import xyz.quaver.pupil.sources.Source
|
||||
import xyz.quaver.pupil.util.notify
|
||||
import xyz.quaver.pupil.util.source
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@@ -66,9 +61,6 @@ class ReaderViewModel(app: Application) : AndroidViewModel(app), DIAware {
|
||||
private val _images = MutableLiveData<List<String>>()
|
||||
val images: LiveData<List<String>> = _images
|
||||
|
||||
private var _readerItems = MutableLiveData<MutableList<ReaderItem>>()
|
||||
val readerItems = _readerItems as LiveData<List<ReaderItem>>
|
||||
|
||||
val isBookmarked = Transformations.switchMap(MediatorLiveData<Pair<Source, String>>().apply {
|
||||
addSource(source) { source -> itemID.value?.let { itemID -> source to itemID } }
|
||||
addSource(itemID) { itemID -> source.value?.let { source -> source to itemID } }
|
||||
@@ -129,7 +121,7 @@ class ReaderViewModel(app: Application) : AndroidViewModel(app), DIAware {
|
||||
viewModelScope.launch {
|
||||
_images.postValue(withContext(Dispatchers.IO) {
|
||||
source.images(itemID)
|
||||
}!!)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user