From 530da98ec6bdf8bd44caefbaee9d0a5430a8380c Mon Sep 17 00:00:00 2001 From: tom5079 Date: Sat, 1 Jun 2019 21:42:14 +0900 Subject: [PATCH] Bug fix Add paging --- .idea/misc.xml | 2 +- app/build.gradle | 4 +- .../java/xyz/quaver/pupil/MainActivity.kt | 404 +++++++++++++++--- .../java/xyz/quaver/pupil/ReaderActivity.kt | 18 +- .../pupil/adapters/GalleryBlockAdapter.kt | 159 +++---- .../quaver/pupil/util/GalleryDownloader.kt | 21 +- app/src/main/res/drawable/ic_jump.xml | 14 + .../ic_navigate_before_black_24dp.xml | 9 + .../drawable/ic_navigate_next_black_24dp.xml | 9 + .../main/res/layout/activity_main_content.xml | 25 +- app/src/main/res/layout/activity_reader.xml | 3 +- .../main/res/layout/dialog_numberpicker.xml | 10 +- app/src/main/res/layout/item_next.xml | 35 ++ app/src/main/res/layout/item_prev.xml | 35 ++ app/src/main/res/menu/main.xml | 7 +- app/src/main/res/menu/reader.xml | 2 +- app/src/main/res/values-ja/strings.xml | 8 +- app/src/main/res/values-ko/strings.xml | 8 +- app/src/main/res/values-v23/styles.xml | 12 - app/src/main/res/values/strings.xml | 13 +- .../java/xyz/quaver/hitomi/galleryblock.kt | 11 +- 21 files changed, 605 insertions(+), 204 deletions(-) create mode 100644 app/src/main/res/drawable/ic_jump.xml create mode 100644 app/src/main/res/drawable/ic_navigate_before_black_24dp.xml create mode 100644 app/src/main/res/drawable/ic_navigate_next_black_24dp.xml create mode 100644 app/src/main/res/layout/item_next.xml create mode 100644 app/src/main/res/layout/item_prev.xml delete mode 100644 app/src/main/res/values-v23/styles.xml diff --git a/.idea/misc.xml b/.idea/misc.xml index 7631aec3..fb8c126a 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index d34d7924..76304c9d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,8 +9,8 @@ android { applicationId "xyz.quaver.pupil" minSdkVersion 16 targetSdkVersion 28 - versionCode 7 - versionName "2.1" + versionCode 8 + versionName "2.2" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { diff --git a/app/src/main/java/xyz/quaver/pupil/MainActivity.kt b/app/src/main/java/xyz/quaver/pupil/MainActivity.kt index 94470e8f..bbe0c7d3 100644 --- a/app/src/main/java/xyz/quaver/pupil/MainActivity.kt +++ b/app/src/main/java/xyz/quaver/pupil/MainActivity.kt @@ -6,16 +6,17 @@ import android.os.Bundle import android.preference.PreferenceManager import android.text.* import android.text.style.AlignmentSpan -import android.view.LayoutInflater -import android.view.View -import android.view.WindowManager +import android.util.Log +import android.view.* +import android.widget.EditText +import android.widget.ImageView +import android.widget.LinearLayout import android.widget.TextView import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity +import androidx.cardview.widget.CardView import androidx.core.content.res.ResourcesCompat import androidx.core.view.GravityCompat -import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView import com.arlib.floatingsearchview.FloatingSearchView import com.arlib.floatingsearchview.suggestions.model.SearchSuggestion import com.arlib.floatingsearchview.util.view.SearchInputView @@ -39,6 +40,7 @@ import java.net.URL import java.util.* import javax.net.ssl.HttpsURLConnection import kotlin.collections.ArrayList +import kotlin.math.roundToInt class MainActivity : AppCompatActivity() { @@ -56,7 +58,9 @@ class MainActivity : AppCompatActivity() { private val SETTINGS = 45162 private var galleryIDs: Deferred>? = null + private var totalItems = 0 private var loadingJob: Job? = null + private var currentPage = 0 private lateinit var histories: Histories private lateinit var downloads: Histories @@ -64,16 +68,25 @@ class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + val preference = PreferenceManager.getDefaultSharedPreferences(this) + + 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 } - window.setFlags( - WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, - WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS - ) - setContentView(R.layout.activity_main) checkUpdate() @@ -109,6 +122,44 @@ class MainActivity : AppCompatActivity() { 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?) { super.onActivityResult(requestCode, resultCode, data) when(requestCode) { @@ -188,31 +239,16 @@ class MainActivity : AppCompatActivity() { } private fun initView() { + var prevP1 = 0 main_appbar_layout.addOnOffsetChangedListener( AppBarLayout.OnOffsetChangedListener { _, p1 -> main_searchview.translationY = p1.toFloat() - main_recyclerview.translationY = p1.toFloat() + main_recyclerview.scrollBy(0, prevP1 - p1) + + prevP1 = p1 } ) - //SwipeRefreshLayout - with(main_swipe_layout) { - setProgressViewOffset( - false, - resources.getDimensionPixelSize(R.dimen.progress_view_start), - resources.getDimensionPixelSize(R.dimen.progress_view_offset) - ) - - setOnRefreshListener { - post { - cancelFetch() - clearGalleries() - fetchGalleries(query) - loadBlocks() - } - } - } - //NavigationView main_nav_view.setNavigationItemSelectedListener { runOnUiThread { @@ -276,7 +312,7 @@ class MainActivity : AppCompatActivity() { with(main_recyclerview) { adapter = GalleryBlockAdapter(galleries).apply { onChipClickedHandler.add { - post { + runOnUiThread { query = it.toQuery() this@MainActivity.findViewById(R.id.search_bar_text) .setText(query, TextView.BufferType.EDITABLE) @@ -288,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) - .setOnItemClickListener { _, position, _ -> + .setOnItemClickListener { _, position, v -> + + if (v !is CardView) + return@setOnItemClickListener + val intent = Intent(this@MainActivity, ReaderActivity::class.java) val gallery = galleries[position].first intent.putExtra("galleryblock", Json(JsonConfiguration.Stable).stringify(GalleryBlock.serializer(), gallery)) @@ -311,7 +338,11 @@ class MainActivity : AppCompatActivity() { startActivity(intent) histories.add(gallery.id) - }.setOnItemLongClickListener { recyclerView, position, _ -> + }.setOnItemLongClickListener { recyclerView, position, v -> + + if (v !is CardView) + return@setOnItemLongClickListener true + val galleryBlock = galleries[position].first val view = LayoutInflater.from(this@MainActivity) .inflate(R.layout.dialog_galleryblock, recyclerView, false) @@ -358,6 +389,210 @@ class MainActivity : AppCompatActivity() { 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(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(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(R.id.icon_prev) + val text = prev.findViewById(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(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(R.id.icon_next) + val text = next.findViewById(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) { + Log.d("Pupil", "hmm...") + val icon = next.findViewById(R.id.icon_next) + next.layoutParams.height = 1 + icon.layoutParams.height = 1 + icon.rotation = 180f + } + + next?.requestLayout() + + notifyItemRemoved(itemCount) + } + } + } + } + } + } + } + + false + } } } @@ -386,7 +621,33 @@ class MainActivity : AppCompatActivity() { setOnMenuItemClickListener { when(it.itemId) { 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() + } } } @@ -471,7 +732,7 @@ class MainActivity : AppCompatActivity() { if (query != this@MainActivity.query) { this@MainActivity.query = query - CoroutineScope(Dispatchers.Main).launch { + runOnUiThread { cancelFetch() clearGalleries() fetchGalleries(query) @@ -502,12 +763,12 @@ class MainActivity : AppCompatActivity() { this.notifyDataSetChanged() } + main_appbar_layout.setExpanded(true) main_noresult.visibility = View.INVISIBLE 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 perPage = preference.getString("per_page", "25")?.toInt() ?: 25 val defaultQuery = preference.getString("default_query", "")!! @@ -521,27 +782,42 @@ class MainActivity : AppCompatActivity() { when(mode) { Mode.SEARCH -> { when { - query.isEmpty() and defaultQuery.isEmpty() -> - fetchNozomi(start = from, count = perPage) - else -> - doSearch("$defaultQuery $query") + query.isEmpty() and defaultQuery.isEmpty() -> { + fetchNozomi(start = currentPage*perPage, count = perPage).let { + totalItems = it.second + it.first + } + } + else -> doSearch("$defaultQuery $query").apply { + totalItems = size + } } } Mode.HISTORY -> { when { - query.isEmpty() -> histories.toList() + query.isEmpty() -> { + histories.toList().apply { + totalItems = size + } + } else -> { val result = doSearch(query).sorted() - histories.filter { result.binarySearch(it) >= 0 } + histories.filter { result.binarySearch(it) >= 0 }.apply { + totalItems = size + } } } } Mode.DOWNLOAD -> { when { - query.isEmpty() -> downloads.toList() + query.isEmpty() -> downloads.toList().apply { + totalItems = size + } else -> { val result = doSearch(query).sorted() - downloads.filter { result.binarySearch(it) >= 0 } + downloads.filter { result.binarySearch(it) >= 0 }.apply { + totalItems = size + } } } } @@ -566,18 +842,11 @@ class MainActivity : AppCompatActivity() { 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 { - query.isEmpty() and defaultQuery.isEmpty() -> + query.isEmpty() and defaultQuery.isEmpty() and (mode == Mode.SEARCH) -> galleryIDs 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 -> for (chunk in chunks) chunk.map { @@ -635,8 +904,7 @@ class MainActivity : AppCompatActivity() { if (galleryBlock != null) { galleries.add(galleryBlock) - - main_recyclerview.adapter?.notifyItemInserted(galleries.size - 1) + main_recyclerview.adapter!!.notifyItemInserted(galleries.size - 1) } } } diff --git a/app/src/main/java/xyz/quaver/pupil/ReaderActivity.kt b/app/src/main/java/xyz/quaver/pupil/ReaderActivity.kt index 542921f5..a6cd8cc3 100644 --- a/app/src/main/java/xyz/quaver/pupil/ReaderActivity.kt +++ b/app/src/main/java/xyz/quaver/pupil/ReaderActivity.kt @@ -12,12 +12,14 @@ import androidx.recyclerview.widget.PagerSnapHelper import androidx.recyclerview.widget.RecyclerView import androidx.vectordrawable.graphics.drawable.Animatable2Compat 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.view.* import kotlinx.android.synthetic.main.dialog_numberpicker.view.* import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import kotlinx.io.IOException import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonConfiguration import xyz.quaver.hitomi.GalleryBlock @@ -89,7 +91,7 @@ class ReaderActivity : AppCompatActivity() { 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) - with(view.reader_dialog_number_picker) { + with(view.dialog_number_picker) { minValue=1 maxValue=gallerySize value=currentPage @@ -97,8 +99,8 @@ class ReaderActivity : AppCompatActivity() { val dialog = AlertDialog.Builder(this).apply { setView(view) }.create() - view.reader_dialog_ok.setOnClickListener { - (reader_recyclerview.layoutManager as LinearLayoutManager?)?.scrollToPositionWithOffset(view.reader_dialog_number_picker.value-1, 0) + view.dialog_ok.setOnClickListener { + (reader_recyclerview.layoutManager as LinearLayoutManager?)?.scrollToPositionWithOffset(view.dialog_number_picker.value-1, 0) dialog.dismiss() } @@ -135,7 +137,13 @@ class ReaderActivity : AppCompatActivity() { var d: GalleryDownloader? = GalleryDownloader.get(galleryBlock.id) 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 { @@ -170,6 +178,8 @@ class ReaderActivity : AppCompatActivity() { } } onErrorHandler = { + if (it is IOException) + Snackbar.make(reader_layout, R.string.unable_to_connect, Snackbar.LENGTH_LONG).show() downloader.download = false } onCompleteHandler = { diff --git a/app/src/main/java/xyz/quaver/pupil/adapters/GalleryBlockAdapter.kt b/app/src/main/java/xyz/quaver/pupil/adapters/GalleryBlockAdapter.kt index 06ccd862..c75529b7 100644 --- a/app/src/main/java/xyz/quaver/pupil/adapters/GalleryBlockAdapter.kt +++ b/app/src/main/java/xyz/quaver/pupil/adapters/GalleryBlockAdapter.kt @@ -1,12 +1,13 @@ package xyz.quaver.pupil.adapters import android.graphics.BitmapFactory -import android.util.SparseArray +import android.util.Log import android.util.SparseBooleanArray import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.LinearLayout +import android.widget.RelativeLayout import androidx.cardview.widget.CardView import androidx.core.content.ContextCompat import androidx.recyclerview.widget.RecyclerView @@ -27,66 +28,28 @@ import xyz.quaver.pupil.types.Tag import java.io.File import java.util.* import kotlin.collections.ArrayList +import kotlin.collections.HashMap import kotlin.concurrent.schedule class GalleryBlockAdapter(private val galleries: List>>) : RecyclerView.Adapter() { - private enum class ViewType { - VIEW_ITEM, - VIEW_PROG + enum class ViewType { + NEXT, + GALLERY, + PREV } - private fun String.wordCapitalize() : String { - val result = ArrayList() - - for (word in this.split(" ")) - result.add(word.capitalize()) - - return result.joinToString(" ") - } - - var noMore = false - private val refreshTasks = SparseArray() - 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) { + inner class GalleryViewHolder(private val view: CardView) : RecyclerView.ViewHolder(view) { + fun bind(item: Pair>) { + with(view) { val resources = context.resources val languages = resources.getStringArray(R.array.languages).map { it.split("|").let { split -> Pair(split[0], split[1]) } }.toMap() - val (gallery, thumbnail) = galleries[position] - holder.galleryID = gallery.id + val (gallery: GalleryBlock, thumbnail: Deferred) = item val artists = gallery.artists val series = gallery.series @@ -99,7 +62,7 @@ class GalleryBlockAdapter(private val galleries: List { @@ -232,32 +192,85 @@ class GalleryBlockAdapter(private val galleries: List View.GONE - false -> View.VISIBLE + } + class NextViewHolder(view: LinearLayout) : RecyclerView.ViewHolder(view) + class PrevViewHolder(view: LinearLayout) : RecyclerView.ViewHolder(view) + + 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() + + for (word in this.split(" ")) + result.add(word.capitalize()) + + return result.joinToString(" ") + } + + private val refreshTasks = HashMap() + 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) { super.onViewDetachedFromWindow(holder) - if (holder is ViewHolder) { - val galleryID = holder.galleryID ?: return - val task = refreshTasks.get(galleryID) ?: return + if (holder is GalleryViewHolder) { + val task = refreshTasks[holder] ?: return - refreshTasks.remove(galleryID) 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 { return when { - galleries.getOrNull(position) == null -> ViewType.VIEW_PROG.ordinal - else -> ViewType.VIEW_ITEM.ordinal - } + showPrev && position == 0 -> ViewType.PREV + showNext && position == galleries.size+(if (showPrev) 1 else 0) -> ViewType.NEXT + else -> ViewType.GALLERY + }.ordinal } } \ No newline at end of file diff --git a/app/src/main/java/xyz/quaver/pupil/util/GalleryDownloader.kt b/app/src/main/java/xyz/quaver/pupil/util/GalleryDownloader.kt index a557d222..b3657ed9 100644 --- a/app/src/main/java/xyz/quaver/pupil/util/GalleryDownloader.kt +++ b/app/src/main/java/xyz/quaver/pupil/util/GalleryDownloader.kt @@ -55,7 +55,7 @@ class GalleryDownloader( var onReaderLoadedHandler: ((Reader) -> Unit)? = null var onProgressHandler: ((Int) -> Unit)? = null var onDownloadedHandler: ((List) -> Unit)? = null - var onErrorHandler: (() -> Unit)? = null + var onErrorHandler: ((Exception) -> Unit)? = null var onCompleteHandler: (() -> Unit)? = null var onNotifyChangedHandler: ((Boolean) -> Unit)? = null @@ -100,15 +100,13 @@ class GalleryDownloader( } } - //Could not retrieve reader - if (reader.isEmpty()) - throw IOException("Can't retrieve Reader") + if (reader.isNotEmpty()) { + //Save cache + if (!cache.parentFile.exists()) + cache.parentFile.mkdirs() - //Save cache - if (!cache.parentFile.exists()) - cache.parentFile.mkdirs() - - cache.writeText(json.stringify(serializer, reader)) + cache.writeText(json.stringify(serializer, reader)) + } reader } @@ -120,6 +118,9 @@ class GalleryDownloader( downloadJob = CoroutineScope(Dispatchers.Default).launch { val reader = reader.await() + if (reader.isEmpty()) + onErrorHandler?.invoke(IOException("Couldn't retrieve Reader")) + val list = ArrayList() onReaderLoadedHandler?.invoke(reader) @@ -162,7 +163,7 @@ class GalleryDownloader( } catch (e: Exception) { cache.delete() - onErrorHandler?.invoke() + onErrorHandler?.invoke(e) notificationBuilder .setContentTitle(galleryBlock.title) diff --git a/app/src/main/res/drawable/ic_jump.xml b/app/src/main/res/drawable/ic_jump.xml new file mode 100644 index 00000000..e59a1a2a --- /dev/null +++ b/app/src/main/res/drawable/ic_jump.xml @@ -0,0 +1,14 @@ + + + + diff --git a/app/src/main/res/drawable/ic_navigate_before_black_24dp.xml b/app/src/main/res/drawable/ic_navigate_before_black_24dp.xml new file mode 100644 index 00000000..e6bb3ca9 --- /dev/null +++ b/app/src/main/res/drawable/ic_navigate_before_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_navigate_next_black_24dp.xml b/app/src/main/res/drawable/ic_navigate_next_black_24dp.xml new file mode 100644 index 00000000..24835127 --- /dev/null +++ b/app/src/main/res/drawable/ic_navigate_next_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/activity_main_content.xml b/app/src/main/res/layout/activity_main_content.xml index ffebabe9..a5b3b266 100644 --- a/app/src/main/res/layout/activity_main_content.xml +++ b/app/src/main/res/layout/activity_main_content.xml @@ -1,5 +1,6 @@ - - - - - + android:paddingTop="64dp" + android:clipToPadding="false" + android:scrollbars="vertical" + app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/> @@ -71,7 +64,7 @@ android:layout_height="match_parent" app:floatingSearch_searchBarMarginLeft="8dp" app:floatingSearch_searchBarMarginRight="8dp" - app:floatingSearch_searchBarMarginTop="24dp" + app:floatingSearch_searchBarMarginTop="8dp" app:floatingSearch_searchHint="@string/search_hint" app:floatingSearch_suggestionsListAnimDuration="250" app:floatingSearch_showSearchKey="true" diff --git a/app/src/main/res/layout/activity_reader.xml b/app/src/main/res/layout/activity_reader.xml index 59ff93c1..9e49df68 100644 --- a/app/src/main/res/layout/activity_reader.xml +++ b/app/src/main/res/layout/activity_reader.xml @@ -1,5 +1,6 @@ diff --git a/app/src/main/res/layout/dialog_numberpicker.xml b/app/src/main/res/layout/dialog_numberpicker.xml index d9167359..943ab6ac 100644 --- a/app/src/main/res/layout/dialog_numberpicker.xml +++ b/app/src/main/res/layout/dialog_numberpicker.xml @@ -7,7 +7,7 @@