Added gallery details
Added dark mode
This commit is contained in:
@@ -14,7 +14,7 @@ android {
|
|||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 29
|
targetSdkVersion 29
|
||||||
versionCode 26
|
versionCode 26
|
||||||
versionName "3.2"
|
versionName "3.2-beta"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
@@ -25,7 +25,7 @@ android {
|
|||||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
buildTypes.each {
|
buildTypes.each {
|
||||||
it.buildConfigField('boolean', 'PRERELEASE', 'false')
|
it.buildConfigField('boolean', 'PRERELEASE', 'true')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
@@ -50,12 +50,13 @@ dependencies {
|
|||||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||||
implementation 'androidx.preference:preference:1.1.0-rc01'
|
implementation 'androidx.preference:preference:1.1.0-rc01'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||||
|
implementation 'androidx.gridlayout:gridlayout:1.0.0'
|
||||||
implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'
|
implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'
|
||||||
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.0.0'
|
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.0.0'
|
||||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||||
implementation 'com.android.support:multidex:1.0.3'
|
implementation 'com.android.support:multidex:1.0.3'
|
||||||
implementation 'com.google.android.material:material:1.0.0'
|
implementation 'com.google.android.material:material:1.1.0-alpha08'
|
||||||
implementation 'com.google.firebase:firebase-core:17.0.0'
|
implementation 'com.google.firebase:firebase-core:17.0.1'
|
||||||
implementation 'com.google.firebase:firebase-perf:18.0.1'
|
implementation 'com.google.firebase:firebase-perf:18.0.1'
|
||||||
implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1'
|
implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1'
|
||||||
implementation 'com.github.arimorty:floatingsearchview:2.1.1'
|
implementation 'com.github.arimorty:floatingsearchview:2.1.1'
|
||||||
|
|||||||
@@ -18,13 +18,10 @@
|
|||||||
|
|
||||||
package xyz.quaver.pupil
|
package xyz.quaver.pupil
|
||||||
|
|
||||||
import android.app.DownloadManager
|
|
||||||
import android.app.Notification
|
import android.app.Notification
|
||||||
import android.app.NotificationChannel
|
import android.app.NotificationChannel
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
import android.content.BroadcastReceiver
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
@@ -76,6 +73,11 @@ class Pupil : MultiDexApplication() {
|
|||||||
preference.edit().putBoolean("channel_created", true).apply()
|
preference.edit().putBoolean("channel_created", true).apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AppCompatDelegate.setDefaultNightMode(when (preference.getBoolean("dark_mode", false)) {
|
||||||
|
true -> AppCompatDelegate.MODE_NIGHT_YES
|
||||||
|
false -> AppCompatDelegate.MODE_NIGHT_NO
|
||||||
|
})
|
||||||
|
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,20 +18,17 @@
|
|||||||
|
|
||||||
package xyz.quaver.pupil.adapters
|
package xyz.quaver.pupil.adapters
|
||||||
|
|
||||||
import android.app.AlertDialog
|
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
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.ArrayAdapter
|
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
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
|
||||||
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.bumptech.glide.Glide
|
|
||||||
import com.bumptech.glide.RequestManager
|
import com.bumptech.glide.RequestManager
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||||
import com.google.android.material.chip.Chip
|
import com.google.android.material.chip.Chip
|
||||||
@@ -49,6 +46,7 @@ import xyz.quaver.pupil.R
|
|||||||
import xyz.quaver.pupil.types.Tag
|
import xyz.quaver.pupil.types.Tag
|
||||||
import xyz.quaver.pupil.util.Histories
|
import xyz.quaver.pupil.util.Histories
|
||||||
import xyz.quaver.pupil.util.getCachedGallery
|
import xyz.quaver.pupil.util.getCachedGallery
|
||||||
|
import xyz.quaver.pupil.util.wordCapitalize
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
@@ -168,19 +166,6 @@ class GalleryBlockAdapter(private val glide: RequestManager, private val galleri
|
|||||||
artists.isNotEmpty() -> View.VISIBLE
|
artists.isNotEmpty() -> View.VISIBLE
|
||||||
else -> View.GONE
|
else -> View.GONE
|
||||||
}
|
}
|
||||||
setOnClickListener {
|
|
||||||
if (artists.size > 1) {
|
|
||||||
AlertDialog.Builder(context).apply {
|
|
||||||
setAdapter(ArrayAdapter(context, android.R.layout.select_dialog_item, artists)) { _, index ->
|
|
||||||
for (callback in onChipClickedHandler)
|
|
||||||
callback.invoke(Tag("artist", artists[index]))
|
|
||||||
}
|
|
||||||
}.show()
|
|
||||||
} else {
|
|
||||||
for(callback in onChipClickedHandler)
|
|
||||||
callback.invoke(Tag("artist", artists.first()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
with(galleryblock_series) {
|
with(galleryblock_series) {
|
||||||
text =
|
text =
|
||||||
@@ -191,31 +176,8 @@ class GalleryBlockAdapter(private val glide: RequestManager, private val galleri
|
|||||||
series.isNotEmpty() -> View.VISIBLE
|
series.isNotEmpty() -> View.VISIBLE
|
||||||
else -> View.GONE
|
else -> View.GONE
|
||||||
}
|
}
|
||||||
setOnClickListener {
|
|
||||||
setOnClickListener {
|
|
||||||
if (series.size > 1) {
|
|
||||||
AlertDialog.Builder(context).apply {
|
|
||||||
setAdapter(ArrayAdapter(context, android.R.layout.select_dialog_item, series)) { _, index ->
|
|
||||||
for (callback in onChipClickedHandler)
|
|
||||||
callback.invoke(Tag("series", series[index]))
|
|
||||||
}
|
|
||||||
}.show()
|
|
||||||
} else {
|
|
||||||
for(callback in onChipClickedHandler)
|
|
||||||
callback.invoke(Tag("series", series.first()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
with(galleryblock_type) {
|
|
||||||
text = resources.getString(R.string.galleryblock_type, galleryBlock.type).wordCapitalize()
|
|
||||||
setOnClickListener {
|
|
||||||
setOnClickListener {
|
|
||||||
for(callback in onChipClickedHandler)
|
|
||||||
callback.invoke(Tag("type", galleryBlock.type))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
galleryblock_type.text = resources.getString(R.string.galleryblock_type, galleryBlock.type).wordCapitalize()
|
||||||
with(galleryblock_language) {
|
with(galleryblock_language) {
|
||||||
text =
|
text =
|
||||||
resources.getString(R.string.galleryblock_language, languages[galleryBlock.language])
|
resources.getString(R.string.galleryblock_language, languages[galleryBlock.language])
|
||||||
@@ -223,48 +185,37 @@ class GalleryBlockAdapter(private val glide: RequestManager, private val galleri
|
|||||||
galleryBlock.language.isNotEmpty() -> View.VISIBLE
|
galleryBlock.language.isNotEmpty() -> View.VISIBLE
|
||||||
else -> View.GONE
|
else -> View.GONE
|
||||||
}
|
}
|
||||||
setOnClickListener {
|
|
||||||
setOnClickListener {
|
|
||||||
for(callback in onChipClickedHandler)
|
|
||||||
callback.invoke(Tag("language", galleryBlock.language))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
galleryblock_tag_group.removeAllViews()
|
galleryblock_tag_group.removeAllViews()
|
||||||
galleryBlock.relatedTags.forEach {
|
galleryBlock.relatedTags.forEach {
|
||||||
val tag = Tag.parse(it).let { tag ->
|
galleryblock_tag_group.addView(Chip(context).apply {
|
||||||
when {
|
val tag = Tag.parse(it).let { tag ->
|
||||||
tag.area != null -> tag
|
when {
|
||||||
else -> Tag("tag", it)
|
tag.area != null -> tag
|
||||||
|
else -> Tag("tag", it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
val chip = LayoutInflater.from(context)
|
chipIcon = when(tag.area) {
|
||||||
.inflate(R.layout.tag_chip, this, false) as Chip
|
"male" -> {
|
||||||
|
setChipBackgroundColorResource(R.color.material_blue_700)
|
||||||
val icon = when(tag.area) {
|
setTextColor(ContextCompat.getColor(context, android.R.color.white))
|
||||||
"male" -> {
|
ContextCompat.getDrawable(context, R.drawable.ic_gender_male_white)
|
||||||
chip.setChipBackgroundColorResource(R.color.material_blue_700)
|
}
|
||||||
chip.setTextColor(ContextCompat.getColor(context, android.R.color.white))
|
"female" -> {
|
||||||
ContextCompat.getDrawable(context, R.drawable.ic_gender_male_white)
|
setChipBackgroundColorResource(R.color.material_pink_600)
|
||||||
|
setTextColor(ContextCompat.getColor(context, android.R.color.white))
|
||||||
|
ContextCompat.getDrawable(context, R.drawable.ic_gender_female_white)
|
||||||
|
}
|
||||||
|
else -> null
|
||||||
}
|
}
|
||||||
"female" -> {
|
text = tag.tag.wordCapitalize()
|
||||||
chip.setChipBackgroundColorResource(R.color.material_pink_600)
|
setOnClickListener {
|
||||||
chip.setTextColor(ContextCompat.getColor(context, android.R.color.white))
|
for (callback in onChipClickedHandler)
|
||||||
ContextCompat.getDrawable(context, R.drawable.ic_gender_female_white)
|
callback.invoke(tag)
|
||||||
}
|
}
|
||||||
else -> null
|
})
|
||||||
}
|
|
||||||
|
|
||||||
chip.chipIcon = icon
|
|
||||||
chip.text = tag.tag.wordCapitalize()
|
|
||||||
chip.setOnClickListener {
|
|
||||||
for (callback in onChipClickedHandler)
|
|
||||||
callback.invoke(tag)
|
|
||||||
}
|
|
||||||
|
|
||||||
galleryblock_tag_group.addView(chip)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
galleryblock_id.text = galleryBlock.id.toString()
|
galleryblock_id.text = galleryBlock.id.toString()
|
||||||
@@ -316,15 +267,6 @@ class GalleryBlockAdapter(private val glide: RequestManager, private val galleri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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>()
|
private val refreshTasks = HashMap<GalleryViewHolder, TimerTask>()
|
||||||
val completeFlag = SparseBooleanArray()
|
val completeFlag = SparseBooleanArray()
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
package xyz.quaver.pupil.adapters
|
package xyz.quaver.pupil.adapters
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
@@ -26,7 +25,6 @@ import android.widget.ImageView
|
|||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.bumptech.glide.RequestManager
|
import com.bumptech.glide.RequestManager
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||||
import com.bumptech.glide.request.target.Target
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Pupil, Hitomi.la viewer for Android
|
||||||
|
* Copyright (C) 2019 tom5079
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package xyz.quaver.pupil.adapters
|
||||||
|
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.bumptech.glide.RequestManager
|
||||||
|
|
||||||
|
class ThumbnailAdapter(private val glide: RequestManager, private val thumbnails: List<String>) : RecyclerView.Adapter<ThumbnailAdapter.ViewHolder>() {
|
||||||
|
|
||||||
|
class ViewHolder(val view: ImageView) : RecyclerView.ViewHolder(view)
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
|
return ViewHolder(ImageView(parent.context))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
|
glide
|
||||||
|
.load(thumbnails[position])
|
||||||
|
.into(holder.view)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount() = thumbnails.size
|
||||||
|
|
||||||
|
}
|
||||||
@@ -20,21 +20,51 @@ package xyz.quaver.pupil.ui
|
|||||||
|
|
||||||
import android.app.Dialog
|
import android.app.Dialog
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.view.Gravity
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.ImageView
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.LinearLayout.LayoutParams
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.gridlayout.widget.GridLayout
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.bumptech.glide.request.target.Target
|
import com.bumptech.glide.RequestManager
|
||||||
|
import com.google.android.material.chip.Chip
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import kotlinx.android.synthetic.main.dialog_galleryblock.*
|
import kotlinx.android.synthetic.main.dialog_galleryblock.*
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.android.synthetic.main.gallery_details.view.*
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.android.synthetic.main.item_gallery_details.view.*
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.*
|
||||||
|
import xyz.quaver.hitomi.Gallery
|
||||||
|
import xyz.quaver.hitomi.GalleryBlock
|
||||||
import xyz.quaver.hitomi.getGallery
|
import xyz.quaver.hitomi.getGallery
|
||||||
|
import xyz.quaver.hitomi.getGalleryBlock
|
||||||
|
import xyz.quaver.pupil.Pupil
|
||||||
import xyz.quaver.pupil.R
|
import xyz.quaver.pupil.R
|
||||||
|
import xyz.quaver.pupil.adapters.GalleryBlockAdapter
|
||||||
|
import xyz.quaver.pupil.adapters.ThumbnailAdapter
|
||||||
|
import xyz.quaver.pupil.types.Tag
|
||||||
|
import xyz.quaver.pupil.util.ItemClickSupport
|
||||||
|
import xyz.quaver.pupil.util.wordCapitalize
|
||||||
|
|
||||||
class GalleryDialog(context: Context, private val galleryID: Int) : Dialog(context) {
|
class GalleryDialog(context: Context, private val galleryID: Int) : Dialog(context) {
|
||||||
|
|
||||||
|
private val languages = context.resources.getStringArray(R.array.languages).map {
|
||||||
|
it.split("|").let { split ->
|
||||||
|
Pair(split[0], split[1])
|
||||||
|
}
|
||||||
|
}.toMap()
|
||||||
|
|
||||||
|
private val glide = Glide.with(context)
|
||||||
|
|
||||||
|
val onChipClickedHandler = ArrayList<((Tag) -> (Unit))>()
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.dialog_galleryblock)
|
setContentView(R.layout.dialog_galleryblock)
|
||||||
@@ -42,22 +72,53 @@ class GalleryDialog(context: Context, private val galleryID: Int) : Dialog(conte
|
|||||||
window?.attributes.apply {
|
window?.attributes.apply {
|
||||||
this ?: return@apply
|
this ?: return@apply
|
||||||
|
|
||||||
width = LinearLayout.LayoutParams.MATCH_PARENT
|
width = LayoutParams.MATCH_PARENT
|
||||||
height = LinearLayout.LayoutParams.MATCH_PARENT
|
height = LayoutParams.MATCH_PARENT
|
||||||
}
|
}
|
||||||
|
|
||||||
gallery_fab.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.arrow_right))
|
with(gallery_fab) {
|
||||||
|
setImageDrawable(ContextCompat.getDrawable(context, R.drawable.arrow_right))
|
||||||
|
setOnClickListener {
|
||||||
|
context.startActivity(Intent(context, ReaderActivity::class.java).apply {
|
||||||
|
putExtra("galleryID", galleryID)
|
||||||
|
})
|
||||||
|
(context.applicationContext as Pupil).histories.add(galleryID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
try {
|
try {
|
||||||
val gallery = getGallery(galleryID)
|
val gallery = getGallery(galleryID)
|
||||||
|
|
||||||
launch(Dispatchers.Main) {
|
launch(Dispatchers.Main) {
|
||||||
gallery_toolbar.title = gallery.title
|
gallery_progressbar.visibility = View.GONE
|
||||||
|
gallery_title.text = gallery.title
|
||||||
|
gallery_artist.text = gallery.artists.joinToString(", ") { it.wordCapitalize() }
|
||||||
|
|
||||||
|
with(gallery_type) {
|
||||||
|
text = gallery.type.wordCapitalize()
|
||||||
|
setOnClickListener {
|
||||||
|
gallery.type.let {
|
||||||
|
when (it) {
|
||||||
|
"artist CG" -> "artistcg"
|
||||||
|
"game CG" -> "gamecg"
|
||||||
|
else -> it
|
||||||
|
}
|
||||||
|
}.let {
|
||||||
|
onChipClickedHandler.forEach { handler ->
|
||||||
|
handler.invoke(Tag("type", it))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Glide.with(context)
|
Glide.with(context)
|
||||||
.load(gallery.thumbnails[0])
|
.load(gallery.thumbnails.firstOrNull())
|
||||||
.into(gallery_thumbnail)
|
.into(gallery_thumbnail)
|
||||||
|
|
||||||
|
addDetails(gallery)
|
||||||
|
addThumbnails(gallery)
|
||||||
|
addRelated(gallery)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Snackbar.make(gallery_layout, R.string.unable_to_connect, Snackbar.LENGTH_INDEFINITE).show()
|
Snackbar.make(gallery_layout, R.string.unable_to_connect, Snackbar.LENGTH_INDEFINITE).show()
|
||||||
@@ -65,4 +126,151 @@ class GalleryDialog(context: Context, private val galleryID: Int) : Dialog(conte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun addDetails(gallery: Gallery) {
|
||||||
|
val inflater = LayoutInflater.from(context)
|
||||||
|
|
||||||
|
inflater.inflate(R.layout.gallery_details, gallery_contents, false).apply {
|
||||||
|
gallery_details.setText(R.string.gallery_details)
|
||||||
|
|
||||||
|
listOf(
|
||||||
|
R.string.gallery_artists,
|
||||||
|
R.string.gallery_groups,
|
||||||
|
R.string.gallery_language,
|
||||||
|
R.string.gallery_series,
|
||||||
|
R.string.gallery_characters,
|
||||||
|
R.string.gallery_tags
|
||||||
|
).zip(
|
||||||
|
listOf(
|
||||||
|
gallery.artists.map { Tag("artist", it) },
|
||||||
|
gallery.groups.map { Tag("group", it) },
|
||||||
|
listOf(gallery.language).map { Tag("language", it) },
|
||||||
|
gallery.series.map { Tag("series", it) },
|
||||||
|
gallery.characters.map { Tag("character", it) },
|
||||||
|
gallery.tags.map {
|
||||||
|
Tag.parse(it).let { tag ->
|
||||||
|
when {
|
||||||
|
tag.area != null -> tag
|
||||||
|
else -> Tag("tag", it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
).filter {
|
||||||
|
(_, content) -> content.isNotEmpty()
|
||||||
|
}.forEach { (title, content) ->
|
||||||
|
inflater.inflate(R.layout.item_gallery_details, gallery_details_contents, false).apply {
|
||||||
|
gallery_details_type.setText(title)
|
||||||
|
|
||||||
|
content.forEach { tag ->
|
||||||
|
gallery_details_tags.addView(
|
||||||
|
Chip(context).apply {
|
||||||
|
chipIcon = when(tag.area) {
|
||||||
|
"male" -> {
|
||||||
|
setChipBackgroundColorResource(R.color.material_blue_700)
|
||||||
|
setTextColor(ContextCompat.getColor(context, android.R.color.white))
|
||||||
|
ContextCompat.getDrawable(context, R.drawable.ic_gender_male_white)
|
||||||
|
}
|
||||||
|
"female" -> {
|
||||||
|
setChipBackgroundColorResource(R.color.material_pink_600)
|
||||||
|
setTextColor(ContextCompat.getColor(context, android.R.color.white))
|
||||||
|
ContextCompat.getDrawable(context, R.drawable.ic_gender_female_white)
|
||||||
|
}
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
text = when (tag.area) {
|
||||||
|
"language" -> languages[tag.tag]
|
||||||
|
else -> tag.tag.wordCapitalize()
|
||||||
|
}
|
||||||
|
|
||||||
|
setOnClickListener {
|
||||||
|
onChipClickedHandler.forEach { handler ->
|
||||||
|
handler.invoke(tag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}.let {
|
||||||
|
gallery_details_contents.addView(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.let {
|
||||||
|
gallery_contents.addView(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addThumbnails(gallery: Gallery) {
|
||||||
|
val inflater = LayoutInflater.from(context)
|
||||||
|
|
||||||
|
inflater.inflate(R.layout.gallery_details, gallery_contents, false).apply {
|
||||||
|
gallery_details.setText(R.string.gallery_thumbnails)
|
||||||
|
|
||||||
|
RecyclerView(context).apply {
|
||||||
|
layoutManager = GridLayoutManager(context, 3)
|
||||||
|
adapter = ThumbnailAdapter(glide, gallery.thumbnails)
|
||||||
|
}.let {
|
||||||
|
gallery_details_contents.addView(it, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT))
|
||||||
|
}
|
||||||
|
}.let {
|
||||||
|
gallery_contents.addView(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addRelated(gallery: Gallery) {
|
||||||
|
val inflater = LayoutInflater.from(context)
|
||||||
|
val galleries = ArrayList<Pair<GalleryBlock, Deferred<String>>>()
|
||||||
|
|
||||||
|
val adapter = GalleryBlockAdapter(glide, galleries).apply {
|
||||||
|
onChipClickedHandler.add { tag ->
|
||||||
|
this@GalleryDialog.onChipClickedHandler.forEach { handler ->
|
||||||
|
handler.invoke(tag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
|
gallery.related.forEachIndexed { i, galleryID ->
|
||||||
|
async(Dispatchers.IO) {
|
||||||
|
getGalleryBlock(galleryID)
|
||||||
|
}.let {
|
||||||
|
val galleryBlock = it.await() ?: return@let
|
||||||
|
|
||||||
|
galleries.add(Pair(galleryBlock, GlobalScope.async { galleryBlock.thumbnails.first() }))
|
||||||
|
adapter.notifyItemInserted(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inflater.inflate(R.layout.gallery_details, gallery_contents, false).apply {
|
||||||
|
gallery_details.setText(R.string.gallery_related)
|
||||||
|
|
||||||
|
RecyclerView(context).apply {
|
||||||
|
layoutManager = LinearLayoutManager(context)
|
||||||
|
this.adapter = adapter
|
||||||
|
|
||||||
|
ItemClickSupport.addTo(this)
|
||||||
|
.setOnItemClickListener { _, position, _ ->
|
||||||
|
context.startActivity(Intent(context, ReaderActivity::class.java).apply {
|
||||||
|
putExtra("galleryID", galleries[position].first.id)
|
||||||
|
})
|
||||||
|
(context.applicationContext as Pupil).histories.add(galleries[position].first.id)
|
||||||
|
}
|
||||||
|
.setOnItemLongClickListener { _, position, _ ->
|
||||||
|
GalleryDialog(context, galleries[position].first.id).apply {
|
||||||
|
onChipClickedHandler.add { tag ->
|
||||||
|
this@GalleryDialog.onChipClickedHandler.forEach { it.invoke(tag) }
|
||||||
|
}
|
||||||
|
}.show()
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}.let {
|
||||||
|
gallery_details_contents.addView(it, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT))
|
||||||
|
}
|
||||||
|
}.let {
|
||||||
|
gallery_contents.addView(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -58,7 +58,7 @@ class LockActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
when(mode) {
|
when(mode) {
|
||||||
null -> {
|
null -> {
|
||||||
if (lockManager.empty()) {
|
if (lockManager.isEmpty()) {
|
||||||
setResult(RESULT_OK)
|
setResult(RESULT_OK)
|
||||||
finish()
|
finish()
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -127,7 +127,21 @@ class MainActivity : AppCompatActivity() {
|
|||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
startActivityForResult(Intent(this, LockActivity::class.java), REQUEST_LOCK)
|
val lockManager = try {
|
||||||
|
LockManager(this)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
android.app.AlertDialog.Builder(this).apply {
|
||||||
|
setTitle(R.string.warning)
|
||||||
|
setMessage(R.string.lock_corrupted)
|
||||||
|
setPositiveButton(android.R.string.ok) { _, _ ->
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}.show()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lockManager.isNotEmpty())
|
||||||
|
startActivityForResult(Intent(this, LockActivity::class.java), REQUEST_LOCK)
|
||||||
|
|
||||||
checkPermissions()
|
checkPermissions()
|
||||||
|
|
||||||
@@ -524,7 +538,6 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
ItemClickSupport.addTo(this)
|
ItemClickSupport.addTo(this)
|
||||||
.setOnItemClickListener { _, position, v ->
|
.setOnItemClickListener { _, position, v ->
|
||||||
|
|
||||||
if (v !is CardView)
|
if (v !is CardView)
|
||||||
return@setOnItemClickListener
|
return@setOnItemClickListener
|
||||||
|
|
||||||
@@ -543,8 +556,20 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
val galleryID = galleries[position].first.id
|
val galleryID = galleries[position].first.id
|
||||||
|
|
||||||
GalleryDialog(this@MainActivity, galleryID)
|
GalleryDialog(this@MainActivity, galleryID).apply {
|
||||||
.show()
|
onChipClickedHandler.add {
|
||||||
|
runOnUiThread {
|
||||||
|
query = it.toQuery()
|
||||||
|
currentPage = 0
|
||||||
|
|
||||||
|
cancelFetch()
|
||||||
|
clearGalleries()
|
||||||
|
fetchGalleries(query, sortMode)
|
||||||
|
loadBlocks()
|
||||||
|
}
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}.show()
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ 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.appcompat.app.AppCompatDelegate
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
@@ -338,6 +339,19 @@ class SettingsActivity : AppCompatActivity() {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
with(findPreference<Preference>("dark_mode")) {
|
||||||
|
this!!
|
||||||
|
|
||||||
|
onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
|
||||||
|
AppCompatDelegate.setDefaultNightMode(when (newValue as Boolean) {
|
||||||
|
true -> AppCompatDelegate.MODE_NIGHT_YES
|
||||||
|
false -> AppCompatDelegate.MODE_NIGHT_NO
|
||||||
|
})
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -112,10 +112,12 @@ class LockManager(base: Context): ContextWrapper(base) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun empty(): Boolean {
|
fun isEmpty(): Boolean {
|
||||||
return locks.isNullOrEmpty()
|
return locks.isNullOrEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun isNotEmpty(): Boolean = !isEmpty()
|
||||||
|
|
||||||
fun contains(type: Lock.Type): Boolean {
|
fun contains(type: Lock.Type): Boolean {
|
||||||
return locks?.any { it.type == type } ?: false
|
return locks?.any { it.type == type } ?: false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,4 +23,13 @@ import android.content.pm.PackageManager
|
|||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
|
||||||
fun Context.hasPermission(permission: String) =
|
fun Context.hasPermission(permission: String) =
|
||||||
ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED
|
ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED
|
||||||
|
|
||||||
|
fun String.wordCapitalize() : String {
|
||||||
|
val result = ArrayList<String>()
|
||||||
|
|
||||||
|
for (word in this.split(" "))
|
||||||
|
result.add(word.capitalize())
|
||||||
|
|
||||||
|
return result.joinToString(" ")
|
||||||
|
}
|
||||||
@@ -104,6 +104,7 @@
|
|||||||
android:id="@+id/main_searchview"
|
android:id="@+id/main_searchview"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
app:floatingSearch_backgroundColor="?attr/colorSurface"
|
||||||
app:floatingSearch_searchBarMarginLeft="8dp"
|
app:floatingSearch_searchBarMarginLeft="8dp"
|
||||||
app:floatingSearch_searchBarMarginRight="8dp"
|
app:floatingSearch_searchBarMarginRight="8dp"
|
||||||
app:floatingSearch_searchBarMarginTop="8dp"
|
app:floatingSearch_searchBarMarginTop="8dp"
|
||||||
|
|||||||
@@ -17,35 +17,99 @@
|
|||||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<LinearLayout 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/gallery_layout"
|
android:id="@+id/gallery_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<androidx.appcompat.widget.Toolbar
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
android:id="@+id/gallery_toolbar"
|
android:id="@+id/gallery_toolbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content">
|
||||||
app:menu="@menu/gallery"
|
|
||||||
android:background="@color/colorPrimary"
|
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||||
app:titleTextColor="@color/white"
|
android:layout_width="match_parent"
|
||||||
android:minHeight="?attr/actionBarSize"/>
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_scrollFlags="scroll|exitUntilCollapsed">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="8dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/gallery_thumbnail"
|
||||||
|
android:layout_width="150dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toLeftOf="@id/gallery_title"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/gallery_title"
|
||||||
|
style="@style/TextAppearance.AppCompat.Headline"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintLeft_toRightOf="@id/gallery_thumbnail"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
android:layout_marginLeft="8dp"
|
||||||
|
android:layout_marginStart="8dp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/TextAppearance.AppCompat.Medium"
|
||||||
|
android:id="@+id/gallery_artist"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/gallery_title"
|
||||||
|
app:layout_constraintLeft_toRightOf="@id/gallery_thumbnail"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
android:layout_marginLeft="8dp"
|
||||||
|
android:layout_marginStart="8dp"/>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/gallery_padding"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/gallery_artist"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/gallery_type"/>
|
||||||
|
|
||||||
|
<com.google.android.material.chip.Chip
|
||||||
|
android:id="@+id/gallery_type"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintLeft_toRightOf="@id/gallery_thumbnail"
|
||||||
|
android:layout_marginLeft="8dp"
|
||||||
|
android:layout_marginStart="8dp"/>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
<androidx.core.widget.NestedScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/gallery_contents"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"/>
|
||||||
|
|
||||||
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/gallery_thumbnail"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
|
||||||
android:contentDescription=""
|
|
||||||
android:padding="16dp"/>
|
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/gallery_progressbar"
|
android:id="@+id/gallery_progressbar"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@@ -55,14 +119,14 @@
|
|||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||||
|
|
||||||
<com.github.clans.fab.FloatingActionButton
|
|
||||||
android:id="@+id/gallery_fab"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="16dp"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
|
android:id="@+id/gallery_fab"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
app:layout_anchor="@id/gallery_toolbar"
|
||||||
|
app:layout_anchorGravity="bottom|end"/>
|
||||||
|
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
40
app/src/main/res/layout/gallery_details.xml
Normal file
40
app/src/main/res/layout/gallery_details.xml
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Pupil, Hitomi.la viewer for Android
|
||||||
|
~ Copyright (C) 2019 tom5079
|
||||||
|
~
|
||||||
|
~ This program is free software: you can redistribute it and/or modify
|
||||||
|
~ it under the terms of the GNU General Public License as published by
|
||||||
|
~ the Free Software Foundation, either version 3 of the License, or
|
||||||
|
~ (at your option) any later version.
|
||||||
|
~
|
||||||
|
~ This program is distributed in the hope that it will be useful,
|
||||||
|
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
~ GNU General Public License for more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU General Public License
|
||||||
|
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="8dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/gallery_details"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
style="@style/TextAppearance.MaterialComponents.Body1"
|
||||||
|
android:textColor="@color/colorAccent"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/gallery_details_contents"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
40
app/src/main/res/layout/item_gallery_details.xml
Normal file
40
app/src/main/res/layout/item_gallery_details.xml
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Pupil, Hitomi.la viewer for Android
|
||||||
|
~ Copyright (C) 2019 tom5079
|
||||||
|
~
|
||||||
|
~ This program is free software: you can redistribute it and/or modify
|
||||||
|
~ it under the terms of the GNU General Public License as published by
|
||||||
|
~ the Free Software Foundation, either version 3 of the License, or
|
||||||
|
~ (at your option) any later version.
|
||||||
|
~
|
||||||
|
~ This program is distributed in the hope that it will be useful,
|
||||||
|
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
~ GNU General Public License for more details.
|
||||||
|
~
|
||||||
|
~ You should have received a copy of the GNU General Public License
|
||||||
|
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="8dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="@style/TextAppearance.MaterialComponents.Body2"
|
||||||
|
android:id="@+id/gallery_details_type"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingBottom="8dp"/>
|
||||||
|
|
||||||
|
<com.google.android.material.chip.ChipGroup
|
||||||
|
android:id="@+id/gallery_details_tags"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:chipSpacingVertical="8dp"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -17,11 +17,7 @@
|
|||||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
android:layout_width="match_parent"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="wrap_content"
|
android:columnCount="3"/>
|
||||||
android:layout_height="24dp"
|
|
||||||
app:chipIconSize="16dp"
|
|
||||||
app:chipStartPadding="8dp"
|
|
||||||
app:chipCornerRadius="100dp"/>
|
|
||||||
@@ -87,8 +87,6 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true"
|
|
||||||
app:layout_constraintLeft_toRightOf="@id/galleryblock_thumbnail"
|
app:layout_constraintLeft_toRightOf="@id/galleryblock_thumbnail"
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/galleryblock_title"/>
|
app:layout_constraintTop_toBottomOf="@id/galleryblock_title"/>
|
||||||
@@ -99,8 +97,6 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/galleryblock_artist"
|
app:layout_constraintTop_toBottomOf="@id/galleryblock_artist"
|
||||||
app:layout_constraintStart_toEndOf="@id/galleryblock_thumbnail"
|
app:layout_constraintStart_toEndOf="@id/galleryblock_thumbnail"
|
||||||
app:layout_constraintEnd_toEndOf="parent"/>
|
app:layout_constraintEnd_toEndOf="parent"/>
|
||||||
@@ -111,8 +107,6 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/galleryblock_series"
|
app:layout_constraintTop_toBottomOf="@id/galleryblock_series"
|
||||||
app:layout_constraintStart_toEndOf="@id/galleryblock_thumbnail" />
|
app:layout_constraintStart_toEndOf="@id/galleryblock_thumbnail" />
|
||||||
|
|
||||||
@@ -123,8 +117,6 @@
|
|||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
android:clickable="true"
|
|
||||||
android:focusable="true"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/galleryblock_type"
|
app:layout_constraintTop_toBottomOf="@id/galleryblock_type"
|
||||||
app:layout_constraintBottom_toTopOf="@id/galleryblock_padding"
|
app:layout_constraintBottom_toTopOf="@id/galleryblock_padding"
|
||||||
app:layout_constraintStart_toEndOf="@id/galleryblock_thumbnail" />
|
app:layout_constraintStart_toEndOf="@id/galleryblock_thumbnail" />
|
||||||
@@ -145,6 +137,7 @@
|
|||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:layout_marginBottom="16dp"
|
android:layout_marginBottom="16dp"
|
||||||
|
app:chipSpacing="2dp"
|
||||||
app:layout_constraintTop_toBottomOf="@id/galleryblock_padding"
|
app:layout_constraintTop_toBottomOf="@id/galleryblock_padding"
|
||||||
app:layout_constraintLeft_toRightOf="@id/galleryblock_thumbnail"
|
app:layout_constraintLeft_toRightOf="@id/galleryblock_thumbnail"
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
|||||||
@@ -88,4 +88,15 @@
|
|||||||
<string name="ignore_update">無視</string>
|
<string name="ignore_update">無視</string>
|
||||||
<string name="lock_corrupted">ロックファイルが破損されています。Pupilを再再インストールしてください。</string>
|
<string name="lock_corrupted">ロックファイルが破損されています。Pupilを再再インストールしてください。</string>
|
||||||
<string name="update_no_permission">権限がないため自動アップデートを行えません。ホームページで直接ダウンロードしてください。</string>
|
<string name="update_no_permission">権限がないため自動アップデートを行えません。ホームページで直接ダウンロードしてください。</string>
|
||||||
|
<string name="settings_dark_mode_title">ダークモード</string>
|
||||||
|
<string name="settings_dark_mode_summary">夜にシコりたい方々へ</string>
|
||||||
|
<string name="gallery_details">ギャラリー情報</string>
|
||||||
|
<string name="gallery_artists">アーティスト</string>
|
||||||
|
<string name="gallery_characters">キャラクター</string>
|
||||||
|
<string name="gallery_groups">グループ</string>
|
||||||
|
<string name="gallery_language">言語</string>
|
||||||
|
<string name="gallery_series">シリーズ</string>
|
||||||
|
<string name="gallery_tags">タグ</string>
|
||||||
|
<string name="gallery_thumbnails">サムネイル</string>
|
||||||
|
<string name="gallery_related">おすすめ</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -88,4 +88,15 @@
|
|||||||
<string name="ignore_update">무시</string>
|
<string name="ignore_update">무시</string>
|
||||||
<string name="lock_corrupted">잠금 파일이 손상되었습니다! 앱을 재설치 해 주시기 바랍니다.</string>
|
<string name="lock_corrupted">잠금 파일이 손상되었습니다! 앱을 재설치 해 주시기 바랍니다.</string>
|
||||||
<string name="update_no_permission">권한이 부여되어 있지 않아 자동 업데이트를 진행할 수 없습니다. 홈페이지에서 직접 다운로드 받으시기 바랍니다.</string>
|
<string name="update_no_permission">권한이 부여되어 있지 않아 자동 업데이트를 진행할 수 없습니다. 홈페이지에서 직접 다운로드 받으시기 바랍니다.</string>
|
||||||
|
<string name="settings_dark_mode_title">다크 모드</string>
|
||||||
|
<string name="settings_dark_mode_summary">딥 다크한 모오드</string>
|
||||||
|
<string name="gallery_details">갤러리 정보</string>
|
||||||
|
<string name="gallery_artists">작가</string>
|
||||||
|
<string name="gallery_characters">캐릭터</string>
|
||||||
|
<string name="gallery_groups">그룹</string>
|
||||||
|
<string name="gallery_language">언어</string>
|
||||||
|
<string name="gallery_series">시리즈</string>
|
||||||
|
<string name="gallery_tags">태그</string>
|
||||||
|
<string name="gallery_related">관련 갤러리</string>
|
||||||
|
<string name="gallery_thumbnails">미리보기</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -8,4 +8,6 @@
|
|||||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||||
<dimen name="nav_header_vertical_spacing">8dp</dimen>
|
<dimen name="nav_header_vertical_spacing">8dp</dimen>
|
||||||
<dimen name="nav_header_height">176dp</dimen>
|
<dimen name="nav_header_height">176dp</dimen>
|
||||||
|
|
||||||
|
<dimen name="thumbnail_margin">8dp</dimen>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -78,6 +78,16 @@
|
|||||||
<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="search_hint_with_page">Search galleries</string>
|
||||||
|
|
||||||
|
<string name="gallery_details">Details</string>
|
||||||
|
<string name="gallery_thumbnails">Thumbnails</string>
|
||||||
|
<string name="gallery_related">Related Galleries</string>
|
||||||
|
<string name="gallery_artists">Artists</string>
|
||||||
|
<string name="gallery_groups">Groups</string>
|
||||||
|
<string name="gallery_language">Language</string>
|
||||||
|
<string name="gallery_series">Series</string>
|
||||||
|
<string name="gallery_characters">Characters</string>
|
||||||
|
<string name="gallery_tags">Tags</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>
|
||||||
<string name="galleryblock_language">Language: %1$s</string>
|
<string name="galleryblock_language">Language: %1$s</string>
|
||||||
@@ -112,6 +122,8 @@
|
|||||||
<string name="settings_use_hiyobi_summary">Load images from hiyobi.me to improve loading speed (if available)</string>
|
<string name="settings_use_hiyobi_summary">Load images from hiyobi.me to improve loading speed (if available)</string>
|
||||||
<string name="settings_security_mode_title">Enable security mode</string>
|
<string name="settings_security_mode_title">Enable security mode</string>
|
||||||
<string name="settings_security_mode_summary">Enable security mode to make the screen invisible on recent app window</string>
|
<string name="settings_security_mode_summary">Enable security mode to make the screen invisible on recent app window</string>
|
||||||
|
<string name="settings_dark_mode_title">Dark mode</string>
|
||||||
|
<string name="settings_dark_mode_summary">Protect yourself against light attacks!</string>
|
||||||
|
|
||||||
<string name="settings_lock_none">None</string>
|
<string name="settings_lock_none">None</string>
|
||||||
<string name="settings_lock_pattern">Pattern</string>
|
<string name="settings_lock_pattern">Pattern</string>
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<!-- Base application theme. -->
|
<!-- Base application theme. -->
|
||||||
<style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
|
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
|
||||||
<!-- Customize your theme here. -->
|
<!-- Customize your theme here. -->
|
||||||
<item name="colorPrimary">@color/colorPrimary</item>
|
<item name="colorPrimary">@color/colorPrimary</item>
|
||||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||||
<item name="colorAccent">@color/colorAccent</item>
|
<item name="colorAccent">@color/colorAccent</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="NoActionBarAppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
|
<style name="NoActionBarAppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
|
||||||
<!-- Customize your theme here. -->
|
<!-- Customize your theme here. -->
|
||||||
<item name="colorPrimary">@color/colorPrimary</item>
|
<item name="colorPrimary">@color/colorPrimary</item>
|
||||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||||
|
|||||||
@@ -65,6 +65,11 @@
|
|||||||
app:summary="@string/settings_security_mode_summary"
|
app:summary="@string/settings_security_mode_summary"
|
||||||
app:defaultValue="true"/>
|
app:defaultValue="true"/>
|
||||||
|
|
||||||
|
<SwitchPreference
|
||||||
|
app:key="dark_mode"
|
||||||
|
app:title="@string/settings_dark_mode_title"
|
||||||
|
app:summary="@string/settings_dark_mode_summary"/>
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
</androidx.preference.PreferenceScreen>
|
</androidx.preference.PreferenceScreen>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ buildscript {
|
|||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
classpath 'io.fabric.tools:gradle:1.29.0'
|
classpath 'io.fabric.tools:gradle:1.29.0'
|
||||||
classpath 'com.google.firebase:perf-plugin:1.2.1'
|
classpath 'com.google.firebase:perf-plugin:1.3.0'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ dependencies {
|
|||||||
sourceCompatibility = "7"
|
sourceCompatibility = "7"
|
||||||
targetCompatibility = "7"
|
targetCompatibility = "7"
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.3.31'
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package xyz.quaver.hitomi
|
|||||||
|
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
import java.net.URLDecoder
|
||||||
|
|
||||||
data class Gallery(
|
data class Gallery(
|
||||||
val related: List<Int>,
|
val related: List<Int>,
|
||||||
@@ -63,11 +64,11 @@ fun getGallery(galleryID: Int) : Gallery {
|
|||||||
val characters = doc.select(".gallery-info a[href~=^/character/]").map { it.text() }
|
val characters = doc.select(".gallery-info a[href~=^/character/]").map { it.text() }
|
||||||
|
|
||||||
val tags = doc.select(".gallery-info a[href~=^/tag/]").map {
|
val tags = doc.select(".gallery-info a[href~=^/tag/]").map {
|
||||||
val href = it.attr("href")
|
val href = URLDecoder.decode(it.attr("href"), "UTF-8")
|
||||||
href.slice(5 until href.indexOf('-'))
|
href.slice(5 until href.indexOf('-'))
|
||||||
}
|
}
|
||||||
|
|
||||||
val thumbnails = Regex("'(//tn.hitomi.la/smalltn/\\d+/\\d+.+)',")
|
val thumbnails = Regex("'(//tn.hitomi.la/smalltn/\\d+/.+)',")
|
||||||
.findAll(doc.select("script").last().html())
|
.findAll(doc.select("script").last().html())
|
||||||
.map {
|
.map {
|
||||||
protocol + it.groups[1]!!.value
|
protocol + it.groups[1]!!.value
|
||||||
|
|||||||
Reference in New Issue
Block a user