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_7" project-jdk-name="1.8 (2)" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/classes" />
|
<output url="file://$PROJECT_DIR$/classes" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@@ -9,8 +9,8 @@ android {
|
|||||||
applicationId "xyz.quaver.pupil"
|
applicationId "xyz.quaver.pupil"
|
||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
versionCode 5
|
versionCode 8
|
||||||
versionName "1.4"
|
versionName "2.2"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
@@ -38,6 +38,7 @@ dependencies {
|
|||||||
implementation 'androidx.preference:preference:1.1.0-alpha05'
|
implementation 'androidx.preference:preference:1.1.0-alpha05'
|
||||||
implementation 'com.google.android.material:material:1.0.0'
|
implementation 'com.google.android.material:material:1.0.0'
|
||||||
implementation 'com.github.arimorty:floatingsearchview:2.1.1'
|
implementation 'com.github.arimorty:floatingsearchview:2.1.1'
|
||||||
|
implementation 'com.github.deano2390:MaterialShowcaseView:1.3.4'
|
||||||
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}"
|
||||||
|
|||||||
@@ -6,16 +6,17 @@ import android.os.Bundle
|
|||||||
import android.preference.PreferenceManager
|
import android.preference.PreferenceManager
|
||||||
import android.text.*
|
import android.text.*
|
||||||
import android.text.style.AlignmentSpan
|
import android.text.style.AlignmentSpan
|
||||||
import android.view.LayoutInflater
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.*
|
||||||
import android.view.WindowManager
|
import android.widget.EditText
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.LinearLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.cardview.widget.CardView
|
||||||
import androidx.core.content.res.ResourcesCompat
|
import androidx.core.content.res.ResourcesCompat
|
||||||
import androidx.core.view.GravityCompat
|
import androidx.core.view.GravityCompat
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import com.arlib.floatingsearchview.FloatingSearchView
|
import com.arlib.floatingsearchview.FloatingSearchView
|
||||||
import com.arlib.floatingsearchview.suggestions.model.SearchSuggestion
|
import com.arlib.floatingsearchview.suggestions.model.SearchSuggestion
|
||||||
import com.arlib.floatingsearchview.util.view.SearchInputView
|
import com.arlib.floatingsearchview.util.view.SearchInputView
|
||||||
@@ -39,107 +40,64 @@ import java.net.URL
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.net.ssl.HttpsURLConnection
|
import javax.net.ssl.HttpsURLConnection
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
enum class Mode {
|
||||||
|
SEARCH,
|
||||||
|
HISTORY,
|
||||||
|
DOWNLOAD
|
||||||
|
}
|
||||||
|
|
||||||
private val galleries = ArrayList<Pair<GalleryBlock, Deferred<String>>>()
|
private val galleries = ArrayList<Pair<GalleryBlock, Deferred<String>>>()
|
||||||
|
|
||||||
private var query = ""
|
private var query = ""
|
||||||
|
private var mode = Mode.SEARCH
|
||||||
|
|
||||||
private val SETTINGS = 45162
|
private val SETTINGS = 45162
|
||||||
|
|
||||||
private var galleryIDs: Deferred<List<Int>>? = null
|
private var galleryIDs: Deferred<List<Int>>? = null
|
||||||
|
private var totalItems = 0
|
||||||
private var loadingJob: Job? = null
|
private var loadingJob: Job? = null
|
||||||
|
private var currentPage = 0
|
||||||
|
|
||||||
|
private lateinit var histories: Histories
|
||||||
|
private lateinit var downloads: Histories
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
Histories.default = Histories(File(cacheDir, "histories.json"))
|
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
window.setFlags(
|
val preference = PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
|
|
||||||
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
|
if (Locale.getDefault().language == "ko") {
|
||||||
)
|
if (!preference.getBoolean("https_block_alert", false)) {
|
||||||
|
android.app.AlertDialog.Builder(this).apply {
|
||||||
|
setTitle(R.string.https_block_alert_title)
|
||||||
|
setMessage(R.string.https_block_alert)
|
||||||
|
setPositiveButton(android.R.string.ok) { _, _ -> }
|
||||||
|
}.show()
|
||||||
|
|
||||||
|
preference.edit().putBoolean("https_block_alert", true).apply()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
with(application as Pupil) {
|
||||||
|
this@MainActivity.histories = histories
|
||||||
|
this@MainActivity.downloads = downloads
|
||||||
|
}
|
||||||
|
|
||||||
setContentView(R.layout.activity_main)
|
setContentView(R.layout.activity_main)
|
||||||
|
|
||||||
checkUpdate()
|
checkUpdate()
|
||||||
|
|
||||||
main_appbar_layout.addOnOffsetChangedListener(
|
initView()
|
||||||
AppBarLayout.OnOffsetChangedListener { _, p1 ->
|
|
||||||
main_searchview.translationY = p1.toFloat()
|
|
||||||
main_recyclerview.translationY = p1.toFloat()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
with(main_swipe_layout) {
|
|
||||||
setProgressViewOffset(
|
|
||||||
false,
|
|
||||||
resources.getDimensionPixelSize(R.dimen.progress_view_start),
|
|
||||||
resources.getDimensionPixelSize(R.dimen.progress_view_offset)
|
|
||||||
)
|
|
||||||
|
|
||||||
setOnRefreshListener {
|
|
||||||
CoroutineScope(Dispatchers.Main).launch {
|
|
||||||
cancelFetch()
|
|
||||||
clearGalleries()
|
|
||||||
fetchGalleries(query)
|
|
||||||
loadBlocks()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
main_nav_view.setNavigationItemSelectedListener {
|
|
||||||
CoroutineScope(Dispatchers.Main).launch {
|
|
||||||
main_drawer_layout.closeDrawers()
|
|
||||||
|
|
||||||
when(it.itemId) {
|
|
||||||
R.id.main_drawer_home -> {
|
|
||||||
cancelFetch()
|
|
||||||
clearGalleries()
|
|
||||||
query = query.replace("HISTORY", "")
|
|
||||||
fetchGalleries(query)
|
|
||||||
}
|
|
||||||
R.id.main_drawer_history -> {
|
|
||||||
cancelFetch()
|
|
||||||
clearGalleries()
|
|
||||||
query += "HISTORY"
|
|
||||||
fetchGalleries(query)
|
|
||||||
}
|
|
||||||
R.id.main_drawer_help -> {
|
|
||||||
AlertDialog.Builder(this@MainActivity).apply {
|
|
||||||
title = getString(R.string.help_dialog_title)
|
|
||||||
setMessage(R.string.help_dialog_message)
|
|
||||||
|
|
||||||
setPositiveButton(android.R.string.ok) { _, _ -> }
|
|
||||||
}.show()
|
|
||||||
}
|
|
||||||
R.id.main_drawer_github -> {
|
|
||||||
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.github))))
|
|
||||||
}
|
|
||||||
R.id.main_drawer_homepage -> {
|
|
||||||
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.home_page))))
|
|
||||||
}
|
|
||||||
R.id.main_drawer_email -> {
|
|
||||||
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.email))))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
loadBlocks()
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
setupSearchBar()
|
|
||||||
setupRecyclerView()
|
|
||||||
fetchGalleries(query)
|
|
||||||
loadBlocks()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBackPressed() {
|
override fun onBackPressed() {
|
||||||
if (main_drawer_layout.isDrawerOpen(GravityCompat.START))
|
when {
|
||||||
main_drawer_layout.closeDrawer(GravityCompat.START)
|
main_drawer_layout.isDrawerOpen(GravityCompat.START) -> main_drawer_layout.closeDrawer(GravityCompat.START)
|
||||||
else if (query.isNotEmpty()) {
|
query.isNotEmpty() -> runOnUiThread {
|
||||||
runOnUiThread {
|
|
||||||
query = ""
|
query = ""
|
||||||
findViewById<SearchInputView>(R.id.search_bar_text).setText(query, TextView.BufferType.EDITABLE)
|
findViewById<SearchInputView>(R.id.search_bar_text).setText(query, TextView.BufferType.EDITABLE)
|
||||||
|
|
||||||
@@ -148,9 +106,8 @@ class MainActivity : AppCompatActivity() {
|
|||||||
fetchGalleries(query)
|
fetchGalleries(query)
|
||||||
loadBlocks()
|
loadBlocks()
|
||||||
}
|
}
|
||||||
|
else -> super.onBackPressed()
|
||||||
}
|
}
|
||||||
else
|
|
||||||
super.onBackPressed()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
@@ -165,6 +122,44 @@ class MainActivity : AppCompatActivity() {
|
|||||||
super.onResume()
|
super.onResume()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
|
||||||
|
val preference = PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
|
val perPage = preference.getString("per_page", "25")!!.toInt()
|
||||||
|
val maxPage = Math.ceil(totalItems / perPage.toDouble()).roundToInt()
|
||||||
|
|
||||||
|
return when(keyCode) {
|
||||||
|
KeyEvent.KEYCODE_VOLUME_DOWN -> {
|
||||||
|
if (currentPage < maxPage) {
|
||||||
|
runOnUiThread {
|
||||||
|
currentPage++
|
||||||
|
|
||||||
|
cancelFetch()
|
||||||
|
clearGalleries()
|
||||||
|
fetchGalleries(query)
|
||||||
|
loadBlocks()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
KeyEvent.KEYCODE_VOLUME_UP -> {
|
||||||
|
if (currentPage > 0) {
|
||||||
|
runOnUiThread {
|
||||||
|
currentPage--
|
||||||
|
|
||||||
|
cancelFetch()
|
||||||
|
clearGalleries()
|
||||||
|
fetchGalleries(query)
|
||||||
|
loadBlocks()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else -> super.onKeyDown(keyCode, event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
super.onActivityResult(requestCode, resultCode, data)
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
when(requestCode) {
|
when(requestCode) {
|
||||||
@@ -243,11 +238,81 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun initView() {
|
||||||
|
var prevP1 = 0
|
||||||
|
main_appbar_layout.addOnOffsetChangedListener(
|
||||||
|
AppBarLayout.OnOffsetChangedListener { _, p1 ->
|
||||||
|
main_searchview.translationY = p1.toFloat()
|
||||||
|
main_recyclerview.scrollBy(0, prevP1 - p1)
|
||||||
|
|
||||||
|
prevP1 = p1
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
//NavigationView
|
||||||
|
main_nav_view.setNavigationItemSelectedListener {
|
||||||
|
runOnUiThread {
|
||||||
|
main_drawer_layout.closeDrawers()
|
||||||
|
|
||||||
|
when(it.itemId) {
|
||||||
|
R.id.main_drawer_home -> {
|
||||||
|
cancelFetch()
|
||||||
|
clearGalleries()
|
||||||
|
query = ""
|
||||||
|
mode = Mode.SEARCH
|
||||||
|
fetchGalleries(query)
|
||||||
|
loadBlocks()
|
||||||
|
}
|
||||||
|
R.id.main_drawer_history -> {
|
||||||
|
cancelFetch()
|
||||||
|
clearGalleries()
|
||||||
|
query = ""
|
||||||
|
mode = Mode.HISTORY
|
||||||
|
fetchGalleries(query)
|
||||||
|
loadBlocks()
|
||||||
|
}
|
||||||
|
R.id.main_drawer_downloads -> {
|
||||||
|
cancelFetch()
|
||||||
|
clearGalleries()
|
||||||
|
query = ""
|
||||||
|
mode = Mode.DOWNLOAD
|
||||||
|
fetchGalleries(query)
|
||||||
|
loadBlocks()
|
||||||
|
}
|
||||||
|
R.id.main_drawer_help -> {
|
||||||
|
AlertDialog.Builder(this@MainActivity).apply {
|
||||||
|
title = getString(R.string.help_dialog_title)
|
||||||
|
setMessage(R.string.help_dialog_message)
|
||||||
|
|
||||||
|
setPositiveButton(android.R.string.ok) { _, _ -> }
|
||||||
|
}.show()
|
||||||
|
}
|
||||||
|
R.id.main_drawer_github -> {
|
||||||
|
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.github))))
|
||||||
|
}
|
||||||
|
R.id.main_drawer_homepage -> {
|
||||||
|
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.home_page))))
|
||||||
|
}
|
||||||
|
R.id.main_drawer_email -> {
|
||||||
|
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.email))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
setupSearchBar()
|
||||||
|
setupRecyclerView()
|
||||||
|
fetchGalleries(query)
|
||||||
|
loadBlocks()
|
||||||
|
}
|
||||||
|
|
||||||
private fun setupRecyclerView() {
|
private fun setupRecyclerView() {
|
||||||
with(main_recyclerview) {
|
with(main_recyclerview) {
|
||||||
adapter = GalleryBlockAdapter(galleries).apply {
|
adapter = GalleryBlockAdapter(galleries).apply {
|
||||||
onChipClickedHandler.add {
|
onChipClickedHandler.add {
|
||||||
post {
|
runOnUiThread {
|
||||||
query = it.toQuery()
|
query = it.toQuery()
|
||||||
this@MainActivity.findViewById<SearchInputView>(R.id.search_bar_text)
|
this@MainActivity.findViewById<SearchInputView>(R.id.search_bar_text)
|
||||||
.setText(query, TextView.BufferType.EDITABLE)
|
.setText(query, TextView.BufferType.EDITABLE)
|
||||||
@@ -259,21 +324,12 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addOnScrollListener(
|
|
||||||
object: RecyclerView.OnScrollListener() {
|
|
||||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
|
||||||
super.onScrolled(recyclerView, dx, dy)
|
|
||||||
|
|
||||||
val layoutManager = recyclerView.layoutManager as LinearLayoutManager
|
|
||||||
|
|
||||||
if (loadingJob?.isActive != true)
|
|
||||||
if (layoutManager.findLastCompletelyVisibleItemPosition() == galleries.size)
|
|
||||||
loadBlocks()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
ItemClickSupport.addTo(this)
|
ItemClickSupport.addTo(this)
|
||||||
.setOnItemClickListener { _, position, _ ->
|
.setOnItemClickListener { _, position, v ->
|
||||||
|
|
||||||
|
if (v !is CardView)
|
||||||
|
return@setOnItemClickListener
|
||||||
|
|
||||||
val intent = Intent(this@MainActivity, ReaderActivity::class.java)
|
val intent = Intent(this@MainActivity, ReaderActivity::class.java)
|
||||||
val gallery = galleries[position].first
|
val gallery = galleries[position].first
|
||||||
intent.putExtra("galleryblock", Json(JsonConfiguration.Stable).stringify(GalleryBlock.serializer(), gallery))
|
intent.putExtra("galleryblock", Json(JsonConfiguration.Stable).stringify(GalleryBlock.serializer(), gallery))
|
||||||
@@ -281,8 +337,12 @@ class MainActivity : AppCompatActivity() {
|
|||||||
//TODO: Maybe sprinke some transitions will be nice :D
|
//TODO: Maybe sprinke some transitions will be nice :D
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
|
|
||||||
Histories.default.add(gallery.id)
|
histories.add(gallery.id)
|
||||||
}.setOnItemLongClickListener { recyclerView, position, v ->
|
}.setOnItemLongClickListener { recyclerView, position, v ->
|
||||||
|
|
||||||
|
if (v !is CardView)
|
||||||
|
return@setOnItemLongClickListener true
|
||||||
|
|
||||||
val galleryBlock = galleries[position].first
|
val galleryBlock = galleries[position].first
|
||||||
val view = LayoutInflater.from(this@MainActivity)
|
val view = LayoutInflater.from(this@MainActivity)
|
||||||
.inflate(R.layout.dialog_galleryblock, recyclerView, false)
|
.inflate(R.layout.dialog_galleryblock, recyclerView, false)
|
||||||
@@ -301,7 +361,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
val downloader = GalleryDownloader.get(galleryBlock.id)
|
val downloader = GalleryDownloader.get(galleryBlock.id)
|
||||||
if (downloader == null) {
|
if (downloader == null) {
|
||||||
GalleryDownloader(context, galleryBlock, true).start()
|
GalleryDownloader(context, galleryBlock, true).start()
|
||||||
Histories.default.add(galleryBlock.id)
|
downloads.add(galleryBlock.id)
|
||||||
} else {
|
} else {
|
||||||
downloader.cancel()
|
downloader.cancel()
|
||||||
downloader.clearNotification()
|
downloader.clearNotification()
|
||||||
@@ -329,6 +389,209 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var origin = 0f
|
||||||
|
var target = -1
|
||||||
|
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
val perPage = preferences.getString("per_page", "25")!!.toInt()
|
||||||
|
setOnTouchListener { _, event ->
|
||||||
|
when(event.action) {
|
||||||
|
MotionEvent.ACTION_UP -> {
|
||||||
|
origin = 0f
|
||||||
|
|
||||||
|
with(main_recyclerview.adapter as GalleryBlockAdapter) {
|
||||||
|
if(showPrev) {
|
||||||
|
showPrev = false
|
||||||
|
|
||||||
|
val prev = main_recyclerview.layoutManager?.getChildAt(0)
|
||||||
|
|
||||||
|
if (prev is LinearLayout) {
|
||||||
|
val icon = prev.findViewById<ImageView>(R.id.icon_prev)
|
||||||
|
prev.layoutParams.height = 1
|
||||||
|
icon.layoutParams.height = 1
|
||||||
|
icon.rotation = 180f
|
||||||
|
}
|
||||||
|
|
||||||
|
prev?.requestLayout()
|
||||||
|
|
||||||
|
notifyItemRemoved(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if(showNext) {
|
||||||
|
showNext = false
|
||||||
|
|
||||||
|
val next = main_recyclerview.layoutManager?.let {
|
||||||
|
getChildAt(childCount-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next is LinearLayout) {
|
||||||
|
val icon = next.findViewById<ImageView>(R.id.icon_next)
|
||||||
|
next.layoutParams.height = 1
|
||||||
|
icon.layoutParams.height = 1
|
||||||
|
icon.rotation = 0f
|
||||||
|
}
|
||||||
|
|
||||||
|
next?.requestLayout()
|
||||||
|
|
||||||
|
notifyItemRemoved(itemCount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target != -1) {
|
||||||
|
currentPage = target
|
||||||
|
|
||||||
|
runOnUiThread {
|
||||||
|
cancelFetch()
|
||||||
|
clearGalleries()
|
||||||
|
fetchGalleries(query)
|
||||||
|
loadBlocks()
|
||||||
|
}
|
||||||
|
|
||||||
|
target = -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MotionEvent.ACTION_DOWN -> origin = event.y
|
||||||
|
MotionEvent.ACTION_MOVE -> {
|
||||||
|
if (origin == 0f)
|
||||||
|
origin = event.y
|
||||||
|
|
||||||
|
val dist = event.y - origin
|
||||||
|
|
||||||
|
when {
|
||||||
|
!canScrollVertically(-1) -> {
|
||||||
|
//TOP
|
||||||
|
|
||||||
|
//Scrolling UP
|
||||||
|
if (dist > 0 && currentPage != 0) {
|
||||||
|
with(main_recyclerview.adapter as GalleryBlockAdapter) {
|
||||||
|
if(!showPrev) {
|
||||||
|
showPrev = true
|
||||||
|
notifyItemInserted(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val prev = main_recyclerview.layoutManager?.getChildAt(0)
|
||||||
|
|
||||||
|
if (prev is LinearLayout) {
|
||||||
|
val icon = prev.findViewById<ImageView>(R.id.icon_prev)
|
||||||
|
val text = prev.findViewById<TextView>(R.id.text_prev).apply {
|
||||||
|
text = getString(R.string.main_move, currentPage)
|
||||||
|
}
|
||||||
|
if (dist < 360) {
|
||||||
|
prev.layoutParams.height = (dist/2).roundToInt()
|
||||||
|
icon.layoutParams.height = (dist/2).roundToInt()
|
||||||
|
icon.rotation = dist+180
|
||||||
|
text.layoutParams.width = dist.roundToInt()
|
||||||
|
|
||||||
|
target = -1
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
prev.layoutParams.height = 180
|
||||||
|
icon.layoutParams.height = 180
|
||||||
|
icon.rotation = 180f
|
||||||
|
text.layoutParams.width = LinearLayout.LayoutParams.WRAP_CONTENT
|
||||||
|
|
||||||
|
target = currentPage-1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prev?.requestLayout()
|
||||||
|
|
||||||
|
return@setOnTouchListener true
|
||||||
|
} else {
|
||||||
|
with(main_recyclerview.adapter as GalleryBlockAdapter) {
|
||||||
|
if(showPrev) {
|
||||||
|
showPrev = false
|
||||||
|
|
||||||
|
val prev = main_recyclerview.layoutManager?.getChildAt(0)
|
||||||
|
|
||||||
|
if (prev is LinearLayout) {
|
||||||
|
val icon = prev.findViewById<ImageView>(R.id.icon_prev)
|
||||||
|
prev.layoutParams.height = 1
|
||||||
|
icon.layoutParams.height = 1
|
||||||
|
icon.rotation = 180f
|
||||||
|
}
|
||||||
|
|
||||||
|
prev?.requestLayout()
|
||||||
|
|
||||||
|
notifyItemRemoved(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
!canScrollVertically(1) -> {
|
||||||
|
//BOTTOM
|
||||||
|
|
||||||
|
//Scrolling DOWN
|
||||||
|
if (dist < 0 && currentPage != Math.ceil(totalItems.toDouble()/perPage).roundToInt()-1) {
|
||||||
|
with(main_recyclerview.adapter as GalleryBlockAdapter) {
|
||||||
|
if(!showNext) {
|
||||||
|
showNext = true
|
||||||
|
notifyItemInserted(itemCount-1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val next = main_recyclerview.layoutManager?.let {
|
||||||
|
getChildAt(childCount-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
val absDist = Math.abs(dist)
|
||||||
|
|
||||||
|
if (next is LinearLayout) {
|
||||||
|
val icon = next.findViewById<ImageView>(R.id.icon_next)
|
||||||
|
val text = next.findViewById<TextView>(R.id.text_next).apply {
|
||||||
|
text = getString(R.string.main_move, currentPage+2)
|
||||||
|
}
|
||||||
|
if (absDist < 360) {
|
||||||
|
next.layoutParams.height = (absDist/2).roundToInt()
|
||||||
|
icon.layoutParams.height = (absDist/2).roundToInt()
|
||||||
|
icon.rotation = -absDist
|
||||||
|
text.layoutParams.width = absDist.roundToInt()
|
||||||
|
|
||||||
|
target = -1
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
next.layoutParams.height = 180
|
||||||
|
icon.layoutParams.height = 180
|
||||||
|
icon.rotation = 0f
|
||||||
|
text.layoutParams.width = LinearLayout.LayoutParams.WRAP_CONTENT
|
||||||
|
|
||||||
|
target = currentPage+1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
next?.requestLayout()
|
||||||
|
|
||||||
|
return@setOnTouchListener true
|
||||||
|
} else {
|
||||||
|
with(main_recyclerview.adapter as GalleryBlockAdapter) {
|
||||||
|
if(showNext) {
|
||||||
|
showNext = false
|
||||||
|
|
||||||
|
val next = main_recyclerview.layoutManager?.let {
|
||||||
|
getChildAt(childCount-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next is LinearLayout) {
|
||||||
|
val icon = next.findViewById<ImageView>(R.id.icon_next)
|
||||||
|
next.layoutParams.height = 1
|
||||||
|
icon.layoutParams.height = 1
|
||||||
|
icon.rotation = 180f
|
||||||
|
}
|
||||||
|
|
||||||
|
next?.requestLayout()
|
||||||
|
|
||||||
|
notifyItemRemoved(itemCount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,7 +620,33 @@ class MainActivity : AppCompatActivity() {
|
|||||||
setOnMenuItemClickListener {
|
setOnMenuItemClickListener {
|
||||||
when(it.itemId) {
|
when(it.itemId) {
|
||||||
R.id.main_menu_settings -> startActivityForResult(Intent(this@MainActivity, SettingsActivity::class.java), SETTINGS)
|
R.id.main_menu_settings -> startActivityForResult(Intent(this@MainActivity, SettingsActivity::class.java), SETTINGS)
|
||||||
R.id.main_menu_search -> setSearchFocused(true)
|
R.id.main_menu_page_indicator -> {
|
||||||
|
val preference = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
val perPage = preference.getString("per_page", "25")!!.toInt()
|
||||||
|
val editText = EditText(context)
|
||||||
|
|
||||||
|
AlertDialog.Builder(context).apply {
|
||||||
|
title = getString(R.string.reader_go_to_page)
|
||||||
|
setView(editText)
|
||||||
|
setTitle(R.string.main_jump_title)
|
||||||
|
setMessage(getString(
|
||||||
|
R.string.main_jump_message,
|
||||||
|
currentPage+1,
|
||||||
|
Math.ceil(totalItems / perPage.toDouble()).roundToInt()
|
||||||
|
))
|
||||||
|
|
||||||
|
setPositiveButton(android.R.string.ok) { _, _ ->
|
||||||
|
currentPage = (editText.text.toString().toIntOrNull() ?: return@setPositiveButton)-1
|
||||||
|
|
||||||
|
runOnUiThread {
|
||||||
|
cancelFetch()
|
||||||
|
clearGalleries()
|
||||||
|
fetchGalleries(query)
|
||||||
|
loadBlocks()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -442,7 +731,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
if (query != this@MainActivity.query) {
|
if (query != this@MainActivity.query) {
|
||||||
this@MainActivity.query = query
|
this@MainActivity.query = query
|
||||||
|
|
||||||
CoroutineScope(Dispatchers.Main).launch {
|
runOnUiThread {
|
||||||
cancelFetch()
|
cancelFetch()
|
||||||
clearGalleries()
|
clearGalleries()
|
||||||
fetchGalleries(query)
|
fetchGalleries(query)
|
||||||
@@ -473,12 +762,12 @@ class MainActivity : AppCompatActivity() {
|
|||||||
this.notifyDataSetChanged()
|
this.notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
main_appbar_layout.setExpanded(true)
|
||||||
main_noresult.visibility = View.INVISIBLE
|
main_noresult.visibility = View.INVISIBLE
|
||||||
main_progressbar.show()
|
main_progressbar.show()
|
||||||
main_swipe_layout.isRefreshing = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchGalleries(query: String, from: Int = 0) {
|
private fun fetchGalleries(query: String) {
|
||||||
val preference = PreferenceManager.getDefaultSharedPreferences(this)
|
val preference = PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
val perPage = preference.getString("per_page", "25")?.toInt() ?: 25
|
val perPage = preference.getString("per_page", "25")?.toInt() ?: 25
|
||||||
val defaultQuery = preference.getString("default_query", "")!!
|
val defaultQuery = preference.getString("default_query", "")!!
|
||||||
@@ -489,13 +778,48 @@ class MainActivity : AppCompatActivity() {
|
|||||||
return
|
return
|
||||||
|
|
||||||
galleryIDs = CoroutineScope(Dispatchers.IO).async {
|
galleryIDs = CoroutineScope(Dispatchers.IO).async {
|
||||||
when {
|
when(mode) {
|
||||||
query.contains("HISTORY") ->
|
Mode.SEARCH -> {
|
||||||
Histories.default.toList()
|
when {
|
||||||
query.isEmpty() and defaultQuery.isEmpty() ->
|
query.isEmpty() and defaultQuery.isEmpty() -> {
|
||||||
fetchNozomi(start = from, count = perPage)
|
fetchNozomi(start = currentPage*perPage, count = perPage).let {
|
||||||
else ->
|
totalItems = it.second
|
||||||
doSearch("$defaultQuery $query")
|
it.first
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> doSearch("$defaultQuery $query").apply {
|
||||||
|
totalItems = size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Mode.HISTORY -> {
|
||||||
|
when {
|
||||||
|
query.isEmpty() -> {
|
||||||
|
histories.toList().apply {
|
||||||
|
totalItems = size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
val result = doSearch(query).sorted()
|
||||||
|
histories.filter { result.binarySearch(it) >= 0 }.apply {
|
||||||
|
totalItems = size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Mode.DOWNLOAD -> {
|
||||||
|
when {
|
||||||
|
query.isEmpty() -> downloads.toList().apply {
|
||||||
|
totalItems = size
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
val result = doSearch(query).sorted()
|
||||||
|
downloads.filter { result.binarySearch(it) >= 0 }.apply {
|
||||||
|
totalItems = size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -517,18 +841,11 @@ class MainActivity : AppCompatActivity() {
|
|||||||
return@launch
|
return@launch
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.isEmpty() and defaultQuery.isEmpty())
|
|
||||||
fetchGalleries("", galleries.size+perPage)
|
|
||||||
else
|
|
||||||
with(main_recyclerview.adapter as GalleryBlockAdapter) {
|
|
||||||
noMore = galleries.size + perPage >= galleryIDs.size
|
|
||||||
}
|
|
||||||
|
|
||||||
when {
|
when {
|
||||||
query.isEmpty() and defaultQuery.isEmpty() ->
|
query.isEmpty() and defaultQuery.isEmpty() and (mode == Mode.SEARCH) ->
|
||||||
galleryIDs
|
galleryIDs
|
||||||
else ->
|
else ->
|
||||||
galleryIDs.slice(galleries.size until Math.min(galleries.size+perPage, galleryIDs.size))
|
galleryIDs.slice(currentPage*perPage until Math.min(currentPage*perPage+perPage, galleryIDs.size))
|
||||||
}.chunked(5).let { chunks ->
|
}.chunked(5).let { chunks ->
|
||||||
for (chunk in chunks)
|
for (chunk in chunks)
|
||||||
chunk.map {
|
chunk.map {
|
||||||
@@ -586,8 +903,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
if (galleryBlock != null) {
|
if (galleryBlock != null) {
|
||||||
galleries.add(galleryBlock)
|
galleries.add(galleryBlock)
|
||||||
|
main_recyclerview.adapter!!.notifyItemInserted(galleries.size - 1)
|
||||||
main_recyclerview.adapter?.notifyItemInserted(galleries.size - 1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,17 +6,23 @@ import android.app.NotificationManager
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.preference.PreferenceManager
|
import android.preference.PreferenceManager
|
||||||
import android.util.SparseArray
|
import androidx.core.content.ContextCompat
|
||||||
import com.finotes.android.finotescore.Fn
|
import com.finotes.android.finotescore.Fn
|
||||||
import com.finotes.android.finotescore.ObservableApplication
|
import com.finotes.android.finotescore.ObservableApplication
|
||||||
import com.finotes.android.finotescore.Severity
|
import xyz.quaver.pupil.util.Histories
|
||||||
import kotlinx.coroutines.Job
|
import java.io.File
|
||||||
|
|
||||||
class Pupil : ObservableApplication() {
|
class Pupil : ObservableApplication() {
|
||||||
|
|
||||||
|
lateinit var histories: Histories
|
||||||
|
lateinit var downloads: Histories
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
val preference = PreferenceManager.getDefaultSharedPreferences(this)
|
val preference = PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
|
|
||||||
|
histories = Histories(File(ContextCompat.getDataDir(this), "histories.json"))
|
||||||
|
downloads = Histories(File(ContextCompat.getDataDir(this), "downloads.json"))
|
||||||
|
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
Fn.init(this)
|
Fn.init(this)
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package xyz.quaver.pupil
|
|||||||
|
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
@@ -13,12 +12,14 @@ import androidx.recyclerview.widget.PagerSnapHelper
|
|||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.vectordrawable.graphics.drawable.Animatable2Compat
|
import androidx.vectordrawable.graphics.drawable.Animatable2Compat
|
||||||
import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat
|
import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat
|
||||||
|
import com.google.android.material.snackbar.Snackbar
|
||||||
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.activity_reader.view.*
|
||||||
import kotlinx.android.synthetic.main.dialog_numberpicker.view.*
|
import kotlinx.android.synthetic.main.dialog_numberpicker.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 kotlinx.io.IOException
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import kotlinx.serialization.json.JsonConfiguration
|
import kotlinx.serialization.json.JsonConfiguration
|
||||||
import xyz.quaver.hitomi.GalleryBlock
|
import xyz.quaver.hitomi.GalleryBlock
|
||||||
@@ -63,7 +64,7 @@ class ReaderActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
initView()
|
initView()
|
||||||
|
|
||||||
if (!downloader.notify)
|
if (!downloader.download)
|
||||||
downloader.start()
|
downloader.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +91,7 @@ class ReaderActivity : AppCompatActivity() {
|
|||||||
when(item?.itemId) {
|
when(item?.itemId) {
|
||||||
R.id.reader_menu_page_indicator -> {
|
R.id.reader_menu_page_indicator -> {
|
||||||
val view = LayoutInflater.from(this).inflate(R.layout.dialog_numberpicker, findViewById(android.R.id.content), false)
|
val view = LayoutInflater.from(this).inflate(R.layout.dialog_numberpicker, findViewById(android.R.id.content), false)
|
||||||
with(view.reader_dialog_number_picker) {
|
with(view.dialog_number_picker) {
|
||||||
minValue=1
|
minValue=1
|
||||||
maxValue=gallerySize
|
maxValue=gallerySize
|
||||||
value=currentPage
|
value=currentPage
|
||||||
@@ -98,8 +99,8 @@ class ReaderActivity : AppCompatActivity() {
|
|||||||
val dialog = AlertDialog.Builder(this).apply {
|
val dialog = AlertDialog.Builder(this).apply {
|
||||||
setView(view)
|
setView(view)
|
||||||
}.create()
|
}.create()
|
||||||
view.reader_dialog_ok.setOnClickListener {
|
view.dialog_ok.setOnClickListener {
|
||||||
(reader_recyclerview.layoutManager as LinearLayoutManager?)?.scrollToPositionWithOffset(view.reader_dialog_number_picker.value-1, 0)
|
(reader_recyclerview.layoutManager as LinearLayoutManager?)?.scrollToPositionWithOffset(view.dialog_number_picker.value-1, 0)
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,7 +114,7 @@ class ReaderActivity : AppCompatActivity() {
|
|||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
|
|
||||||
if (!downloader.notify)
|
if (!downloader.download)
|
||||||
downloader.cancel()
|
downloader.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,7 +137,13 @@ class ReaderActivity : AppCompatActivity() {
|
|||||||
var d: GalleryDownloader? = GalleryDownloader.get(galleryBlock.id)
|
var d: GalleryDownloader? = GalleryDownloader.get(galleryBlock.id)
|
||||||
|
|
||||||
if (d == null) {
|
if (d == null) {
|
||||||
d = GalleryDownloader(this, galleryBlock)
|
try {
|
||||||
|
d = GalleryDownloader(this, galleryBlock)
|
||||||
|
} catch (e: IOException) {
|
||||||
|
Snackbar.make(reader_layout, R.string.unable_to_connect, Snackbar.LENGTH_LONG).show()
|
||||||
|
finish()
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
downloader = d.apply {
|
downloader = d.apply {
|
||||||
@@ -159,18 +166,21 @@ class ReaderActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
onDownloadedHandler = {
|
onDownloadedHandler = {
|
||||||
|
val item = it.toList()
|
||||||
CoroutineScope(Dispatchers.Main).launch {
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
if (images.isEmpty()) {
|
if (images.isEmpty()) {
|
||||||
images.addAll(it)
|
images.addAll(item)
|
||||||
reader_recyclerview.adapter?.notifyDataSetChanged()
|
reader_recyclerview.adapter?.notifyDataSetChanged()
|
||||||
} else {
|
} else {
|
||||||
images.add(it.last())
|
images.add(item.last())
|
||||||
reader_recyclerview.adapter?.notifyItemInserted(images.size-1)
|
reader_recyclerview.adapter?.notifyItemInserted(images.size-1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onErrorHandler = {
|
onErrorHandler = {
|
||||||
downloader.notify = false
|
if (it is IOException)
|
||||||
|
Snackbar.make(reader_layout, R.string.unable_to_connect, Snackbar.LENGTH_LONG).show()
|
||||||
|
downloader.download = false
|
||||||
}
|
}
|
||||||
onCompleteHandler = {
|
onCompleteHandler = {
|
||||||
CoroutineScope(Dispatchers.Main).launch {
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
@@ -180,32 +190,36 @@ class ReaderActivity : AppCompatActivity() {
|
|||||||
onNotifyChangedHandler = { notify ->
|
onNotifyChangedHandler = { notify ->
|
||||||
val fab = reader_fab_download
|
val fab = reader_fab_download
|
||||||
|
|
||||||
if (notify) {
|
runOnUiThread {
|
||||||
val icon = AnimatedVectorDrawableCompat.create(this, R.drawable.ic_downloading)
|
if (notify) {
|
||||||
icon?.registerAnimationCallback(object: Animatable2Compat.AnimationCallback() {
|
val icon = AnimatedVectorDrawableCompat.create(this, R.drawable.ic_downloading)
|
||||||
override fun onAnimationEnd(drawable: Drawable?) {
|
icon?.registerAnimationCallback(object: Animatable2Compat.AnimationCallback() {
|
||||||
if (downloader.notify)
|
override fun onAnimationEnd(drawable: Drawable?) {
|
||||||
fab.post {
|
if (downloader.download)
|
||||||
icon.start()
|
fab.post {
|
||||||
fab.labelText = getString(R.string.reader_fab_download_cancel)
|
icon.start()
|
||||||
}
|
fab.labelText = getString(R.string.reader_fab_download_cancel)
|
||||||
else
|
}
|
||||||
fab.post {
|
else
|
||||||
fab.setImageResource(R.drawable.ic_download)
|
fab.post {
|
||||||
fab.labelText = getString(R.string.reader_fab_download)
|
fab.setImageResource(R.drawable.ic_download)
|
||||||
}
|
fab.labelText = getString(R.string.reader_fab_download)
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
})
|
||||||
|
|
||||||
fab.setImageDrawable(icon)
|
fab.setImageDrawable(icon)
|
||||||
icon?.start()
|
icon?.start()
|
||||||
} else {
|
} else {
|
||||||
fab.setImageResource(R.drawable.ic_download)
|
runOnUiThread {
|
||||||
|
fab.setImageResource(R.drawable.ic_download)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (downloader.notify) {
|
if (downloader.download) {
|
||||||
downloader.invokeOnReaderLoaded()
|
downloader.invokeOnReaderLoaded()
|
||||||
downloader.invokeOnNotifyChanged()
|
downloader.invokeOnNotifyChanged()
|
||||||
}
|
}
|
||||||
@@ -255,9 +269,9 @@ class ReaderActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
reader_fab_download.setOnClickListener {
|
reader_fab_download.setOnClickListener {
|
||||||
downloader.notify = !downloader.notify
|
downloader.download = !downloader.download
|
||||||
|
|
||||||
if (!downloader.notify)
|
if (!downloader.download)
|
||||||
downloader.clearNotification()
|
downloader.clearNotification()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import androidx.preference.Preference
|
|||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
import kotlinx.android.synthetic.main.dialog_default_query.view.*
|
import kotlinx.android.synthetic.main.dialog_default_query.view.*
|
||||||
import xyz.quaver.pupil.types.Tags
|
import xyz.quaver.pupil.types.Tags
|
||||||
import xyz.quaver.pupil.util.Histories
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class SettingsActivity : AppCompatActivity() {
|
class SettingsActivity : AppCompatActivity() {
|
||||||
@@ -99,7 +98,7 @@ class SettingsActivity : AppCompatActivity() {
|
|||||||
with(findPreference<Preference>("clear_history")) {
|
with(findPreference<Preference>("clear_history")) {
|
||||||
this ?: return@with
|
this ?: return@with
|
||||||
|
|
||||||
val histories = Histories.default
|
val histories = (activity!!.application as Pupil).histories
|
||||||
|
|
||||||
summary = getString(R.string.settings_clear_history_summary, histories.size)
|
summary = getString(R.string.settings_clear_history_summary, histories.size)
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
package xyz.quaver.pupil.adapters
|
package xyz.quaver.pupil.adapters
|
||||||
|
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import android.graphics.PorterDuff
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.util.SparseArray
|
|
||||||
import android.util.SparseBooleanArray
|
import android.util.SparseBooleanArray
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.RelativeLayout
|
||||||
import androidx.cardview.widget.CardView
|
import androidx.cardview.widget.CardView
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
@@ -29,66 +28,28 @@ import xyz.quaver.pupil.types.Tag
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
import kotlin.collections.HashMap
|
||||||
import kotlin.concurrent.schedule
|
import kotlin.concurrent.schedule
|
||||||
|
|
||||||
class GalleryBlockAdapter(private val galleries: List<Pair<GalleryBlock, Deferred<String>>>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
class GalleryBlockAdapter(private val galleries: List<Pair<GalleryBlock, Deferred<String>>>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||||
|
|
||||||
private enum class ViewType {
|
enum class ViewType {
|
||||||
VIEW_ITEM,
|
NEXT,
|
||||||
VIEW_PROG
|
GALLERY,
|
||||||
|
PREV
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun String.wordCapitalize() : String {
|
inner class GalleryViewHolder(private val view: CardView) : RecyclerView.ViewHolder(view) {
|
||||||
val result = ArrayList<String>()
|
fun bind(item: Pair<GalleryBlock, Deferred<String>>) {
|
||||||
|
with(view) {
|
||||||
for (word in this.split(" "))
|
|
||||||
result.add(word.capitalize())
|
|
||||||
|
|
||||||
return result.joinToString(" ")
|
|
||||||
}
|
|
||||||
|
|
||||||
var noMore = false
|
|
||||||
private val refreshTasks = SparseArray<TimerTask>()
|
|
||||||
val completeFlag = SparseBooleanArray()
|
|
||||||
|
|
||||||
val onChipClickedHandler = ArrayList<((Tag) -> Unit)>()
|
|
||||||
|
|
||||||
class ViewHolder(val view: CardView, var galleryID: Int? = null) : RecyclerView.ViewHolder(view)
|
|
||||||
class ProgressViewHolder(val view: LinearLayout) : RecyclerView.ViewHolder(view)
|
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
|
||||||
when(viewType) {
|
|
||||||
ViewType.VIEW_ITEM.ordinal -> {
|
|
||||||
val view = LayoutInflater.from(parent.context).inflate(
|
|
||||||
R.layout.item_galleryblock, parent, false
|
|
||||||
) as CardView
|
|
||||||
|
|
||||||
return ViewHolder(view)
|
|
||||||
}
|
|
||||||
ViewType.VIEW_PROG.ordinal -> {
|
|
||||||
val view = LayoutInflater.from(parent.context).inflate(
|
|
||||||
R.layout.item_progressbar, parent, false
|
|
||||||
) as LinearLayout
|
|
||||||
|
|
||||||
return ProgressViewHolder(view)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw Exception("Unexpected ViewType")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
|
||||||
if (holder is ViewHolder) {
|
|
||||||
with(holder.view) {
|
|
||||||
val resources = context.resources
|
val resources = context.resources
|
||||||
val languages = resources.getStringArray(R.array.languages).map {
|
val languages = resources.getStringArray(R.array.languages).map {
|
||||||
it.split("|").let { split ->
|
it.split("|").let { split ->
|
||||||
Pair(split[0], split[1])
|
Pair(split[0], split[1])
|
||||||
}
|
}
|
||||||
}.toMap()
|
}.toMap()
|
||||||
val (gallery, thumbnail) = galleries[position]
|
|
||||||
|
|
||||||
holder.galleryID = gallery.id
|
val (gallery: GalleryBlock, thumbnail: Deferred<String>) = item
|
||||||
|
|
||||||
val artists = gallery.artists
|
val artists = gallery.artists
|
||||||
val series = gallery.series
|
val series = gallery.series
|
||||||
@@ -101,7 +62,7 @@ class GalleryBlockAdapter(private val galleries: List<Pair<GalleryBlock, Deferre
|
|||||||
|
|
||||||
val bitmap = BitmapFactory.decodeFile(thumbnail.await())
|
val bitmap = BitmapFactory.decodeFile(thumbnail.await())
|
||||||
|
|
||||||
CoroutineScope(Dispatchers.Main).launch {
|
post {
|
||||||
galleryblock_thumbnail.setImageBitmap(bitmap)
|
galleryblock_thumbnail.setImageBitmap(bitmap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -124,10 +85,10 @@ class GalleryBlockAdapter(private val galleries: List<Pair<GalleryBlock, Deferre
|
|||||||
galleryblock_progressbar.visibility = View.GONE
|
galleryblock_progressbar.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
if (refreshTasks.get(gallery.id) == null) {
|
if (refreshTasks[this@GalleryViewHolder] == null) {
|
||||||
val refresh = Timer(false).schedule(0, 1000) {
|
val refresh = Timer(false).schedule(0, 1000) {
|
||||||
post {
|
post {
|
||||||
with(galleryblock_progressbar) {
|
with(view.galleryblock_progressbar) {
|
||||||
progress = imageCache.list()?.size ?: 0
|
progress = imageCache.list()?.size ?: 0
|
||||||
|
|
||||||
if (!readerCache.exists()) {
|
if (!readerCache.exists()) {
|
||||||
@@ -135,7 +96,7 @@ class GalleryBlockAdapter(private val galleries: List<Pair<GalleryBlock, Deferre
|
|||||||
max = 0
|
max = 0
|
||||||
progress = 0
|
progress = 0
|
||||||
|
|
||||||
holder.view.galleryblock_progress_complete.visibility = View.INVISIBLE
|
view.galleryblock_progress_complete.visibility = View.INVISIBLE
|
||||||
} else {
|
} else {
|
||||||
if (visibility == View.GONE) {
|
if (visibility == View.GONE) {
|
||||||
val reader = Json(JsonConfiguration.Stable)
|
val reader = Json(JsonConfiguration.Stable)
|
||||||
@@ -146,24 +107,21 @@ class GalleryBlockAdapter(private val galleries: List<Pair<GalleryBlock, Deferre
|
|||||||
|
|
||||||
if (progress == max) {
|
if (progress == max) {
|
||||||
if (completeFlag.get(gallery.id, false)) {
|
if (completeFlag.get(gallery.id, false)) {
|
||||||
with(holder.view.galleryblock_progress_complete) {
|
with(view.galleryblock_progress_complete) {
|
||||||
setImageResource(R.drawable.ic_progressbar)
|
setImageResource(R.drawable.ic_progressbar)
|
||||||
visibility = View.VISIBLE
|
visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val drawable = AnimatedVectorDrawableCompat.create(context, R.drawable.ic_progressbar_complete)
|
val drawable = AnimatedVectorDrawableCompat.create(context, R.drawable.ic_progressbar_complete)
|
||||||
with(holder.view.galleryblock_progress_complete) {
|
with(view.galleryblock_progress_complete) {
|
||||||
setImageDrawable(drawable)
|
setImageDrawable(drawable)
|
||||||
visibility = View.VISIBLE
|
visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
drawable?.start()
|
drawable?.start()
|
||||||
completeFlag.put(gallery.id, true)
|
completeFlag.put(gallery.id, true)
|
||||||
}
|
}
|
||||||
} else {
|
} else
|
||||||
with(holder.view.galleryblock_progress_complete) {
|
view.galleryblock_progress_complete.visibility = View.INVISIBLE
|
||||||
visibility = View.INVISIBLE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
@@ -171,7 +129,7 @@ class GalleryBlockAdapter(private val galleries: List<Pair<GalleryBlock, Deferre
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshTasks.put(gallery.id, refresh)
|
refreshTasks[this@GalleryViewHolder] = refresh
|
||||||
}
|
}
|
||||||
|
|
||||||
galleryblock_title.text = gallery.title
|
galleryblock_title.text = gallery.title
|
||||||
@@ -207,7 +165,7 @@ class GalleryBlockAdapter(private val galleries: List<Pair<GalleryBlock, Deferre
|
|||||||
val tag = Tag.parse(it)
|
val tag = Tag.parse(it)
|
||||||
|
|
||||||
val chip = LayoutInflater.from(context)
|
val chip = LayoutInflater.from(context)
|
||||||
.inflate(R.layout.tag_chip, holder.view, false) as Chip
|
.inflate(R.layout.tag_chip, this, false) as Chip
|
||||||
|
|
||||||
val icon = when(tag.area) {
|
val icon = when(tag.area) {
|
||||||
"male" -> {
|
"male" -> {
|
||||||
@@ -234,32 +192,85 @@ class GalleryBlockAdapter(private val galleries: List<Pair<GalleryBlock, Deferre
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (holder is ProgressViewHolder) {
|
}
|
||||||
holder.view.visibility = when(noMore) {
|
class NextViewHolder(view: LinearLayout) : RecyclerView.ViewHolder(view)
|
||||||
true -> View.GONE
|
class PrevViewHolder(view: LinearLayout) : RecyclerView.ViewHolder(view)
|
||||||
false -> View.VISIBLE
|
|
||||||
|
class ViewHolderFactory {
|
||||||
|
companion object {
|
||||||
|
fun getLayoutID(type: Int): Int {
|
||||||
|
return when(ViewType.values()[type]) {
|
||||||
|
ViewType.NEXT -> R.layout.item_next
|
||||||
|
ViewType.PREV -> R.layout.item_prev
|
||||||
|
ViewType.GALLERY -> R.layout.item_galleryblock
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun String.wordCapitalize() : String {
|
||||||
|
val result = ArrayList<String>()
|
||||||
|
|
||||||
|
for (word in this.split(" "))
|
||||||
|
result.add(word.capitalize())
|
||||||
|
|
||||||
|
return result.joinToString(" ")
|
||||||
|
}
|
||||||
|
|
||||||
|
private val refreshTasks = HashMap<GalleryViewHolder, TimerTask>()
|
||||||
|
val completeFlag = SparseBooleanArray()
|
||||||
|
|
||||||
|
val onChipClickedHandler = ArrayList<((Tag) -> Unit)>()
|
||||||
|
|
||||||
|
var showNext = false
|
||||||
|
var showPrev = false
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||||
|
|
||||||
|
fun getViewHolder(type: Int, view: View): RecyclerView.ViewHolder {
|
||||||
|
return when(ViewType.values()[type]) {
|
||||||
|
ViewType.NEXT -> NextViewHolder(view as LinearLayout)
|
||||||
|
ViewType.PREV -> PrevViewHolder(view as LinearLayout)
|
||||||
|
ViewType.GALLERY -> GalleryViewHolder(view as CardView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return getViewHolder(
|
||||||
|
viewType,
|
||||||
|
LayoutInflater.from(parent.context).inflate(
|
||||||
|
ViewHolderFactory.getLayoutID(viewType),
|
||||||
|
parent,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||||
|
if (holder is GalleryViewHolder)
|
||||||
|
holder.bind(galleries[position-(if (showPrev) 1 else 0)])
|
||||||
|
}
|
||||||
|
|
||||||
override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) {
|
override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) {
|
||||||
super.onViewDetachedFromWindow(holder)
|
super.onViewDetachedFromWindow(holder)
|
||||||
|
|
||||||
if (holder is ViewHolder) {
|
if (holder is GalleryViewHolder) {
|
||||||
val galleryID = holder.galleryID ?: return
|
val task = refreshTasks[holder] ?: return
|
||||||
val task = refreshTasks.get(galleryID) ?: return
|
|
||||||
|
|
||||||
refreshTasks.remove(galleryID)
|
|
||||||
task.cancel()
|
task.cancel()
|
||||||
|
refreshTasks.remove(holder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount() = if (galleries.isEmpty()) 0 else galleries.size+1
|
override fun getItemCount() =
|
||||||
|
(if (galleries.isEmpty()) 0 else galleries.size)+
|
||||||
|
(if (showNext) 1 else 0)+
|
||||||
|
(if (showPrev) 1 else 0)
|
||||||
|
|
||||||
override fun getItemViewType(position: Int): Int {
|
override fun getItemViewType(position: Int): Int {
|
||||||
return when {
|
return when {
|
||||||
galleries.getOrNull(position) == null -> ViewType.VIEW_PROG.ordinal
|
showPrev && position == 0 -> ViewType.PREV
|
||||||
else -> ViewType.VIEW_ITEM.ordinal
|
showNext && position == galleries.size+(if (showPrev) 1 else 0) -> ViewType.NEXT
|
||||||
}
|
else -> ViewType.GALLERY
|
||||||
|
}.ordinal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -38,9 +38,7 @@ class ReaderAdapter(private val images: List<String>) : RecyclerView.Adapter<Rea
|
|||||||
|
|
||||||
val image = BitmapFactory.decodeFile(images[position], options)
|
val image = BitmapFactory.decodeFile(images[position], options)
|
||||||
|
|
||||||
launch(Dispatchers.Main) {
|
post { setImageBitmap(image) }
|
||||||
setImageBitmap(image)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class GalleryDownloader(
|
|||||||
_notify: Boolean = false
|
_notify: Boolean = false
|
||||||
) : ContextWrapper(base) {
|
) : ContextWrapper(base) {
|
||||||
|
|
||||||
var notify: Boolean = false
|
var download: Boolean = false
|
||||||
set(value) {
|
set(value) {
|
||||||
if (value) {
|
if (value) {
|
||||||
field = true
|
field = true
|
||||||
@@ -55,7 +55,7 @@ class GalleryDownloader(
|
|||||||
var onReaderLoadedHandler: ((Reader) -> Unit)? = null
|
var onReaderLoadedHandler: ((Reader) -> Unit)? = null
|
||||||
var onProgressHandler: ((Int) -> Unit)? = null
|
var onProgressHandler: ((Int) -> Unit)? = null
|
||||||
var onDownloadedHandler: ((List<String>) -> Unit)? = null
|
var onDownloadedHandler: ((List<String>) -> Unit)? = null
|
||||||
var onErrorHandler: (() -> Unit)? = null
|
var onErrorHandler: ((Exception) -> Unit)? = null
|
||||||
var onCompleteHandler: (() -> Unit)? = null
|
var onCompleteHandler: (() -> Unit)? = null
|
||||||
var onNotifyChangedHandler: ((Boolean) -> Unit)? = null
|
var onNotifyChangedHandler: ((Boolean) -> Unit)? = null
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ class GalleryDownloader(
|
|||||||
initNotification()
|
initNotification()
|
||||||
|
|
||||||
reader = CoroutineScope(Dispatchers.IO).async {
|
reader = CoroutineScope(Dispatchers.IO).async {
|
||||||
notify = _notify
|
download = _notify
|
||||||
val json = Json(JsonConfiguration.Stable)
|
val json = Json(JsonConfiguration.Stable)
|
||||||
val serializer = ReaderItem.serializer().list
|
val serializer = ReaderItem.serializer().list
|
||||||
val preference = PreferenceManager.getDefaultSharedPreferences(this@GalleryDownloader)
|
val preference = PreferenceManager.getDefaultSharedPreferences(this@GalleryDownloader)
|
||||||
@@ -100,15 +100,13 @@ class GalleryDownloader(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Could not retrieve reader
|
if (reader.isNotEmpty()) {
|
||||||
if (reader.isEmpty())
|
//Save cache
|
||||||
throw IOException("Can't retrieve Reader")
|
if (!cache.parentFile.exists())
|
||||||
|
cache.parentFile.mkdirs()
|
||||||
|
|
||||||
//Save cache
|
cache.writeText(json.stringify(serializer, reader))
|
||||||
if (!cache.parentFile.exists())
|
}
|
||||||
cache.parentFile.mkdirs()
|
|
||||||
|
|
||||||
cache.writeText(json.stringify(serializer, reader))
|
|
||||||
|
|
||||||
reader
|
reader
|
||||||
}
|
}
|
||||||
@@ -120,6 +118,9 @@ class GalleryDownloader(
|
|||||||
downloadJob = CoroutineScope(Dispatchers.Default).launch {
|
downloadJob = CoroutineScope(Dispatchers.Default).launch {
|
||||||
val reader = reader.await()
|
val reader = reader.await()
|
||||||
|
|
||||||
|
if (reader.isEmpty())
|
||||||
|
onErrorHandler?.invoke(IOException("Couldn't retrieve Reader"))
|
||||||
|
|
||||||
val list = ArrayList<String>()
|
val list = ArrayList<String>()
|
||||||
|
|
||||||
onReaderLoadedHandler?.invoke(reader)
|
onReaderLoadedHandler?.invoke(reader)
|
||||||
@@ -138,7 +139,7 @@ class GalleryDownloader(
|
|||||||
.setProgress(reader.size, index, false)
|
.setProgress(reader.size, index, false)
|
||||||
.setContentText("$index/${reader.size}")
|
.setContentText("$index/${reader.size}")
|
||||||
|
|
||||||
if (notify)
|
if (download)
|
||||||
notificationManager.notify(galleryBlock.id, notificationBuilder.build())
|
notificationManager.notify(galleryBlock.id, notificationBuilder.build())
|
||||||
|
|
||||||
async(Dispatchers.IO) {
|
async(Dispatchers.IO) {
|
||||||
@@ -162,7 +163,7 @@ class GalleryDownloader(
|
|||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
cache.delete()
|
cache.delete()
|
||||||
|
|
||||||
onErrorHandler?.invoke()
|
onErrorHandler?.invoke(e)
|
||||||
|
|
||||||
notificationBuilder
|
notificationBuilder
|
||||||
.setContentTitle(galleryBlock.title)
|
.setContentTitle(galleryBlock.title)
|
||||||
@@ -188,10 +189,10 @@ class GalleryDownloader(
|
|||||||
.setContentText(getString(R.string.reader_notification_complete))
|
.setContentText(getString(R.string.reader_notification_complete))
|
||||||
.setProgress(0, 0, false)
|
.setProgress(0, 0, false)
|
||||||
|
|
||||||
if (notify)
|
if (download)
|
||||||
notificationManager.notify(galleryBlock.id, notificationBuilder.build())
|
notificationManager.notify(galleryBlock.id, notificationBuilder.build())
|
||||||
|
|
||||||
notify = false
|
download = false
|
||||||
}
|
}
|
||||||
|
|
||||||
remove(galleryBlock.id)
|
remove(galleryBlock.id)
|
||||||
@@ -219,7 +220,7 @@ class GalleryDownloader(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun invokeOnNotifyChanged() {
|
fun invokeOnNotifyChanged() {
|
||||||
onNotifyChangedHandler?.invoke(notify)
|
onNotifyChangedHandler?.invoke(download)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initNotification() {
|
private fun initNotification() {
|
||||||
|
|||||||
@@ -20,10 +20,6 @@ class Histories(private val file: File) : ArrayList<Int>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
|
||||||
lateinit var default: Histories
|
|
||||||
}
|
|
||||||
|
|
||||||
@UseExperimental(ImplicitReflectionSerializer::class)
|
@UseExperimental(ImplicitReflectionSerializer::class)
|
||||||
fun load() : Histories {
|
fun load() : Histories {
|
||||||
return apply {
|
return apply {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package xyz.quaver.pupil.util
|
package xyz.quaver.pupil.util
|
||||||
|
|
||||||
import kotlinx.io.IOException
|
|
||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.*
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
|
||||||
|
|||||||
14
app/src/main/res/drawable/ic_jump.xml
Normal file
14
app/src/main/res/drawable/ic_jump.xml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#fff"
|
||||||
|
android:pathData="M18.4,10.6C16.55,8.99 14.15,8 11.5,8c-4.65,0 -8.58,3.03 -9.96,7.22L3.9,16c1.05,-3.19 4.05,-5.5 7.6,-5.5 1.95,0 3.73,0.72 5.12,1.88L13,16h9V7l-3.6,3.6z"/>
|
||||||
|
<path
|
||||||
|
android:fillColor="#fff"
|
||||||
|
android:pathData="M8.5,15
|
||||||
|
a1.5,1.5 0 1,1 1.5,1.5
|
||||||
|
a1.5,1.5 0 0,1 -1.5,-1.5 Z"/>
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M15.41,7.41L14,6l-6,6 6,6 1.41,-1.41L10.83,12z"/>
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M10,6L8.59,7.41 13.17,12l-4.58,4.59L10,18l6,-6z"/>
|
||||||
|
</vector>
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
|
android:id="@+id/main_layout"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
@@ -22,7 +23,7 @@
|
|||||||
|
|
||||||
<View
|
<View
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="80dp"
|
android:layout_height="64dp"
|
||||||
android:visibility="invisible"
|
android:visibility="invisible"
|
||||||
android:background="@color/transparent"
|
android:background="@color/transparent"
|
||||||
app:layout_scrollFlags="scroll|enterAlways"
|
app:layout_scrollFlags="scroll|enterAlways"
|
||||||
@@ -46,22 +47,14 @@
|
|||||||
android:text="@string/main_no_result"
|
android:text="@string/main_no_result"
|
||||||
android:visibility="invisible"/>
|
android:visibility="invisible"/>
|
||||||
|
|
||||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/main_swipe_layout"
|
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:layout_marginBottom="-80dp">
|
android:paddingTop="64dp"
|
||||||
|
android:clipToPadding="false"
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
android:scrollbars="vertical"
|
||||||
android:id="@+id/main_recyclerview"
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:paddingTop="80dp"
|
|
||||||
android:clipToPadding="false"
|
|
||||||
android:scrollbars="vertical"
|
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
|
|
||||||
|
|
||||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
||||||
@@ -71,7 +64,7 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
app:floatingSearch_searchBarMarginLeft="8dp"
|
app:floatingSearch_searchBarMarginLeft="8dp"
|
||||||
app:floatingSearch_searchBarMarginRight="8dp"
|
app:floatingSearch_searchBarMarginRight="8dp"
|
||||||
app:floatingSearch_searchBarMarginTop="24dp"
|
app:floatingSearch_searchBarMarginTop="8dp"
|
||||||
app:floatingSearch_searchHint="@string/search_hint"
|
app:floatingSearch_searchHint="@string/search_hint"
|
||||||
app:floatingSearch_suggestionsListAnimDuration="250"
|
app:floatingSearch_suggestionsListAnimDuration="250"
|
||||||
app:floatingSearch_showSearchKey="true"
|
app:floatingSearch_showSearchKey="true"
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/reader_layout"
|
||||||
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"
|
||||||
@@ -39,6 +40,7 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="bottom|end"
|
android:layout_gravity="bottom|end"
|
||||||
|
android:layout_margin="16dp"
|
||||||
app:menu_colorNormal="@color/colorAccent">
|
app:menu_colorNormal="@color/colorAccent">
|
||||||
|
|
||||||
<com.github.clans.fab.FloatingActionButton
|
<com.github.clans.fab.FloatingActionButton
|
||||||
@@ -46,7 +48,6 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:src="@drawable/ic_downloading"
|
android:src="@drawable/ic_downloading"
|
||||||
android:tint="@android:color/white"
|
|
||||||
app:fab_label="@string/reader_fab_download"
|
app:fab_label="@string/reader_fab_download"
|
||||||
app:fab_size="mini"/>
|
app:fab_size="mini"/>
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
style="?android:textAppearanceLarge"
|
style="?android:textAppearanceLarge"
|
||||||
android:id="@+id/reader_dialog_title"
|
android:id="@+id/dialog_title"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/reader_go_to_page"
|
android:text="@string/reader_go_to_page"
|
||||||
@@ -15,20 +15,20 @@
|
|||||||
app:layout_constraintStart_toStartOf="parent"/>
|
app:layout_constraintStart_toStartOf="parent"/>
|
||||||
|
|
||||||
<NumberPicker
|
<NumberPicker
|
||||||
android:id="@+id/reader_dialog_number_picker"
|
android:id="@+id/dialog_number_picker"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:layout_constraintTop_toBottomOf="@id/reader_dialog_title"
|
app:layout_constraintTop_toBottomOf="@id/dialog_title"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"/>
|
app:layout_constraintEnd_toEndOf="parent"/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/reader_dialog_ok"
|
android:id="@+id/dialog_ok"
|
||||||
style="?borderlessButtonStyle"
|
style="?borderlessButtonStyle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@android:string/ok"
|
android:text="@android:string/ok"
|
||||||
app:layout_constraintTop_toBottomOf="@id/reader_dialog_number_picker"
|
app:layout_constraintTop_toBottomOf="@id/dialog_number_picker"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"/>
|
app:layout_constraintEnd_toEndOf="parent"/>
|
||||||
|
|
||||||
|
|||||||
35
app/src/main/res/layout/item_next.xml
Normal file
35
app/src/main/res/layout/item_next.xml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:gravity="center">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/icon_next"
|
||||||
|
android:contentDescription="@string/page_indicator_placeholder"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:src="@drawable/ic_navigate_next_black_24dp"
|
||||||
|
android:tint="@color/colorAccent"
|
||||||
|
android:rotation="180"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text_next"
|
||||||
|
android:layout_width="1dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:ellipsize="end" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
35
app/src/main/res/layout/item_prev.xml
Normal file
35
app/src/main/res/layout/item_prev.xml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:gravity="center">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/icon_prev"
|
||||||
|
android:contentDescription="@string/page_indicator_placeholder"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:src="@drawable/ic_navigate_next_black_24dp"
|
||||||
|
android:tint="@color/colorAccent"
|
||||||
|
android:rotation="180"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/text_prev"
|
||||||
|
android:layout_width="1dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:ellipsize="end" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -10,6 +10,10 @@
|
|||||||
<item android:id="@+id/main_drawer_history"
|
<item android:id="@+id/main_drawer_history"
|
||||||
android:title="@string/main_drawer_history"
|
android:title="@string/main_drawer_history"
|
||||||
android:icon="@drawable/ic_history"/>
|
android:icon="@drawable/ic_history"/>
|
||||||
|
|
||||||
|
<item android:id="@+id/main_drawer_downloads"
|
||||||
|
android:title="@string/main_drawer_downloads"
|
||||||
|
android:icon="@drawable/ic_download"/>
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
<item android:title="@string/main_drawer_group_contact_title">
|
<item android:title="@string/main_drawer_group_contact_title">
|
||||||
|
|||||||
@@ -2,10 +2,9 @@
|
|||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
<menu 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">
|
||||||
|
|
||||||
<item
|
<item android:id="@+id/main_menu_page_indicator"
|
||||||
android:id="@+id/main_menu_search"
|
android:icon="@drawable/ic_jump"
|
||||||
android:icon="@drawable/ic_search"
|
android:title="@string/page_indicator_placeholder"
|
||||||
android:title="@string/main_search"
|
|
||||||
app:showAsAction="ifRoom"/>
|
app:showAsAction="ifRoom"/>
|
||||||
|
|
||||||
<item
|
<item
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
<item android:id="@+id/reader_menu_page_indicator"
|
<item android:id="@+id/reader_menu_page_indicator"
|
||||||
android:title="@string/reader_page_indicator_placeholder"
|
android:title="@string/page_indicator_placeholder"
|
||||||
app:showAsAction="always|withText"/>
|
app:showAsAction="always|withText"/>
|
||||||
|
|
||||||
</menu>
|
</menu>
|
||||||
@@ -6,12 +6,12 @@
|
|||||||
<string name="main_no_result">結果なし</string>
|
<string name="main_no_result">結果なし</string>
|
||||||
<string name="main_search">検索</string>
|
<string name="main_search">検索</string>
|
||||||
<string name="search_hint">ギャラリー検索</string>
|
<string name="search_hint">ギャラリー検索</string>
|
||||||
|
<string name="search_hint_with_page">ギャラリー検索</string>
|
||||||
<string name="settings_cache_title">キャッシュ</string>
|
<string name="settings_cache_title">キャッシュ</string>
|
||||||
<string name="settings_clear_image_cache">イメージキャッシュクリア</string>
|
<string name="settings_clear_image_cache">イメージキャッシュクリア</string>
|
||||||
<string name="settings_clear_cache_alert_message">キャッシュをクリアするとイメージのロード速度に影響を与えます。実行しますか?</string>
|
<string name="settings_clear_cache_alert_message">キャッシュをクリアするとイメージのロード速度に影響を与えます。実行しますか?</string>
|
||||||
<string name="settings_clear_cache_summary">キャッシュサイズ: %1$d%2$s</string>
|
<string name="settings_clear_cache_summary">キャッシュサイズ: %1$d%2$s</string>
|
||||||
<string name="settings_default_query">デフォルトキーワード</string>
|
<string name="settings_default_query">デフォルトキーワード</string>
|
||||||
<string name="permission_explain">権限を拒否すると一部の機能が利用できません</string>
|
|
||||||
<string name="settings_galleries_per_page">一回にロードするギャラリー数</string>
|
<string name="settings_galleries_per_page">一回にロードするギャラリー数</string>
|
||||||
<string name="settings_search_title">検索設定</string>
|
<string name="settings_search_title">検索設定</string>
|
||||||
<string name="settings_title">設定</string>
|
<string name="settings_title">設定</string>
|
||||||
@@ -52,4 +52,11 @@
|
|||||||
<string name="reader_notification_error">ダウンロードエラー</string>
|
<string name="reader_notification_error">ダウンロードエラー</string>
|
||||||
<string name="reader_fab_download_cancel">バックグラウンドダウンロード中止</string>
|
<string name="reader_fab_download_cancel">バックグラウンドダウンロード中止</string>
|
||||||
<string name="main_dialog_delete">このギャラリーを削除</string>
|
<string name="main_dialog_delete">このギャラリーを削除</string>
|
||||||
|
<string name="main_drawer_downloads">ダウンロード</string>
|
||||||
|
<string name="main_jump_title">ページ移動</string>
|
||||||
|
<string name="main_jump_message">現ページ番号: %1$d\nページ数: %2$d</string>
|
||||||
|
<string name="unable_to_connect">hitomi.laに接続できません</string>
|
||||||
|
<string name="main_move">%1$dページへ移動</string>
|
||||||
|
<string name="https_block_alert_title">(Korean only)</string>
|
||||||
|
<string name="https_block_alert">(Korean only)</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -3,8 +3,8 @@
|
|||||||
<string name="galleryblock_language">언어: %1$s</string>
|
<string name="galleryblock_language">언어: %1$s</string>
|
||||||
<string name="galleryblock_series">시리즈: %1$s</string>
|
<string name="galleryblock_series">시리즈: %1$s</string>
|
||||||
<string name="galleryblock_type">종류: %1$s</string>
|
<string name="galleryblock_type">종류: %1$s</string>
|
||||||
<string name="permission_explain">권한을 거부하면 일부 기능이 작동하지 않을 수 있습니다</string>
|
|
||||||
<string name="search_hint">갤러리 검색</string>
|
<string name="search_hint">갤러리 검색</string>
|
||||||
|
<string name="search_hint_with_page">갤러리 검색</string>
|
||||||
<string name="settings_default_query">기본 검색어</string>
|
<string name="settings_default_query">기본 검색어</string>
|
||||||
<string name="settings_clear_image_cache">이미지 캐시 정리하기</string>
|
<string name="settings_clear_image_cache">이미지 캐시 정리하기</string>
|
||||||
<string name="settings_clear_cache_alert_message">캐시를 정리하면 이미지 로딩속도가 느려질 수 있습니다. 계속하시겠습니까?</string>
|
<string name="settings_clear_cache_alert_message">캐시를 정리하면 이미지 로딩속도가 느려질 수 있습니다. 계속하시겠습니까?</string>
|
||||||
@@ -52,4 +52,11 @@
|
|||||||
<string name="reader_notification_error">다운로드 오류</string>
|
<string name="reader_notification_error">다운로드 오류</string>
|
||||||
<string name="reader_fab_download_cancel">백그라운드 다운로드 취소</string>
|
<string name="reader_fab_download_cancel">백그라운드 다운로드 취소</string>
|
||||||
<string name="main_dialog_delete">갤러리 삭제</string>
|
<string name="main_dialog_delete">갤러리 삭제</string>
|
||||||
|
<string name="main_drawer_downloads">다운로드</string>
|
||||||
|
<string name="main_jump_title">페이지 이동</string>
|
||||||
|
<string name="main_jump_message">현재 페이지: %1$d\n페이지 수: %2$d</string>
|
||||||
|
<string name="unable_to_connect">hitomi.la에 연결할 수 없습니다</string>
|
||||||
|
<string name="main_move">%1$d 페이지로 이동</string>
|
||||||
|
<string name="https_block_alert_title">접속 불가 현상 안내</string>
|
||||||
|
<string name="https_block_alert">최근 https 차단으로 접속이 안 되는 경우가 발생하고 있습니다\n이 경우 플레이스토어에서 SNIper앱을 이용하시면 정상이용이 가능합니다.</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<style name="NoActionBarAppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
|
|
||||||
<item name="android:windowTranslucentStatus">true</item>
|
|
||||||
<item name="android:windowTranslucentNavigation">true</item>
|
|
||||||
<item name="android:windowLightStatusBar">true</item>
|
|
||||||
<!-- Customize your theme here. -->
|
|
||||||
<item name="colorPrimary">@color/colorPrimary</item>
|
|
||||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
|
||||||
<item name="colorAccent">@color/colorAccent</item>
|
|
||||||
</style>
|
|
||||||
</resources>
|
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
<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="page_indicator_placeholder" translatable="false">-/-</string>
|
||||||
|
|
||||||
<string name="plus_to_close" translatable="false">Fab</string>
|
<string name="plus_to_close" translatable="false">Fab</string>
|
||||||
|
|
||||||
@@ -20,22 +20,31 @@
|
|||||||
|
|
||||||
<string name="warning">Warning</string>
|
<string name="warning">Warning</string>
|
||||||
|
|
||||||
<string name="permission_explain">Denying any permission can deactivate some functions</string>
|
<string name="https_block_alert_title">(Korean only)</string>
|
||||||
|
<string name="https_block_alert">(Korean only)</string>
|
||||||
|
|
||||||
<string name="channel_download">Download</string>
|
<string name="channel_download">Download</string>
|
||||||
<string name="channel_download_description">Shows download status</string>
|
<string name="channel_download_description">Shows download status</string>
|
||||||
|
|
||||||
|
<string name="unable_to_connect">Unable to connect to hitomi.la</string>
|
||||||
|
|
||||||
<string name="main_search">Search</string>
|
<string name="main_search">Search</string>
|
||||||
<string name="main_no_result">No result</string>
|
<string name="main_no_result">No result</string>
|
||||||
|
|
||||||
<string name="main_drawer_home">Home</string>
|
<string name="main_drawer_home">Home</string>
|
||||||
<string name="main_drawer_history">History</string>
|
<string name="main_drawer_history">History</string>
|
||||||
|
<string name="main_drawer_downloads">Downloads</string>
|
||||||
<string name="main_drawer_group_contact_title">Contact</string>
|
<string name="main_drawer_group_contact_title">Contact</string>
|
||||||
<string name="main_drawer_group_contact_help">Help</string>
|
<string name="main_drawer_group_contact_help">Help</string>
|
||||||
<string name="main_drawer_group_contact_homepage">Visit homepage</string>
|
<string name="main_drawer_group_contact_homepage">Visit homepage</string>
|
||||||
<string name="main_drawer_group_contact_github">Visit github</string>
|
<string name="main_drawer_group_contact_github">Visit github</string>
|
||||||
<string name="main_drawer_group_contact_email">Email me!</string>
|
<string name="main_drawer_group_contact_email">Email me!</string>
|
||||||
|
|
||||||
|
<string name="main_jump_title">Jump to page</string>
|
||||||
|
<string name="main_jump_message">Current page: %1$d\nMaximum page: %2$d</string>
|
||||||
|
|
||||||
|
<string name="main_move">Move to page %1$d</string>
|
||||||
|
|
||||||
<string name="main_dialog_delete">Delete this gallery</string>
|
<string name="main_dialog_delete">Delete this gallery</string>
|
||||||
|
|
||||||
<string name="help_dialog_title">WIP</string>
|
<string name="help_dialog_title">WIP</string>
|
||||||
@@ -47,6 +56,7 @@
|
|||||||
<string name="update_release_note"># Release Note(v%1$s)\n%2$s</string>
|
<string name="update_release_note"># Release Note(v%1$s)\n%2$s</string>
|
||||||
|
|
||||||
<string name="search_hint">Search galleries</string>
|
<string name="search_hint">Search galleries</string>
|
||||||
|
<string name="search_hint_with_page">Search galleries</string>
|
||||||
|
|
||||||
<string name="galleryblock_series">Series: %1$s</string>
|
<string name="galleryblock_series">Series: %1$s</string>
|
||||||
<string name="galleryblock_type">Type: %1$s</string>
|
<string name="galleryblock_type">Type: %1$s</string>
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ allprojects {
|
|||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
|
maven { url "https://jitpack.io" }
|
||||||
maven {
|
maven {
|
||||||
url "s3://finotescore-android/release"
|
url "s3://finotescore-android/release"
|
||||||
credentials(AwsCredentials) {
|
credentials(AwsCredentials) {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import java.util.*
|
|||||||
import javax.net.ssl.HttpsURLConnection
|
import javax.net.ssl.HttpsURLConnection
|
||||||
|
|
||||||
//galleryblock.js
|
//galleryblock.js
|
||||||
fun fetchNozomi(area: String? = null, tag: String = "index", language: String = "all", start: Int = -1, count: Int = -1) : List<Int> {
|
fun fetchNozomi(area: String? = null, tag: String = "index", language: String = "all", start: Int = -1, count: Int = -1) : Pair<List<Int>, Int> {
|
||||||
val url =
|
val url =
|
||||||
when(area) {
|
when(area) {
|
||||||
null -> "$protocol//$domain/$tag-$language$nozomiextension"
|
null -> "$protocol//$domain/$tag-$language$nozomiextension"
|
||||||
@@ -28,6 +28,11 @@ fun fetchNozomi(area: String? = null, tag: String = "index", language: String =
|
|||||||
setRequestProperty("Range", "bytes=$startByte-$endByte")
|
setRequestProperty("Range", "bytes=$startByte-$endByte")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
connect()
|
||||||
|
|
||||||
|
val totalItems = getHeaderField("Content-Range")
|
||||||
|
.replace(Regex("^[Bb]ytes \\d+-\\d+/"), "").toInt() / 4
|
||||||
|
|
||||||
val nozomi = ArrayList<Int>()
|
val nozomi = ArrayList<Int>()
|
||||||
|
|
||||||
val arrayBuffer = ByteBuffer
|
val arrayBuffer = ByteBuffer
|
||||||
@@ -37,10 +42,10 @@ fun fetchNozomi(area: String? = null, tag: String = "index", language: String =
|
|||||||
while (arrayBuffer.hasRemaining())
|
while (arrayBuffer.hasRemaining())
|
||||||
nozomi.add(arrayBuffer.int)
|
nozomi.add(arrayBuffer.int)
|
||||||
|
|
||||||
return nozomi
|
return Pair(nozomi, totalItems)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
return emptyList()
|
return Pair(emptyList(), 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user