Added horizontal view for ReaderActivity
Added page selector for ReaderActivity
This commit is contained in:
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/classes" />
|
<output url="file://$PROJECT_DIR$/classes" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@@ -40,6 +40,7 @@ dependencies {
|
|||||||
implementation 'androidx.appcompat:appcompat:1.0.2'
|
implementation 'androidx.appcompat:appcompat:1.0.2'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||||
implementation "ru.noties.markwon:core:${markwonVersion}"
|
implementation "ru.noties.markwon:core:${markwonVersion}"
|
||||||
|
implementation 'com.shawnlin:number-picker:2.4.8'
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
|
||||||
androidTestImplementation 'androidx.test:runner:1.1.1'
|
androidTestImplementation 'androidx.test:runner:1.1.1'
|
||||||
|
|||||||
@@ -38,12 +38,10 @@ import ru.noties.markwon.Markwon
|
|||||||
import xyz.quaver.hitomi.*
|
import xyz.quaver.hitomi.*
|
||||||
import xyz.quaver.pupil.adapters.GalleryBlockAdapter
|
import xyz.quaver.pupil.adapters.GalleryBlockAdapter
|
||||||
import xyz.quaver.pupil.types.TagSuggestion
|
import xyz.quaver.pupil.types.TagSuggestion
|
||||||
import xyz.quaver.pupil.util.Histories
|
import xyz.quaver.pupil.util.*
|
||||||
import xyz.quaver.pupil.util.SetLineOverlap
|
|
||||||
import xyz.quaver.pupil.util.checkUpdate
|
|
||||||
import xyz.quaver.pupil.util.getApkUrl
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
|
import java.lang.Exception
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.net.ssl.HttpsURLConnection
|
import javax.net.ssl.HttpsURLConnection
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
@@ -268,18 +266,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
private fun setupRecyclerView() {
|
private fun setupRecyclerView() {
|
||||||
with(main_recyclerview) {
|
with(main_recyclerview) {
|
||||||
adapter = GalleryBlockAdapter(galleries).apply {
|
adapter = GalleryBlockAdapter(galleries)
|
||||||
setClickListener { galleryID, title ->
|
|
||||||
val intent = Intent(this@MainActivity, ReaderActivity::class.java)
|
|
||||||
intent.putExtra("GALLERY_ID", galleryID)
|
|
||||||
intent.putExtra("GALLERY_TITLE", title)
|
|
||||||
|
|
||||||
//TODO: Maybe sprinke some transitions will be nice :D
|
|
||||||
startActivity(intent)
|
|
||||||
|
|
||||||
Histories.default.add(galleryID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
addOnScrollListener(
|
addOnScrollListener(
|
||||||
object: RecyclerView.OnScrollListener() {
|
object: RecyclerView.OnScrollListener() {
|
||||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||||
@@ -293,6 +280,17 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
ItemClickSupport.addTo(this).setOnItemClickListener { _, position, _ ->
|
||||||
|
val intent = Intent(this@MainActivity, ReaderActivity::class.java)
|
||||||
|
val gallery = galleries[position].first
|
||||||
|
intent.putExtra("GALLERY_ID", gallery.id)
|
||||||
|
intent.putExtra("GALLERY_TITLE", gallery.title)
|
||||||
|
|
||||||
|
//TODO: Maybe sprinke some transitions will be nice :D
|
||||||
|
startActivity(intent)
|
||||||
|
|
||||||
|
Histories.default.add(gallery.id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -485,38 +483,43 @@ class MainActivity : AppCompatActivity() {
|
|||||||
galleryIDs
|
galleryIDs
|
||||||
else ->
|
else ->
|
||||||
galleryIDs.slice(galleries.size until Math.min(galleries.size+perPage, galleryIDs.size))
|
galleryIDs.slice(galleries.size until Math.min(galleries.size+perPage, galleryIDs.size))
|
||||||
}.chunked(4).forEach { chunked ->
|
}.chunked(4).let { chunks ->
|
||||||
chunked.map {
|
for (chunk in chunks)
|
||||||
async {
|
chunk.map {
|
||||||
val galleryBlock = getGalleryBlock(it)
|
async {
|
||||||
|
try {
|
||||||
|
val galleryBlock = getGalleryBlock(it)
|
||||||
|
|
||||||
val thumbnail = async {
|
val thumbnail = async {
|
||||||
val cache = File(cacheDir, "imageCache/$it/thumbnail.${galleryBlock.thumbnails[0].path.split('.').last()}")
|
val cache = File(cacheDir, "imageCache/$it/thumbnail.${galleryBlock.thumbnails[0].path.split('.').last()}")
|
||||||
|
|
||||||
if (!cache.exists())
|
if (!cache.exists())
|
||||||
with(galleryBlock.thumbnails[0].openConnection() as HttpsURLConnection) {
|
with(galleryBlock.thumbnails[0].openConnection() as HttpsURLConnection) {
|
||||||
if (!cache.parentFile.exists())
|
if (!cache.parentFile.exists())
|
||||||
cache.parentFile.mkdirs()
|
cache.parentFile.mkdirs()
|
||||||
|
|
||||||
inputStream.copyTo(FileOutputStream(cache))
|
inputStream.copyTo(FileOutputStream(cache))
|
||||||
|
}
|
||||||
|
|
||||||
|
cache.absolutePath
|
||||||
}
|
}
|
||||||
|
|
||||||
cache.absolutePath
|
Pair(galleryBlock, thumbnail)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}.forEach {
|
||||||
|
val galleryBlock = it.await() ?: return@forEach
|
||||||
|
|
||||||
Pair(galleryBlock, thumbnail)
|
withContext(Dispatchers.Main) {
|
||||||
}
|
main_progressbar.hide()
|
||||||
}.forEach {
|
|
||||||
val galleryBlock = it.await()
|
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
galleries.add(galleryBlock)
|
||||||
main_progressbar.hide()
|
main_recyclerview.adapter?.notifyItemInserted(galleries.size - 1)
|
||||||
|
}
|
||||||
galleries.add(galleryBlock)
|
|
||||||
main_recyclerview.adapter?.notifyItemInserted(galleries.size - 1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,22 @@
|
|||||||
package xyz.quaver.pupil
|
package xyz.quaver.pupil
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.view.*
|
||||||
import android.view.ContextMenu
|
import androidx.appcompat.app.AlertDialog
|
||||||
import android.view.View
|
|
||||||
import android.view.WindowManager
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.PagerSnapHelper
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import kotlinx.android.synthetic.main.activity_reader.*
|
import kotlinx.android.synthetic.main.activity_reader.*
|
||||||
|
import kotlinx.android.synthetic.main.activity_reader.view.*
|
||||||
|
import kotlinx.android.synthetic.main.dialog_numberpicker.view.*
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import xyz.quaver.hitomi.Reader
|
import xyz.quaver.hitomi.Reader
|
||||||
import xyz.quaver.hitomi.getReader
|
import xyz.quaver.hitomi.getReader
|
||||||
import xyz.quaver.hitomi.getReferer
|
import xyz.quaver.hitomi.getReferer
|
||||||
import xyz.quaver.pupil.adapters.GalleryAdapter
|
import xyz.quaver.pupil.adapters.ReaderAdapter
|
||||||
|
import xyz.quaver.pupil.util.ItemClickSupport
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
@@ -22,12 +26,16 @@ class ReaderActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
private val images = ArrayList<String>()
|
private val images = ArrayList<String>()
|
||||||
private var galleryID = 0
|
private var galleryID = 0
|
||||||
|
private var gallerySize: Int = 0
|
||||||
|
private var currentPage: Int = 0
|
||||||
private lateinit var reader: Deferred<Reader>
|
private lateinit var reader: Deferred<Reader>
|
||||||
private var loadJob: Job? = null
|
private var loadJob: Job? = null
|
||||||
private var screenMode = 0
|
|
||||||
|
private lateinit var snapHelper: PagerSnapHelper
|
||||||
|
|
||||||
|
private var menu: Menu? = null
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
Log.d("Pupil", "Reader Opened")
|
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
window.setFlags(
|
window.setFlags(
|
||||||
@@ -41,12 +49,10 @@ class ReaderActivity : AppCompatActivity() {
|
|||||||
galleryID = intent.getIntExtra("GALLERY_ID", 0)
|
galleryID = intent.getIntExtra("GALLERY_ID", 0)
|
||||||
CoroutineScope(Dispatchers.Unconfined).launch {
|
CoroutineScope(Dispatchers.Unconfined).launch {
|
||||||
reader = async(Dispatchers.IO) {
|
reader = async(Dispatchers.IO) {
|
||||||
Log.d("Pupil", "Loading reader")
|
|
||||||
val preference = PreferenceManager.getDefaultSharedPreferences(this@ReaderActivity)
|
val preference = PreferenceManager.getDefaultSharedPreferences(this@ReaderActivity)
|
||||||
if (preference.getBoolean("use_hiyobi", false)) {
|
if (preference.getBoolean("use_hiyobi", false)) {
|
||||||
try {
|
try {
|
||||||
xyz.quaver.hiyobi.getReader(galleryID)
|
xyz.quaver.hiyobi.getReader(galleryID)
|
||||||
Log.d("Pupil", "Using Hiyobi.me")
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
getReader(galleryID)
|
getReader(galleryID)
|
||||||
}
|
}
|
||||||
@@ -55,13 +61,36 @@ class ReaderActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
snapHelper = PagerSnapHelper()
|
||||||
|
|
||||||
|
val preferences = PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
|
|
||||||
|
val attrs = window.attributes
|
||||||
|
|
||||||
|
if (preferences.getBoolean("reader_fullscreen", false)) {
|
||||||
|
attrs.flags = attrs.flags or WindowManager.LayoutParams.FLAG_FULLSCREEN
|
||||||
|
supportActionBar?.hide()
|
||||||
|
} else {
|
||||||
|
attrs.flags = attrs.flags and WindowManager.LayoutParams.FLAG_FULLSCREEN.inv()
|
||||||
|
supportActionBar?.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
window.attributes = attrs
|
||||||
|
|
||||||
|
if (preferences.getBoolean("reader_one_by_one", false)) {
|
||||||
|
snapHelper.attachToRecyclerView(reader_recyclerview)
|
||||||
|
reader_recyclerview.layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
|
||||||
|
} else {
|
||||||
|
snapHelper.attachToRecyclerView(null)
|
||||||
|
reader_recyclerview.layoutManager = LinearLayoutManager(this)
|
||||||
|
}
|
||||||
|
|
||||||
initView()
|
initView()
|
||||||
Log.d("Pupil", "Reader view init complete")
|
|
||||||
loadImages()
|
loadImages()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
val preferences = android.preference.PreferenceManager.getDefaultSharedPreferences(this)
|
val preferences = PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
|
|
||||||
if (preferences.getBoolean("security_mode", false))
|
if (preferences.getBoolean("security_mode", false))
|
||||||
window.setFlags(
|
window.setFlags(
|
||||||
@@ -69,37 +98,96 @@ class ReaderActivity : AppCompatActivity() {
|
|||||||
WindowManager.LayoutParams.FLAG_SECURE)
|
WindowManager.LayoutParams.FLAG_SECURE)
|
||||||
else
|
else
|
||||||
window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
|
window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
|
||||||
|
|
||||||
super.onResume()
|
super.onResume()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
||||||
|
menuInflater.inflate(R.menu.reader, menu)
|
||||||
|
this.menu = menu
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
|
||||||
|
when(item?.itemId) {
|
||||||
|
R.id.reader_menu_page_indicator -> {
|
||||||
|
val view = LayoutInflater.from(this).inflate(R.layout.dialog_numberpicker, findViewById(android.R.id.content), false)
|
||||||
|
val dialog = AlertDialog.Builder(this).apply {
|
||||||
|
setView(view)
|
||||||
|
with(view.reader_dialog_number_picker) {
|
||||||
|
minValue=1
|
||||||
|
maxValue=gallerySize
|
||||||
|
value=currentPage
|
||||||
|
}
|
||||||
|
}.create()
|
||||||
|
view.reader_dialog_ok.setOnClickListener {
|
||||||
|
(reader_recyclerview.layoutManager as LinearLayoutManager?)?.scrollToPositionWithOffset(view.reader_dialog_number_picker.value-1, 0)
|
||||||
|
dialog.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
loadJob?.cancel()
|
loadJob?.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateContextMenu(menu: ContextMenu?, v: View?, menuInfo: ContextMenu.ContextMenuInfo?) {
|
|
||||||
super.onCreateContextMenu(menu, v, menuInfo)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initView() {
|
private fun initView() {
|
||||||
reader_recyclerview.adapter = GalleryAdapter(images).apply {
|
with(reader_recyclerview) {
|
||||||
setOnClick {
|
adapter = ReaderAdapter(images)
|
||||||
val attrs = window.attributes
|
|
||||||
|
|
||||||
screenMode = (screenMode+1)%2
|
addOnScrollListener(object: RecyclerView.OnScrollListener() {
|
||||||
|
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||||
|
super.onScrolled(recyclerView, dx, dy)
|
||||||
|
|
||||||
when(screenMode) {
|
val layoutManager = recyclerView.layoutManager as LinearLayoutManager
|
||||||
0 -> {
|
|
||||||
|
if (layoutManager.findFirstVisibleItemPosition() == -1)
|
||||||
|
return
|
||||||
|
currentPage = layoutManager.findFirstVisibleItemPosition()+1
|
||||||
|
menu?.findItem(R.id.reader_menu_page_indicator)?.title = "$currentPage/$gallerySize"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
ItemClickSupport.addTo(this)
|
||||||
|
.setOnItemClickListener { _, _, _ ->
|
||||||
|
val attrs = window.attributes
|
||||||
|
val fullscreen = preferences.getBoolean("reader_fullscreen", false)
|
||||||
|
|
||||||
|
if (fullscreen) {
|
||||||
attrs.flags = attrs.flags and WindowManager.LayoutParams.FLAG_FULLSCREEN.inv()
|
attrs.flags = attrs.flags and WindowManager.LayoutParams.FLAG_FULLSCREEN.inv()
|
||||||
supportActionBar?.show()
|
supportActionBar?.show()
|
||||||
}
|
} else {
|
||||||
1 -> {
|
|
||||||
attrs.flags = attrs.flags or WindowManager.LayoutParams.FLAG_FULLSCREEN
|
attrs.flags = attrs.flags or WindowManager.LayoutParams.FLAG_FULLSCREEN
|
||||||
supportActionBar?.hide()
|
supportActionBar?.hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
window.attributes = attrs
|
||||||
|
|
||||||
|
preferences.edit().putBoolean("reader_fullscreen", !fullscreen).apply()
|
||||||
|
}.setOnItemLongClickListener { _, _, _ ->
|
||||||
|
val oneByOne = preferences.getBoolean("reader_one_by_one", false)
|
||||||
|
if (oneByOne) {
|
||||||
|
snapHelper.attachToRecyclerView(null)
|
||||||
|
reader_recyclerview.layoutManager = LinearLayoutManager(context)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
snapHelper.attachToRecyclerView(reader_recyclerview)
|
||||||
|
reader_recyclerview.layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
(reader_recyclerview.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(currentPage, 0)
|
||||||
|
|
||||||
|
preferences.edit().putBoolean("reader_one_by_one", !oneByOne).apply()
|
||||||
|
|
||||||
|
true
|
||||||
}
|
}
|
||||||
window.attributes = attrs
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,11 +195,8 @@ class ReaderActivity : AppCompatActivity() {
|
|||||||
fun webpUrlFromUrl(url: URL) = URL(url.toString().replace("/galleries/", "/webp/") + ".webp")
|
fun webpUrlFromUrl(url: URL) = URL(url.toString().replace("/galleries/", "/webp/") + ".webp")
|
||||||
|
|
||||||
loadJob = CoroutineScope(Dispatchers.Default).launch {
|
loadJob = CoroutineScope(Dispatchers.Default).launch {
|
||||||
Log.d("Pupil", "Reader Waiting for the data")
|
|
||||||
val reader = reader.await()
|
val reader = reader.await()
|
||||||
|
|
||||||
Log.d("Pupil", "Reader Data recieved")
|
|
||||||
|
|
||||||
launch(Dispatchers.Main) {
|
launch(Dispatchers.Main) {
|
||||||
with(reader_progressbar) {
|
with(reader_progressbar) {
|
||||||
max = reader.size
|
max = reader.size
|
||||||
@@ -119,6 +204,9 @@ class ReaderActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
visibility = View.VISIBLE
|
visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gallerySize = reader.size
|
||||||
|
menu?.findItem(R.id.reader_menu_page_indicator)?.title = "$currentPage/$gallerySize"
|
||||||
}
|
}
|
||||||
|
|
||||||
reader.chunked(8).forEach { chunked ->
|
reader.chunked(8).forEach { chunked ->
|
||||||
|
|||||||
@@ -36,11 +36,6 @@ class GalleryBlockAdapter(private val galleries: List<Pair<GalleryBlock, Deferre
|
|||||||
class ViewHolder(val view: CardView) : RecyclerView.ViewHolder(view)
|
class ViewHolder(val view: CardView) : RecyclerView.ViewHolder(view)
|
||||||
class ProgressViewHolder(view: LinearLayout) : RecyclerView.ViewHolder(view)
|
class ProgressViewHolder(view: LinearLayout) : RecyclerView.ViewHolder(view)
|
||||||
|
|
||||||
private var callback: ((Int, String) -> Unit)? = null
|
|
||||||
fun setClickListener(callback: ((Int, String) -> Unit)?) {
|
|
||||||
this.callback = callback
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||||
when(viewType) {
|
when(viewType) {
|
||||||
ViewType.VIEW_ITEM.ordinal -> {
|
ViewType.VIEW_ITEM.ordinal -> {
|
||||||
@@ -76,10 +71,6 @@ class GalleryBlockAdapter(private val galleries: List<Pair<GalleryBlock, Deferre
|
|||||||
val artists = gallery.artists
|
val artists = gallery.artists
|
||||||
val series = gallery.series
|
val series = gallery.series
|
||||||
|
|
||||||
setOnClickListener {
|
|
||||||
callback?.invoke(gallery.id, gallery.title)
|
|
||||||
}
|
|
||||||
|
|
||||||
CoroutineScope(Dispatchers.Default).launch {
|
CoroutineScope(Dispatchers.Default).launch {
|
||||||
val bitmap = BitmapFactory.decodeFile(thumbnail.await())
|
val bitmap = BitmapFactory.decodeFile(thumbnail.await())
|
||||||
|
|
||||||
|
|||||||
@@ -1,39 +1,31 @@
|
|||||||
package xyz.quaver.pupil.adapters
|
package xyz.quaver.pupil.adapters
|
||||||
|
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import android.util.Log
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import kotlinx.android.synthetic.main.item_reader.view.*
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import xyz.quaver.pupil.R
|
import xyz.quaver.pupil.R
|
||||||
|
|
||||||
class GalleryAdapter(private val images: List<String>) : RecyclerView.Adapter<GalleryAdapter.ViewHolder>() {
|
class ReaderAdapter(private val images: List<String>) : RecyclerView.Adapter<ReaderAdapter.ViewHolder>() {
|
||||||
|
|
||||||
class ViewHolder(val view: ImageView) : RecyclerView.ViewHolder(view)
|
class ViewHolder(val view: View) : RecyclerView.ViewHolder(view)
|
||||||
|
|
||||||
private var onClick: (() -> Unit)? = null
|
|
||||||
fun setOnClick(callback: (() -> Unit)?) {
|
|
||||||
this.onClick = callback
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
LayoutInflater.from(parent.context).inflate(
|
LayoutInflater.from(parent.context).inflate(
|
||||||
R.layout.item_gallery, parent, false
|
R.layout.item_reader, parent, false
|
||||||
).let {
|
).let {
|
||||||
return ViewHolder(it as ImageView)
|
return ViewHolder(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
with(holder.view) {
|
with(holder.view as ImageView) {
|
||||||
setOnClickListener {
|
|
||||||
onClick?.invoke()
|
|
||||||
}
|
|
||||||
|
|
||||||
CoroutineScope(Dispatchers.Default).launch {
|
CoroutineScope(Dispatchers.Default).launch {
|
||||||
val options = BitmapFactory.Options()
|
val options = BitmapFactory.Options()
|
||||||
|
|
||||||
107
app/src/main/java/xyz/quaver/pupil/util/ItemClickSupport.java
Normal file
107
app/src/main/java/xyz/quaver/pupil/util/ItemClickSupport.java
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
package xyz.quaver.pupil.util;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import xyz.quaver.pupil.R;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Source: http://www.littlerobots.nl/blog/Handle-Android-RecyclerView-Clicks/
|
||||||
|
USAGE:
|
||||||
|
|
||||||
|
ItemClickSupport.addTo(mRecyclerView).setOnItemClickListener(new ItemClickSupport.OnItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemClicked(RecyclerView recyclerView, int position, View v) {
|
||||||
|
// do it
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
*/
|
||||||
|
public class ItemClickSupport {
|
||||||
|
private final RecyclerView mRecyclerView;
|
||||||
|
private OnItemClickListener mOnItemClickListener;
|
||||||
|
private OnItemLongClickListener mOnItemLongClickListener;
|
||||||
|
private View.OnClickListener mOnClickListener = new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (mOnItemClickListener != null) {
|
||||||
|
RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
|
||||||
|
mOnItemClickListener.onItemClicked(mRecyclerView, holder.getAdapterPosition(), v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private View.OnLongClickListener mOnLongClickListener = new View.OnLongClickListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onLongClick(View v) {
|
||||||
|
if (mOnItemLongClickListener != null) {
|
||||||
|
RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
|
||||||
|
return mOnItemLongClickListener.onItemLongClicked(mRecyclerView, holder.getAdapterPosition(), v);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private RecyclerView.OnChildAttachStateChangeListener mAttachListener
|
||||||
|
= new RecyclerView.OnChildAttachStateChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onChildViewAttachedToWindow(@NonNull View view) {
|
||||||
|
if (mOnItemClickListener != null) {
|
||||||
|
view.setOnClickListener(mOnClickListener);
|
||||||
|
}
|
||||||
|
if (mOnItemLongClickListener != null) {
|
||||||
|
view.setOnLongClickListener(mOnLongClickListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChildViewDetachedFromWindow(@NonNull View view) {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private ItemClickSupport(RecyclerView recyclerView) {
|
||||||
|
mRecyclerView = recyclerView;
|
||||||
|
mRecyclerView.setTag(R.id.item_click_support, this);
|
||||||
|
mRecyclerView.addOnChildAttachStateChangeListener(mAttachListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ItemClickSupport addTo(RecyclerView view) {
|
||||||
|
ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
|
||||||
|
if (support == null) {
|
||||||
|
support = new ItemClickSupport(view);
|
||||||
|
}
|
||||||
|
return support;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ItemClickSupport removeFrom(RecyclerView view) {
|
||||||
|
ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
|
||||||
|
if (support != null) {
|
||||||
|
support.detach(view);
|
||||||
|
}
|
||||||
|
return support;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemClickSupport setOnItemClickListener(OnItemClickListener listener) {
|
||||||
|
mOnItemClickListener = listener;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemClickSupport setOnItemLongClickListener(OnItemLongClickListener listener) {
|
||||||
|
mOnItemLongClickListener = listener;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void detach(RecyclerView view) {
|
||||||
|
view.removeOnChildAttachStateChangeListener(mAttachListener);
|
||||||
|
view.setTag(R.id.item_click_support, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface OnItemClickListener {
|
||||||
|
|
||||||
|
void onItemClicked(RecyclerView recyclerView, int position, View v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface OnItemLongClickListener {
|
||||||
|
|
||||||
|
boolean onItemLongClicked(RecyclerView recyclerView, int position, View v);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -50,13 +50,13 @@
|
|||||||
android:id="@+id/main_swipe_layout"
|
android:id="@+id/main_swipe_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginBottom="-64dp">
|
android:layout_marginBottom="-80dp">
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/main_recyclerview"
|
android:id="@+id/main_recyclerview"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:paddingTop="64dp"
|
android:paddingTop="80dp"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:scrollbars="vertical"
|
android:scrollbars="vertical"
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
|
||||||
|
|||||||
@@ -1,15 +1,22 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context=".ReaderActivity">
|
tools:context=".ReaderActivity">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/reader_recyclerview"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/reader_framelayout"
|
android:id="@+id/reader_framelayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="4dp">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/reader_progressbar"
|
android:id="@+id/reader_progressbar"
|
||||||
@@ -20,11 +27,4 @@
|
|||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
android:id="@+id/reader_recyclerview"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_below="@id/reader_framelayout"
|
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
35
app/src/main/res/layout/dialog_numberpicker.xml
Normal file
35
app/src/main/res/layout/dialog_numberpicker.xml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="?android:textAppearanceLarge"
|
||||||
|
android:id="@+id/reader_dialog_title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/reader_go_to_page"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"/>
|
||||||
|
|
||||||
|
<NumberPicker
|
||||||
|
android:id="@+id/reader_dialog_number_picker"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/reader_dialog_title"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/reader_dialog_ok"
|
||||||
|
style="?borderlessButtonStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@android:string/ok"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/reader_dialog_number_picker"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"/>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
@@ -4,6 +4,5 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingBottom="8dp"
|
android:paddingBottom="8dp"
|
||||||
android:adjustViewBounds="true"
|
android:scaleType="fitCenter"
|
||||||
android:clickable="true"
|
android:adjustViewBounds="true"/>
|
||||||
android:focusable="true"/>
|
|
||||||
9
app/src/main/res/menu/reader.xml
Normal file
9
app/src/main/res/menu/reader.xml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item android:id="@+id/reader_menu_page_indicator"
|
||||||
|
android:title="@string/reader_page_indicator_placeholder"
|
||||||
|
app:showAsAction="always|withText"/>
|
||||||
|
|
||||||
|
</menu>
|
||||||
@@ -30,4 +30,5 @@
|
|||||||
<string name="update_release_note"># リリースノート(v%1$s)\n%2$s</string>
|
<string name="update_release_note"># リリースノート(v%1$s)\n%2$s</string>
|
||||||
<string name="settings_security_mode_title">セキュリティーモード</string>
|
<string name="settings_security_mode_title">セキュリティーモード</string>
|
||||||
<string name="settings_security_mode_summary">アプリ履歴でアプリの画面を表示しない</string>
|
<string name="settings_security_mode_summary">アプリ履歴でアプリの画面を表示しない</string>
|
||||||
|
<string name="reader_go_to_page">移動</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -30,4 +30,5 @@
|
|||||||
<string name="update_release_note"># 릴리즈 노트(v%1$s)\n%2$s</string>
|
<string name="update_release_note"># 릴리즈 노트(v%1$s)\n%2$s</string>
|
||||||
<string name="settings_security_mode_summary">최근 앱 목록 창에서 앱 화면을 보이지 않게 합니다</string>
|
<string name="settings_security_mode_summary">최근 앱 목록 창에서 앱 화면을 보이지 않게 합니다</string>
|
||||||
<string name="settings_security_mode_title">보안 모드 활성화</string>
|
<string name="settings_security_mode_title">보안 모드 활성화</string>
|
||||||
|
<string name="reader_go_to_page">이동</string>
|
||||||
</resources>
|
</resources>
|
||||||
4
app/src/main/res/values/ids.xml
Normal file
4
app/src/main/res/values/ids.xml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<item name="item_click_support" type="id" />
|
||||||
|
</resources>
|
||||||
@@ -8,6 +8,9 @@
|
|||||||
<string name="galleryblock_thumbnail_description" translatable="false">Thumbnail</string>
|
<string name="galleryblock_thumbnail_description" translatable="false">Thumbnail</string>
|
||||||
|
|
||||||
<string name="reader_imageview_description" translatable="false">Content ImageView</string>
|
<string name="reader_imageview_description" translatable="false">Content ImageView</string>
|
||||||
|
<string name="reader_page_indicator_placeholder" translatable="false">-/-</string>
|
||||||
|
|
||||||
|
<string name="plus_to_close" translatable="false">Fab</string>
|
||||||
|
|
||||||
<!-- Translate needed down here -->
|
<!-- Translate needed down here -->
|
||||||
|
|
||||||
@@ -32,6 +35,8 @@
|
|||||||
<string name="galleryblock_type">Type: %1$s</string>
|
<string name="galleryblock_type">Type: %1$s</string>
|
||||||
<string name="galleryblock_language">Language: %1$s</string>
|
<string name="galleryblock_language">Language: %1$s</string>
|
||||||
|
|
||||||
|
<string name="reader_go_to_page">Go to page</string>
|
||||||
|
|
||||||
<string name="settings_title">Settings</string>
|
<string name="settings_title">Settings</string>
|
||||||
<string name="settings_search_title">Search Settings</string>
|
<string name="settings_search_title">Search Settings</string>
|
||||||
<string name="settings_galleries_per_page">Galleries per page</string>
|
<string name="settings_galleries_per_page">Galleries per page</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user