Merge pull request #8 from tom5079/development

Version 2.7
This commit is contained in:
tom5079
2019-06-08 15:33:19 +09:00
committed by GitHub
22 changed files with 416 additions and 114 deletions

View File

@@ -9,8 +9,8 @@ android {
applicationId "xyz.quaver.pupil"
minSdkVersion 16
targetSdkVersion 28
versionCode 11
versionName "2.5.2"
versionCode 14
versionName "2.7"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {

View File

@@ -3,6 +3,7 @@ package xyz.quaver.pupil
import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.drawable.Animatable
import android.net.Uri
import android.os.Bundle
import android.os.Environment
@@ -21,6 +22,7 @@ import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.core.content.res.ResourcesCompat
import androidx.core.view.GravityCompat
import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat
import com.arlib.floatingsearchview.FloatingSearchView
import com.arlib.floatingsearchview.suggestions.model.SearchSuggestion
import com.arlib.floatingsearchview.util.view.SearchInputView
@@ -31,14 +33,20 @@ import kotlinx.android.synthetic.main.activity_main_content.*
import kotlinx.android.synthetic.main.dialog_galleryblock.view.*
import kotlinx.coroutines.*
import kotlinx.io.IOException
import kotlinx.serialization.ImplicitReflectionSerializer
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.content
import kotlinx.serialization.list
import kotlinx.serialization.parseList
import kotlinx.serialization.stringify
import ru.noties.markwon.Markwon
import xyz.quaver.hitomi.*
import xyz.quaver.pupil.adapters.GalleryBlockAdapter
import xyz.quaver.pupil.types.Tag
import xyz.quaver.pupil.types.TagSuggestion
import xyz.quaver.pupil.types.Tags
import xyz.quaver.pupil.util.*
import java.io.File
import java.io.FileInputStream
@@ -56,7 +64,8 @@ class MainActivity : AppCompatActivity() {
enum class Mode {
SEARCH,
HISTORY,
DOWNLOAD
DOWNLOAD,
FAVORITE
}
private val galleries = ArrayList<Pair<GalleryBlock, Deferred<String>>>()
@@ -73,6 +82,7 @@ class MainActivity : AppCompatActivity() {
private lateinit var histories: Histories
private lateinit var downloads: Histories
private lateinit var favorites: Histories
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -96,6 +106,7 @@ class MainActivity : AppCompatActivity() {
with(application as Pupil) {
this@MainActivity.histories = histories
this@MainActivity.downloads = downloads
this@MainActivity.favorites = favorites
}
setContentView(R.layout.activity_main)
@@ -274,6 +285,7 @@ class MainActivity : AppCompatActivity() {
R.id.main_drawer_home -> {
cancelFetch()
clearGalleries()
currentPage = 0
query = ""
mode = Mode.SEARCH
fetchGalleries(query)
@@ -282,6 +294,7 @@ class MainActivity : AppCompatActivity() {
R.id.main_drawer_history -> {
cancelFetch()
clearGalleries()
currentPage = 0
query = ""
mode = Mode.HISTORY
fetchGalleries(query)
@@ -290,11 +303,21 @@ class MainActivity : AppCompatActivity() {
R.id.main_drawer_downloads -> {
cancelFetch()
clearGalleries()
currentPage = 0
query = ""
mode = Mode.DOWNLOAD
fetchGalleries(query)
loadBlocks()
}
R.id.main_drawer_favorite -> {
cancelFetch()
clearGalleries()
currentPage = 0
query = ""
mode = Mode.FAVORITE
fetchGalleries(query)
loadBlocks()
}
R.id.main_drawer_help -> {
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.help))))
}
@@ -686,6 +709,7 @@ class MainActivity : AppCompatActivity() {
}
private var suggestionJob : Job? = null
@UseExperimental(ImplicitReflectionSerializer::class)
private fun setupSearchBar() {
val searchInputView = findViewById<SearchInputView>(R.id.search_bar_text)
//Change upper case letters to lower case
@@ -707,16 +731,24 @@ class MainActivity : AppCompatActivity() {
})
with(main_searchview as FloatingSearchView) {
val favoritesFile = File(ContextCompat.getDataDir(context), "favorites_tags.json")
val json = Json(JsonConfiguration.Stable)
val serializer = Tag.serializer().list
if (!favoritesFile.exists()) {
favoritesFile.createNewFile()
favoritesFile.writeText(json.stringify(Tags(listOf())))
}
setOnMenuItemClickListener {
when(it.itemId) {
R.id.main_menu_settings -> startActivityForResult(Intent(this@MainActivity, SettingsActivity::class.java), SETTINGS)
R.id.main_menu_page_indicator -> {
R.id.main_menu_jump -> {
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(
@@ -737,6 +769,32 @@ class MainActivity : AppCompatActivity() {
}
}.show()
}
R.id.main_menu_id -> {
val editText = EditText(context)
AlertDialog.Builder(context).apply {
setView(editText)
setTitle(R.string.main_open_gallery_by_id)
setPositiveButton(android.R.string.ok) { _, _ ->
CoroutineScope(Dispatchers.Default).launch {
try {
val intent = Intent(this@MainActivity, ReaderActivity::class.java)
val gallery =
getGalleryBlock(editText.text.toString().toInt()) ?: throw Exception()
intent.putExtra(
"galleryblock",
Json(JsonConfiguration.Stable).stringify(GalleryBlock.serializer(), gallery)
)
startActivity(intent)
} catch (e: Exception) {
Snackbar.make(main_layout, R.string.main_open_gallery_by_id_error, Snackbar.LENGTH_LONG).show()
}
}
}
}.show()
}
}
}
@@ -751,7 +809,15 @@ class MainActivity : AppCompatActivity() {
suggestionJob?.cancel()
suggestionJob = CoroutineScope(Dispatchers.IO).launch {
val suggestions = getSuggestionsForQuery(currentQuery).map { TagSuggestion(it) }
val suggestions = ArrayList(getSuggestionsForQuery(currentQuery).map { TagSuggestion(it) })
suggestions.filter {
val tag = "${it.n}:${it.s.replace(Regex("\\s"), "_")}"
Tags(json.parse(serializer, favoritesFile.readText())).contains(tag)
}.reversed().forEach {
suggestions.remove(it)
suggestions.add(0, it)
}
withContext(Dispatchers.Main) {
swapSuggestions(suggestions)
@@ -759,8 +825,9 @@ class MainActivity : AppCompatActivity() {
}
}
setOnBindSuggestionCallback { _, leftIcon, textView, item, _ ->
setOnBindSuggestionCallback { suggestionView, leftIcon, textView, item, _ ->
val suggestion = item as TagSuggestion
val tag = "${suggestion.n}:${suggestion.s.replace(Regex("\\s"), "_")}"
leftIcon.setImageDrawable(
ResourcesCompat.getDrawable(
@@ -778,16 +845,52 @@ class MainActivity : AppCompatActivity() {
null)
)
val text = "${suggestion.s}\n ${suggestion.t}"
with(suggestionView.findViewById<ImageView>(R.id.right_icon)) {
val len = text.length
val left = suggestion.s.length
if (Tags(json.parse(serializer, favoritesFile.readText())).contains(tag))
setImageResource(R.drawable.ic_star_filled)
else
setImageResource(R.drawable.ic_star_empty)
textView.text = SpannableString(text).apply {
val s = AlignmentSpan.Standard(Layout.Alignment.ALIGN_OPPOSITE)
setSpan(s, left, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
setSpan(SetLineOverlap(true), 1, len-2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
setSpan(SetLineOverlap(false), len-1, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
visibility = View.VISIBLE
rotation = 0f
isEnabled = true
setColorFilter(ContextCompat.getColor(context, R.color.material_orange_500))
isClickable = true
setOnClickListener {
val favorites = Tags(json.parse(serializer, favoritesFile.readText()))
if (favorites.contains(tag)) {
setImageResource(R.drawable.ic_star_empty)
favorites.remove(tag)
}
else {
setImageDrawable(AnimatedVectorDrawableCompat.create(context, R.drawable.avd_star))
(drawable as Animatable).start()
favorites.add(tag)
}
favoritesFile.writeText(json.stringify(favorites))
}
}
if (suggestion.t == -1) {
textView.text = suggestion.s
} else {
val text = "${suggestion.s}\n ${suggestion.t}"
val len = text.length
val left = suggestion.s.length
textView.text = SpannableString(text).apply {
val s = AlignmentSpan.Standard(Layout.Alignment.ALIGN_OPPOSITE)
setSpan(s, left, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
setSpan(SetLineOverlap(true), 1, len-2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
setSpan(SetLineOverlap(false), len-1, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}
}
}
@@ -810,7 +913,10 @@ class MainActivity : AppCompatActivity() {
setOnFocusChangeListener(object: FloatingSearchView.OnFocusChangeListener {
override fun onFocus() {
//Do Nothing
if (searchInputView.text.isEmpty())
swapSuggestions(json.parse(serializer, favoritesFile.readText()).map {
TagSuggestion(it.tag, -1, "", it.area ?: "tag")
})
}
override fun onFocusCleared() {
@@ -824,6 +930,7 @@ class MainActivity : AppCompatActivity() {
runOnUiThread {
cancelFetch()
clearGalleries()
currentPage = 0
fetchGalleries(query)
loadBlocks()
}
@@ -910,6 +1017,19 @@ class MainActivity : AppCompatActivity() {
}
}
}
Mode.FAVORITE -> {
when {
query.isEmpty() -> favorites.toList().apply {
totalItems = size
}
else -> {
val result = doSearch(query).sorted()
favorites.filter { result.binarySearch(it) >= 0 }.apply {
totalItems = size
}
}
}
}
}
}
}

View File

@@ -16,12 +16,14 @@ class Pupil : ObservableApplication() {
lateinit var histories: Histories
lateinit var downloads: Histories
lateinit var favorites: Histories
override fun onCreate() {
val preference = PreferenceManager.getDefaultSharedPreferences(this)
histories = Histories(File(ContextCompat.getDataDir(this), "histories.json"))
downloads = Histories(File(ContextCompat.getDataDir(this), "downloads.json"))
favorites = Histories(File(ContextCompat.getDataDir(this), "favorites.json"))
super.onCreate()
Fn.init(this)

View File

@@ -1,10 +1,12 @@
package xyz.quaver.pupil
import android.graphics.drawable.Animatable
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.view.*
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.LinearSmoothScroller
@@ -20,12 +22,19 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.io.IOException
import kotlinx.serialization.ImplicitReflectionSerializer
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration
import kotlinx.serialization.list
import kotlinx.serialization.stringify
import xyz.quaver.hitomi.GalleryBlock
import xyz.quaver.pupil.adapters.ReaderAdapter
import xyz.quaver.pupil.types.Tag
import xyz.quaver.pupil.types.Tags
import xyz.quaver.pupil.util.GalleryDownloader
import xyz.quaver.pupil.util.Histories
import xyz.quaver.pupil.util.ItemClickSupport
import java.io.File
class ReaderActivity : AppCompatActivity() {
@@ -43,9 +52,13 @@ class ReaderActivity : AppCompatActivity() {
private var menu: Menu? = null
private lateinit var favorites: Histories
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
favorites = (application as Pupil).favorites
window.setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE)
@@ -81,8 +94,17 @@ class ReaderActivity : AppCompatActivity() {
super.onResume()
}
@UseExperimental(ImplicitReflectionSerializer::class)
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.reader, menu)
with(menu?.findItem(R.id.reader_menu_favorite)) {
this ?: return@with
if (favorites.contains(galleryBlock.id))
(icon as Animatable).start()
}
this.menu = menu
return true
}
@@ -106,6 +128,18 @@ class ReaderActivity : AppCompatActivity() {
dialog.show()
}
R.id.reader_menu_favorite -> {
val id = galleryBlock.id
val favorite = menu?.findItem(R.id.reader_menu_favorite) ?: return true
if (favorites.contains(id)) {
favorites.remove(id)
favorite.icon = AnimatedVectorDrawableCompat.create(this, R.drawable.avd_star)
} else {
favorites.add(id)
(favorite.icon as Animatable).start()
}
}
}
return true

View File

@@ -1,6 +1,8 @@
package xyz.quaver.pupil.adapters
import android.graphics.BitmapFactory
import android.graphics.drawable.Animatable
import android.util.Log
import android.util.SparseBooleanArray
import android.view.LayoutInflater
import android.view.View
@@ -21,8 +23,10 @@ import kotlinx.serialization.json.JsonConfiguration
import kotlinx.serialization.list
import xyz.quaver.hitomi.GalleryBlock
import xyz.quaver.hitomi.ReaderItem
import xyz.quaver.pupil.Pupil
import xyz.quaver.pupil.R
import xyz.quaver.pupil.types.Tag
import xyz.quaver.pupil.util.Histories
import java.io.File
import java.util.*
import kotlin.collections.ArrayList
@@ -37,6 +41,8 @@ class GalleryBlockAdapter(private val galleries: List<Pair<GalleryBlock, Deferre
PREV
}
private lateinit var favorites: Histories
inner class GalleryViewHolder(private val view: CardView) : RecyclerView.ViewHolder(view) {
fun bind(item: Pair<GalleryBlock, Deferred<String>>) {
with(view) {
@@ -202,6 +208,27 @@ class GalleryBlockAdapter(private val galleries: List<Pair<GalleryBlock, Deferre
galleryblock_tag_group.addView(chip)
}
if (!::favorites.isInitialized)
favorites = (context.applicationContext as Pupil).favorites
with(galleryblock_favorite) {
post {
isChecked = favorites.contains(gallery.id)
}
setOnClickListener {
when {
isChecked -> favorites.add(gallery.id)
else -> favorites.remove(gallery.id)
}
}
setOnCheckedChangeListener { _, isChecked ->
when {
isChecked -> (background as Animatable).start()
else -> background = AnimatedVectorDrawableCompat.create(context, R.drawable.avd_star)
}
}
}
}
}
}

View File

@@ -1,5 +1,6 @@
package xyz.quaver.pupil.adapters
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.view.LayoutInflater
import android.view.View

View File

@@ -1,5 +1,8 @@
package xyz.quaver.pupil.types
import kotlinx.serialization.Serializable
@Serializable
data class Tag(val area: String?, val tag: String, val isNegative: Boolean = false) {
companion object {
fun parse(tag: String) : Tag {

View File

@@ -104,7 +104,13 @@ class GalleryDownloader(
val cached = json.parse(serializer, cache.readText())
if (cached.isNotEmpty()) {
useHiyobi = when {
cached.first().url.contains("hitomi.la") -> false
else -> true
}
onReaderLoadedHandler?.invoke(cached)
return@async cached
}
}

View File

@@ -0,0 +1,37 @@
<animated-vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="newApi">
<aapt:attr name="android:drawable">
<vector
android:name="vector"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:name="path"
android:pathData="M 12 15.39 L 8.24 17.66 L 9.23 13.38 L 5.91 10.5 L 10.29 10.13 L 12 6.09 L 13.71 10.13 L 18.09 10.5 L 14.77 13.38 L 15.76 17.66 M 22 9.24 L 14.81 8.63 L 12 2 L 9.19 8.63 L 2 9.24 L 7.45 13.97 L 5.82 21 L 12 17.27 L 18.18 21 L 16.54 13.97 L 22 9.24 Z"
android:fillColor="#000"/>
<clip-path
android:name="clip"
android:pathData="M 2 21 L 2 21 L 22 21 L 22 21 Z"/>
<path
android:name="path_1"
android:pathData="M 12 17.27 L 18.18 21 L 16.54 13.97 L 22 9.24 L 14.81 8.62 L 12 2 L 9.19 8.62 L 2 9.24 L 7.45 13.97 L 5.82 21 L 12 17.27 Z"
android:fillColor="#000"/>
</vector>
</aapt:attr>
<target android:name="clip">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="pathData"
android:duration="500"
android:valueFrom="M 2 21 L 2 21 L 22 21 L 22 21 Z"
android:valueTo="M 2 2 L 2 21 L 22 21 L 22 2 Z"
android:valueType="pathType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
</animated-vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 B

View File

@@ -0,0 +1,4 @@
<vector android:height="24dp" android:width="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#000" android:pathData="M 12 15.39 L 8.24 17.66 L 9.23 13.38 L 5.91 10.5 L 10.29 10.13 L 12 6.09 L 13.71 10.13 L 18.09 10.5 L 14.77 13.38 L 15.76 17.66 M 22 9.24 L 14.81 8.63 L 12 2 L 9.19 8.63 L 2 9.24 L 7.45 13.97 L 5.82 21 L 12 17.27 L 18.18 21 L 16.54 13.97 L 22 9.24 Z"/>
</vector>

View File

@@ -0,0 +1,4 @@
<vector android:height="24dp" android:width="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#000" android:pathData="M 12 17.27 L 18.18 21 L 16.54 13.97 L 22 9.24 L 14.81 8.62 L 12 2 L 9.19 8.62 L 2 9.24 L 7.45 13.97 L 5.82 21 L 12 17.27 Z"/>
</vector>

View File

@@ -14,111 +14,145 @@
android:focusable="true"
android:clickable="true">
<androidx.constraintlayout.widget.ConstraintLayout
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="wrap_content"
android:orientation="vertical">
<ProgressBar
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:id="@+id/galleryblock_progressbar"
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="4dp"
android:visibility="gone"
app:layout_constraintTop_toTopOf="parent"/>
android:layout_height="wrap_content">
<ImageView
android:id="@+id/galleryblock_progress_complete"
android:layout_width="match_parent"
android:layout_height="4dp"
android:visibility="invisible"
android:scaleType="fitXY"
android:contentDescription="@string/reader_imageview_description"
app:layout_constraintTop_toTopOf="parent"/>
<ProgressBar
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:id="@+id/galleryblock_progressbar"
android:layout_width="match_parent"
android:layout_height="4dp"
android:visibility="gone"
app:layout_constraintTop_toTopOf="parent"/>
<ImageView
android:id="@+id/galleryblock_thumbnail"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:contentDescription="@string/galleryblock_thumbnail_description"
android:adjustViewBounds="true"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/galleryblock_progressbar"
app:layout_constraintBottom_toBottomOf="parent"/>
<ImageView
android:id="@+id/galleryblock_progress_complete"
android:layout_width="match_parent"
android:layout_height="4dp"
android:visibility="invisible"
android:scaleType="fitXY"
android:contentDescription="@string/reader_imageview_description"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
style="@style/TextAppearance.AppCompat.Headline"
android:id="@+id/galleryblock_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
app:layout_constraintLeft_toRightOf="@id/galleryblock_thumbnail"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<ImageView
android:id="@+id/galleryblock_thumbnail"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:contentDescription="@string/galleryblock_thumbnail_description"
android:adjustViewBounds="true"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/galleryblock_progressbar"
app:layout_constraintBottom_toBottomOf="parent"/>
<TextView
style="@style/TextAppearance.AppCompat.Medium"
android:id="@+id/galleryblock_artist"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
app:layout_constraintLeft_toRightOf="@id/galleryblock_thumbnail"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/galleryblock_title"/>
<TextView
style="@style/TextAppearance.AppCompat.Headline"
android:id="@+id/galleryblock_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
app:layout_constraintLeft_toRightOf="@id/galleryblock_thumbnail"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="@+id/galleryblock_series"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
app:layout_constraintTop_toBottomOf="@id/galleryblock_artist"
app:layout_constraintStart_toEndOf="@id/galleryblock_thumbnail"
app:layout_constraintEnd_toEndOf="parent"/>
<TextView
style="@style/TextAppearance.AppCompat.Medium"
android:id="@+id/galleryblock_artist"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
app:layout_constraintLeft_toRightOf="@id/galleryblock_thumbnail"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/galleryblock_title"/>
<TextView
android:id="@+id/galleryblock_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
app:layout_constraintTop_toBottomOf="@id/galleryblock_series"
app:layout_constraintStart_toEndOf="@id/galleryblock_thumbnail" />
<TextView
android:id="@+id/galleryblock_series"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
app:layout_constraintTop_toBottomOf="@id/galleryblock_artist"
app:layout_constraintStart_toEndOf="@id/galleryblock_thumbnail"
app:layout_constraintEnd_toEndOf="parent"/>
<TextView
android:id="@+id/galleryblock_language"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintTop_toBottomOf="@id/galleryblock_type"
app:layout_constraintBottom_toTopOf="@id/galleryblock_padding"
app:layout_constraintStart_toEndOf="@id/galleryblock_thumbnail" />
<TextView
android:id="@+id/galleryblock_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
app:layout_constraintTop_toBottomOf="@id/galleryblock_series"
app:layout_constraintStart_toEndOf="@id/galleryblock_thumbnail" />
<TextView
android:id="@+id/galleryblock_language"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintTop_toBottomOf="@id/galleryblock_type"
app:layout_constraintBottom_toTopOf="@id/galleryblock_padding"
app:layout_constraintStart_toEndOf="@id/galleryblock_thumbnail" />
<View
android:id="@+id/galleryblock_padding"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/galleryblock_language"
app:layout_constraintBottom_toTopOf="@id/galleryblock_tag_group"/>
<com.google.android.material.chip.ChipGroup
android:id="@+id/galleryblock_tag_group"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
app:layout_constraintTop_toBottomOf="@id/galleryblock_padding"
app:layout_constraintLeft_toRightOf="@id/galleryblock_thumbnail"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<View
android:id="@+id/galleryblock_padding"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintStart_toEndOf="@id/galleryblock_thumbnail"
app:layout_constraintTop_toBottomOf="@id/galleryblock_language"
app:layout_constraintBottom_toTopOf="@id/galleryblock_tag_group"/>
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_margin="8dp"
android:background="@android:color/darker_gray"/>
<com.google.android.material.chip.ChipGroup
android:id="@+id/galleryblock_tag_group"
android:layout_width="0dp"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
app:layout_constraintLeft_toRightOf="@id/galleryblock_thumbnail"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/galleryblock_padding"
app:layout_constraintBottom_toBottomOf="parent"/>
android:orientation="horizontal"
android:gravity="end">
</androidx.constraintlayout.widget.ConstraintLayout>
<ToggleButton
android:id="@+id/galleryblock_favorite"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="8dp"
android:background="@drawable/avd_star"
android:backgroundTint="@color/material_orange_500"
android:text=""
android:textOn=""
android:textOff=""/>
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>

View File

@@ -14,6 +14,10 @@
<item android:id="@+id/main_drawer_downloads"
android:title="@string/main_drawer_downloads"
android:icon="@drawable/ic_download"/>
<item android:id="@+id/main_drawer_favorite"
android:title="@string/main_drawer_favorite"
android:icon="@drawable/ic_star_filled"/>
</group>
<item android:title="@string/main_drawer_group_contact_title">

View File

@@ -2,9 +2,14 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/main_menu_page_indicator"
<item android:id="@+id/main_menu_jump"
android:icon="@drawable/ic_jump"
android:title="@string/page_indicator_placeholder"
android:title="@string/main_jump_title"
app:showAsAction="ifRoom"/>
<item android:id="@+id/main_menu_id"
android:icon="@drawable/ic_numeric"
android:title="@string/main_open_gallery_by_id"
app:showAsAction="ifRoom"/>
<item

View File

@@ -2,6 +2,12 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/reader_menu_favorite"
android:title=""
android:iconTint="@color/material_orange_500"
android:icon="@drawable/avd_star"
app:showAsAction="always"/>
<item android:id="@+id/reader_menu_use_hiyobi"
android:title=""
android:icon="@drawable/ic_hiyobi"

View File

@@ -67,4 +67,7 @@
<string name="settings_clear_downloads">ダウンロード削除</string>
<string name="settings_clear_downloads_alert_message">ダウンロードしたギャラリーを全て削除します。\n実行しますか</string>
<string name="settings_use_hiyobi_summary">ロード速度を向上させるため可能であればhiyobi.meからイメージロード</string>
<string name="main_drawer_favorite">お気に入り</string>
<string name="main_open_gallery_by_id">ギャラリー番号で見る</string>
<string name="main_open_gallery_by_id_error">エラーが発生しました</string>
</resources>

View File

@@ -67,4 +67,7 @@
<string name="settings_clear_downloads">다운로드 삭제</string>
<string name="settings_clear_downloads_alert_message">다운로드 된 만화를 모두 삭제합니다.\n계속하시겠습니까?</string>
<string name="settings_use_hiyobi_summary">속도 향상을 위해 가능하면 hiyobi.me에서 이미지 로드</string>
<string name="main_drawer_favorite">즐겨찾기</string>
<string name="main_open_gallery_by_id">갤러리 번호로 열기</string>
<string name="main_open_gallery_by_id_error">갤러리를 찾지 못했습니다</string>
</resources>

View File

@@ -8,4 +8,5 @@
<color name="material_pink_600">#d81b60</color>
<color name="material_blue_700">#1976d2</color>
<color name="material_green_a700">#00c853</color>
<color name="material_orange_500">#ff9800</color>
</resources>

View File

@@ -4,8 +4,8 @@
<string name="release_url" translatable="false">https://api.github.com/repos/tom5079/Pupil-issue/releases</string>
<string name="release_name" translatable="false">Pupil-v(\\d+\\.)+\\d+\\.apk</string>
<string name="home_page" translatable="false">https://tom5079.github.io/Pupil</string>
<string name="help" translatable="false">https://tom5079.github.io/Pupil/2019/06/06/manual-kr.html</string>
<string name="home_page" translatable="false">http://bit.ly/2ZlOjXJ</string>
<string name="help" translatable="false">http://bit.ly/2Z7lNZE</string>
<string name="github" translatable="false">https://github.com/tom5079/Pupil-issue/issues/new/choose</string>
<string name="email" translatable="false">mailto:pupil.hentai@gmail.com</string>
@@ -35,6 +35,7 @@
<string name="main_drawer_home">Home</string>
<string name="main_drawer_history">History</string>
<string name="main_drawer_downloads">Downloads</string>
<string name="main_drawer_favorite">Favorites</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_homepage">Visit homepage</string>
@@ -43,6 +44,8 @@
<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_open_gallery_by_id">Open Gallery by ID</string>
<string name="main_open_gallery_by_id_error">Failed to open gallery</string>
<string name="main_move">Move to page %1$d</string>

View File

@@ -11,9 +11,11 @@ fun doSearch(query: String) : List<Int> {
val terms = query
.trim()
.replace(Regex("""^\?"""), "")
.replace('_', ' ')
.toLowerCase()
.split(Regex("\\s+"))
.map {
it.replace('_', ' ')
}
val positiveTerms = LinkedList<String>()
val negativeTerms = LinkedList<String>()
@@ -42,7 +44,8 @@ fun doSearch(query: String) : List<Int> {
//positive results
positiveTerms.map {
launch(searchDispatcher) {
filterPositive(getGalleryIDsForQuery(it).sorted())
val newResults = getGalleryIDsForQuery(it)
filterPositive(newResults.sorted())
}
}.forEach {
it.join()

View File

@@ -7,7 +7,9 @@ import java.net.URL
class UnitTest {
@Test
fun test() {
print(File("C:\\asdf").list()?.size ?: 0)
val galleries = getGalleryIDsForQuery("series:touhou_project")
println(galleries.size)
}
@Test