@@ -9,8 +9,8 @@ android {
|
|||||||
applicationId "xyz.quaver.pupil"
|
applicationId "xyz.quaver.pupil"
|
||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
versionCode 3
|
versionCode 4
|
||||||
versionName "1.2"
|
versionName "1.3"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
@@ -40,6 +40,7 @@ dependencies {
|
|||||||
implementation 'androidx.appcompat:appcompat:1.0.2'
|
implementation 'androidx.appcompat:appcompat:1.0.2'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||||
implementation "ru.noties.markwon:core:${markwonVersion}"
|
implementation "ru.noties.markwon:core:${markwonVersion}"
|
||||||
|
implementation 'com.shawnlin:number-picker:2.4.8'
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
|
||||||
androidTestImplementation 'androidx.test:runner:1.1.1'
|
androidTestImplementation 'androidx.test:runner:1.1.1'
|
||||||
|
|||||||
@@ -4,16 +4,10 @@ import android.graphics.BitmapFactory
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.platform.app.InstrumentationRegistry
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import xyz.quaver.hiyobi.getReader
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instrumented test, which will execute on an Android device.
|
* Instrumented test, which will execute on an Android device.
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
package="xyz.quaver.pupil">
|
package="xyz.quaver.pupil">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
|
||||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
|
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
@@ -25,7 +23,7 @@
|
|||||||
android:resource="@xml/filepaths"/>
|
android:resource="@xml/filepaths"/>
|
||||||
</provider>
|
</provider>
|
||||||
|
|
||||||
<activity android:name=".GalleryActivity"
|
<activity android:name=".ReaderActivity"
|
||||||
android:configChanges="keyboardHidden|orientation|screenSize"/>
|
android:configChanges="keyboardHidden|orientation|screenSize"/>
|
||||||
<activity
|
<activity
|
||||||
android:name=".SettingsActivity"
|
android:name=".SettingsActivity"
|
||||||
|
|||||||
@@ -1,155 +0,0 @@
|
|||||||
package xyz.quaver.pupil
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.util.Log
|
|
||||||
import android.view.View
|
|
||||||
import android.view.WindowManager
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
import androidx.preference.PreferenceManager
|
|
||||||
import kotlinx.android.synthetic.main.activity_gallery.*
|
|
||||||
import kotlinx.coroutines.*
|
|
||||||
import xyz.quaver.hitomi.Reader
|
|
||||||
import xyz.quaver.hitomi.getReader
|
|
||||||
import xyz.quaver.hitomi.getReferer
|
|
||||||
import xyz.quaver.pupil.adapters.GalleryAdapter
|
|
||||||
import java.io.File
|
|
||||||
import java.io.FileOutputStream
|
|
||||||
import java.net.URL
|
|
||||||
import javax.net.ssl.HttpsURLConnection
|
|
||||||
|
|
||||||
class GalleryActivity : AppCompatActivity() {
|
|
||||||
|
|
||||||
private val images = ArrayList<String>()
|
|
||||||
private var galleryID = 0
|
|
||||||
private lateinit var reader: Deferred<Reader>
|
|
||||||
private var loadJob: Job? = null
|
|
||||||
private var screenMode = 0
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
|
|
||||||
window.setFlags(
|
|
||||||
WindowManager.LayoutParams.FLAG_SECURE,
|
|
||||||
WindowManager.LayoutParams.FLAG_SECURE)
|
|
||||||
|
|
||||||
setContentView(R.layout.activity_gallery)
|
|
||||||
|
|
||||||
supportActionBar?.title = intent.getStringExtra("GALLERY_TITLE")
|
|
||||||
|
|
||||||
galleryID = intent.getIntExtra("GALLERY_ID", 0)
|
|
||||||
CoroutineScope(Dispatchers.Unconfined).launch {
|
|
||||||
reader = async(Dispatchers.IO) {
|
|
||||||
val preference = PreferenceManager.getDefaultSharedPreferences(this@GalleryActivity)
|
|
||||||
if (preference.getBoolean("use_hiyobi", false)) {
|
|
||||||
try {
|
|
||||||
xyz.quaver.hiyobi.getReader(galleryID)
|
|
||||||
Log.d("Pupil", "Using Hiyobi.me")
|
|
||||||
} catch (e: Exception) {
|
|
||||||
getReader(galleryID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
getReader(galleryID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
initView()
|
|
||||||
loadImages()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
val preferences = android.preference.PreferenceManager.getDefaultSharedPreferences(this)
|
|
||||||
|
|
||||||
if (preferences.getBoolean("security_mode", false))
|
|
||||||
window.setFlags(
|
|
||||||
WindowManager.LayoutParams.FLAG_SECURE,
|
|
||||||
WindowManager.LayoutParams.FLAG_SECURE)
|
|
||||||
else
|
|
||||||
window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
|
|
||||||
super.onResume()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroy() {
|
|
||||||
super.onDestroy()
|
|
||||||
loadJob?.cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initView() {
|
|
||||||
gallery_recyclerview.adapter = GalleryAdapter(images).apply {
|
|
||||||
setOnClick {
|
|
||||||
val attrs = window.attributes
|
|
||||||
|
|
||||||
screenMode = (screenMode+1)%2
|
|
||||||
|
|
||||||
when(screenMode) {
|
|
||||||
0 -> {
|
|
||||||
attrs.flags = attrs.flags and WindowManager.LayoutParams.FLAG_FULLSCREEN.inv()
|
|
||||||
supportActionBar?.show()
|
|
||||||
}
|
|
||||||
1 -> {
|
|
||||||
attrs.flags = attrs.flags or WindowManager.LayoutParams.FLAG_FULLSCREEN
|
|
||||||
supportActionBar?.hide()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
window.attributes = attrs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadImages() {
|
|
||||||
|
|
||||||
fun webpUrlFromUrl(url: URL) = URL(url.toString().replace("/galleries/", "/webp/") + ".webp")
|
|
||||||
|
|
||||||
loadJob = CoroutineScope(Dispatchers.Default).launch {
|
|
||||||
val reader = reader.await()
|
|
||||||
|
|
||||||
launch(Dispatchers.Main) {
|
|
||||||
with(gallery_progressbar) {
|
|
||||||
max = reader.size
|
|
||||||
progress = 0
|
|
||||||
|
|
||||||
visibility = View.VISIBLE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
reader.chunked(8).forEach { chunked ->
|
|
||||||
chunked.map {
|
|
||||||
async(Dispatchers.IO) {
|
|
||||||
val url = if (it.second?.haswebp == 1) webpUrlFromUrl(it.first) else it.first
|
|
||||||
|
|
||||||
val fileName: String
|
|
||||||
|
|
||||||
with(url.path) {
|
|
||||||
fileName = substring(lastIndexOf('/')+1)
|
|
||||||
}
|
|
||||||
|
|
||||||
val cache = File(cacheDir, "/imageCache/$galleryID/$fileName")
|
|
||||||
|
|
||||||
if (!cache.exists())
|
|
||||||
with(url.openConnection() as HttpsURLConnection) {
|
|
||||||
setRequestProperty("Referer", getReferer(galleryID))
|
|
||||||
|
|
||||||
if (!cache.parentFile.exists())
|
|
||||||
cache.parentFile.mkdirs()
|
|
||||||
|
|
||||||
inputStream.copyTo(FileOutputStream(cache))
|
|
||||||
}
|
|
||||||
|
|
||||||
cache.absolutePath
|
|
||||||
}
|
|
||||||
}.forEach {
|
|
||||||
val cache = it.await()
|
|
||||||
|
|
||||||
launch(Dispatchers.Main) {
|
|
||||||
images.add(cache)
|
|
||||||
gallery_recyclerview.adapter?.notifyItemInserted(images.size - 1)
|
|
||||||
gallery_progressbar.progress++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
launch(Dispatchers.Main) {
|
|
||||||
gallery_progressbar.visibility = View.GONE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,31 +1,15 @@
|
|||||||
package xyz.quaver.pupil
|
package xyz.quaver.pupil
|
||||||
|
|
||||||
import android.Manifest
|
|
||||||
import android.app.DownloadManager
|
|
||||||
import android.content.BroadcastReceiver
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
|
||||||
import android.content.pm.PackageManager
|
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.graphics.BitmapFactory
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Environment
|
|
||||||
import android.preference.PreferenceManager
|
import android.preference.PreferenceManager
|
||||||
import android.text.*
|
import android.text.*
|
||||||
import android.text.style.AlignmentSpan
|
import android.text.style.AlignmentSpan
|
||||||
import android.util.Log
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.app.ActivityCompat
|
|
||||||
import androidx.core.app.NotificationCompat
|
|
||||||
import androidx.core.content.ContextCompat
|
|
||||||
import androidx.core.content.FileProvider
|
|
||||||
import androidx.core.content.res.ResourcesCompat
|
import androidx.core.content.res.ResourcesCompat
|
||||||
import androidx.core.view.GravityCompat
|
import androidx.core.view.GravityCompat
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
@@ -44,19 +28,18 @@ import xyz.quaver.hitomi.*
|
|||||||
import xyz.quaver.pupil.adapters.GalleryBlockAdapter
|
import xyz.quaver.pupil.adapters.GalleryBlockAdapter
|
||||||
import xyz.quaver.pupil.types.TagSuggestion
|
import xyz.quaver.pupil.types.TagSuggestion
|
||||||
import xyz.quaver.pupil.util.Histories
|
import xyz.quaver.pupil.util.Histories
|
||||||
|
import xyz.quaver.pupil.util.ItemClickSupport
|
||||||
import xyz.quaver.pupil.util.SetLineOverlap
|
import xyz.quaver.pupil.util.SetLineOverlap
|
||||||
import xyz.quaver.pupil.util.checkUpdate
|
import xyz.quaver.pupil.util.checkUpdate
|
||||||
import xyz.quaver.pupil.util.getApkUrl
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.lang.StringBuilder
|
import java.io.FileOutputStream
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.net.ssl.HttpsURLConnection
|
import javax.net.ssl.HttpsURLConnection
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
private val permissionRequestCode = 4585
|
private val galleries = ArrayList<Pair<GalleryBlock, Deferred<String>>>()
|
||||||
private val galleries = ArrayList<Pair<GalleryBlock, Bitmap?>>()
|
|
||||||
|
|
||||||
private var query = ""
|
private var query = ""
|
||||||
|
|
||||||
@@ -67,9 +50,12 @@ class MainActivity : AppCompatActivity() {
|
|||||||
Histories.default = Histories(File(cacheDir, "histories.json"))
|
Histories.default = Histories(File(cacheDir, "histories.json"))
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
setContentView(R.layout.activity_main)
|
window.setFlags(
|
||||||
|
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
|
||||||
|
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
|
||||||
|
)
|
||||||
|
|
||||||
checkPermission()
|
setContentView(R.layout.activity_main)
|
||||||
|
|
||||||
checkUpdate()
|
checkUpdate()
|
||||||
|
|
||||||
@@ -81,7 +67,11 @@ class MainActivity : AppCompatActivity() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
with(main_swipe_layout) {
|
with(main_swipe_layout) {
|
||||||
setProgressViewOffset(false, 0, resources.getDimensionPixelSize(R.dimen.progress_view_offset))
|
setProgressViewOffset(
|
||||||
|
false,
|
||||||
|
resources.getDimensionPixelSize(R.dimen.progress_view_start),
|
||||||
|
resources.getDimensionPixelSize(R.dimen.progress_view_offset)
|
||||||
|
)
|
||||||
|
|
||||||
setOnRefreshListener {
|
setOnRefreshListener {
|
||||||
CoroutineScope(Dispatchers.Main).launch {
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
@@ -97,17 +87,36 @@ class MainActivity : AppCompatActivity() {
|
|||||||
CoroutineScope(Dispatchers.Main).launch {
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
main_drawer_layout.closeDrawers()
|
main_drawer_layout.closeDrawers()
|
||||||
|
|
||||||
cancelFetch()
|
|
||||||
clearGalleries()
|
|
||||||
when(it.itemId) {
|
when(it.itemId) {
|
||||||
R.id.main_drawer_home -> {
|
R.id.main_drawer_home -> {
|
||||||
|
cancelFetch()
|
||||||
|
clearGalleries()
|
||||||
query = query.replace("HISTORY", "")
|
query = query.replace("HISTORY", "")
|
||||||
fetchGalleries(query)
|
fetchGalleries(query)
|
||||||
}
|
}
|
||||||
R.id.main_drawer_history -> {
|
R.id.main_drawer_history -> {
|
||||||
|
cancelFetch()
|
||||||
|
clearGalleries()
|
||||||
query += "HISTORY"
|
query += "HISTORY"
|
||||||
fetchGalleries(query)
|
fetchGalleries(query)
|
||||||
}
|
}
|
||||||
|
R.id.main_drawer_help -> {
|
||||||
|
AlertDialog.Builder(this@MainActivity).apply {
|
||||||
|
title = getString(R.string.help_dialog_title)
|
||||||
|
setMessage(R.string.help_dialog_message)
|
||||||
|
|
||||||
|
setPositiveButton(android.R.string.ok) { _, _ -> }
|
||||||
|
}.show()
|
||||||
|
}
|
||||||
|
R.id.main_drawer_github -> {
|
||||||
|
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.github))))
|
||||||
|
}
|
||||||
|
R.id.main_drawer_homepage -> {
|
||||||
|
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.home_page))))
|
||||||
|
}
|
||||||
|
R.id.main_drawer_email -> {
|
||||||
|
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.email))))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
loadBlocks()
|
loadBlocks()
|
||||||
}
|
}
|
||||||
@@ -140,23 +149,6 @@ class MainActivity : AppCompatActivity() {
|
|||||||
super.onResume()
|
super.onResume()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkPermission() {
|
|
||||||
val permissions = arrayOf(
|
|
||||||
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
|
||||||
)
|
|
||||||
|
|
||||||
if (permissions.any { ContextCompat.checkSelfPermission(this, it) != PackageManager.PERMISSION_GRANTED }) {
|
|
||||||
if (permissions.any { ActivityCompat.shouldShowRequestPermissionRationale(this, it) })
|
|
||||||
AlertDialog.Builder(this).apply {
|
|
||||||
setTitle(R.string.warning)
|
|
||||||
setMessage(R.string.permission_explain)
|
|
||||||
setPositiveButton(android.R.string.ok) { _, _ -> }
|
|
||||||
}.show()
|
|
||||||
else
|
|
||||||
ActivityCompat.requestPermissions(this, permissions, permissionRequestCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun checkUpdate() {
|
private fun checkUpdate() {
|
||||||
|
|
||||||
fun extractReleaseNote(update: JsonObject, locale: String) : String {
|
fun extractReleaseNote(update: JsonObject, locale: String) : String {
|
||||||
@@ -177,7 +169,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
val result = StringBuilder()
|
val result = StringBuilder()
|
||||||
|
|
||||||
for(line in markdown.split('\n')) {
|
for(line in markdown.lines()) {
|
||||||
if (releaseNote.matches(line)) {
|
if (releaseNote.matches(line)) {
|
||||||
releaseNoteFlag = true
|
releaseNoteFlag = true
|
||||||
continue
|
continue
|
||||||
@@ -201,57 +193,16 @@ class MainActivity : AppCompatActivity() {
|
|||||||
return getString(R.string.update_release_note, update["tag_name"]?.content, result.toString())
|
return getString(R.string.update_release_note, update["tag_name"]?.content, result.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
|
|
||||||
return
|
|
||||||
|
|
||||||
CoroutineScope(Dispatchers.Default).launch {
|
CoroutineScope(Dispatchers.Default).launch {
|
||||||
val update =
|
val update =
|
||||||
checkUpdate(getString(R.string.release_url), BuildConfig.VERSION_NAME) ?: return@launch
|
checkUpdate(getString(R.string.release_url), BuildConfig.VERSION_NAME) ?: return@launch
|
||||||
|
|
||||||
val (url, fileName) = getApkUrl(update, getString(R.string.release_name)) ?: return@launch
|
|
||||||
|
|
||||||
val dialog = AlertDialog.Builder(this@MainActivity).apply {
|
val dialog = AlertDialog.Builder(this@MainActivity).apply {
|
||||||
setTitle(R.string.update_title)
|
setTitle(R.string.update_title)
|
||||||
val msg = extractReleaseNote(update, Locale.getDefault().language)
|
val msg = extractReleaseNote(update, Locale.getDefault().language)
|
||||||
setMessage(Markwon.create(context).toMarkdown(msg))
|
setMessage(Markwon.create(context).toMarkdown(msg))
|
||||||
setPositiveButton(android.R.string.yes) { _, _ ->
|
setPositiveButton(android.R.string.yes) { _, _ ->
|
||||||
Toast.makeText(
|
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.home_page))))
|
||||||
context, getString(R.string.update_download_started), Toast.LENGTH_SHORT
|
|
||||||
).show()
|
|
||||||
|
|
||||||
val dest = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), fileName)
|
|
||||||
val desturi =
|
|
||||||
FileProvider.getUriForFile(
|
|
||||||
applicationContext,
|
|
||||||
"xyz.quaver.pupil.provider",
|
|
||||||
dest
|
|
||||||
)
|
|
||||||
|
|
||||||
if (dest.exists())
|
|
||||||
dest.delete()
|
|
||||||
|
|
||||||
val request = DownloadManager.Request(Uri.parse(url)).apply {
|
|
||||||
setDescription(getString(R.string.update_notification_description))
|
|
||||||
setTitle(getString(R.string.app_name))
|
|
||||||
setDestinationUri(Uri.fromFile(dest))
|
|
||||||
setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE)
|
|
||||||
}
|
|
||||||
|
|
||||||
val manager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
|
|
||||||
val id = manager.enqueue(request)
|
|
||||||
|
|
||||||
registerReceiver(object: BroadcastReceiver() {
|
|
||||||
override fun onReceive(context: Context?, intent: Intent?) {
|
|
||||||
val install = Intent(Intent.ACTION_VIEW).apply {
|
|
||||||
flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_GRANT_READ_URI_PERMISSION
|
|
||||||
setDataAndType(desturi, manager.getMimeTypeForDownloadedFile(id))
|
|
||||||
}
|
|
||||||
|
|
||||||
startActivity(install)
|
|
||||||
unregisterReceiver(this)
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
|
|
||||||
}
|
}
|
||||||
setNegativeButton(android.R.string.no) { _, _ ->}
|
setNegativeButton(android.R.string.no) { _, _ ->}
|
||||||
}
|
}
|
||||||
@@ -264,18 +215,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
private fun setupRecyclerView() {
|
private fun setupRecyclerView() {
|
||||||
with(main_recyclerview) {
|
with(main_recyclerview) {
|
||||||
adapter = GalleryBlockAdapter(galleries).apply {
|
adapter = GalleryBlockAdapter(galleries)
|
||||||
setClickListener { galleryID, title ->
|
|
||||||
val intent = Intent(this@MainActivity, GalleryActivity::class.java)
|
|
||||||
intent.putExtra("GALLERY_ID", galleryID)
|
|
||||||
intent.putExtra("GALLERY_TITLE", title)
|
|
||||||
|
|
||||||
//TODO: Maybe sprinke some transitions will be nice :D
|
|
||||||
startActivity(intent)
|
|
||||||
|
|
||||||
Histories.default.add(galleryID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
addOnScrollListener(
|
addOnScrollListener(
|
||||||
object: RecyclerView.OnScrollListener() {
|
object: RecyclerView.OnScrollListener() {
|
||||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||||
@@ -289,6 +229,17 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
ItemClickSupport.addTo(this).setOnItemClickListener { _, position, _ ->
|
||||||
|
val intent = Intent(this@MainActivity, ReaderActivity::class.java)
|
||||||
|
val gallery = galleries[position].first
|
||||||
|
intent.putExtra("GALLERY_ID", gallery.id)
|
||||||
|
intent.putExtra("GALLERY_TITLE", gallery.title)
|
||||||
|
|
||||||
|
//TODO: Maybe sprinke some transitions will be nice :D
|
||||||
|
startActivity(intent)
|
||||||
|
|
||||||
|
Histories.default.add(gallery.id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,9 +353,11 @@ class MainActivity : AppCompatActivity() {
|
|||||||
if (query != this@MainActivity.query) {
|
if (query != this@MainActivity.query) {
|
||||||
this@MainActivity.query = query
|
this@MainActivity.query = query
|
||||||
|
|
||||||
cancelFetch()
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
clearGalleries()
|
cancelFetch()
|
||||||
fetchGalleries(query)
|
clearGalleries()
|
||||||
|
fetchGalleries(query)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -481,29 +434,43 @@ class MainActivity : AppCompatActivity() {
|
|||||||
galleryIDs
|
galleryIDs
|
||||||
else ->
|
else ->
|
||||||
galleryIDs.slice(galleries.size until Math.min(galleries.size+perPage, galleryIDs.size))
|
galleryIDs.slice(galleries.size until Math.min(galleries.size+perPage, galleryIDs.size))
|
||||||
}.chunked(4).forEach { chunked ->
|
}.chunked(4).let { chunks ->
|
||||||
chunked.map {
|
for (chunk in chunks)
|
||||||
async {
|
chunk.map {
|
||||||
val galleryBlock = getGalleryBlock(it)
|
async {
|
||||||
val thumbnail: Bitmap
|
try {
|
||||||
|
val galleryBlock = getGalleryBlock(it)
|
||||||
|
|
||||||
with(galleryBlock.thumbnails[0].openConnection() as HttpsURLConnection) {
|
val thumbnail = async {
|
||||||
thumbnail = BitmapFactory.decodeStream(inputStream)
|
val cache = File(cacheDir, "imageCache/$it/thumbnail.${galleryBlock.thumbnails[0].path.split('.').last()}")
|
||||||
|
|
||||||
|
if (!cache.exists())
|
||||||
|
with(galleryBlock.thumbnails[0].openConnection() as HttpsURLConnection) {
|
||||||
|
if (!cache.parentFile.exists())
|
||||||
|
cache.parentFile.mkdirs()
|
||||||
|
|
||||||
|
inputStream.copyTo(FileOutputStream(cache))
|
||||||
|
}
|
||||||
|
|
||||||
|
cache.absolutePath
|
||||||
|
}
|
||||||
|
|
||||||
|
Pair(galleryBlock, thumbnail)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}.forEach {
|
||||||
|
val galleryBlock = it.await() ?: return@forEach
|
||||||
|
|
||||||
Pair(galleryBlock, thumbnail)
|
withContext(Dispatchers.Main) {
|
||||||
}
|
main_progressbar.hide()
|
||||||
}.forEach {
|
|
||||||
val galleryBlock = it.await()
|
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
galleries.add(galleryBlock)
|
||||||
main_progressbar.hide()
|
main_recyclerview.adapter?.notifyItemInserted(galleries.size - 1)
|
||||||
|
}
|
||||||
galleries.add(galleryBlock)
|
|
||||||
main_recyclerview.adapter?.notifyItemInserted(galleries.size - 1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
254
app/src/main/java/xyz/quaver/pupil/ReaderActivity.kt
Normal file
@@ -0,0 +1,254 @@
|
|||||||
|
package xyz.quaver.pupil
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.*
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.PagerSnapHelper
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import kotlinx.android.synthetic.main.activity_reader.*
|
||||||
|
import kotlinx.android.synthetic.main.activity_reader.view.*
|
||||||
|
import kotlinx.android.synthetic.main.dialog_numberpicker.view.*
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
import xyz.quaver.hitomi.Reader
|
||||||
|
import xyz.quaver.hitomi.getReader
|
||||||
|
import xyz.quaver.hitomi.getReferer
|
||||||
|
import xyz.quaver.pupil.adapters.ReaderAdapter
|
||||||
|
import xyz.quaver.pupil.util.ItemClickSupport
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
import java.net.URL
|
||||||
|
import javax.net.ssl.HttpsURLConnection
|
||||||
|
|
||||||
|
class ReaderActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
private val images = ArrayList<String>()
|
||||||
|
private var galleryID = 0
|
||||||
|
private var gallerySize: Int = 0
|
||||||
|
private var currentPage: Int = 0
|
||||||
|
private lateinit var reader: Deferred<Reader>
|
||||||
|
private var loadJob: Job? = null
|
||||||
|
|
||||||
|
private lateinit var snapHelper: PagerSnapHelper
|
||||||
|
|
||||||
|
private var menu: Menu? = null
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
window.setFlags(
|
||||||
|
WindowManager.LayoutParams.FLAG_SECURE,
|
||||||
|
WindowManager.LayoutParams.FLAG_SECURE)
|
||||||
|
|
||||||
|
setContentView(R.layout.activity_reader)
|
||||||
|
|
||||||
|
supportActionBar?.title = intent.getStringExtra("GALLERY_TITLE")
|
||||||
|
|
||||||
|
galleryID = intent.getIntExtra("GALLERY_ID", 0)
|
||||||
|
CoroutineScope(Dispatchers.Unconfined).launch {
|
||||||
|
reader = async(Dispatchers.IO) {
|
||||||
|
val preference = PreferenceManager.getDefaultSharedPreferences(this@ReaderActivity)
|
||||||
|
if (preference.getBoolean("use_hiyobi", false)) {
|
||||||
|
try {
|
||||||
|
xyz.quaver.hiyobi.getReader(galleryID)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
getReader(galleryID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getReader(galleryID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
snapHelper = PagerSnapHelper()
|
||||||
|
|
||||||
|
val preferences = PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
|
|
||||||
|
val attrs = window.attributes
|
||||||
|
|
||||||
|
if (preferences.getBoolean("reader_fullscreen", false)) {
|
||||||
|
attrs.flags = attrs.flags or WindowManager.LayoutParams.FLAG_FULLSCREEN
|
||||||
|
supportActionBar?.hide()
|
||||||
|
} else {
|
||||||
|
attrs.flags = attrs.flags and WindowManager.LayoutParams.FLAG_FULLSCREEN.inv()
|
||||||
|
supportActionBar?.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
window.attributes = attrs
|
||||||
|
|
||||||
|
if (preferences.getBoolean("reader_one_by_one", false)) {
|
||||||
|
snapHelper.attachToRecyclerView(reader_recyclerview)
|
||||||
|
reader_recyclerview.layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
|
||||||
|
} else {
|
||||||
|
snapHelper.attachToRecyclerView(null)
|
||||||
|
reader_recyclerview.layoutManager = LinearLayoutManager(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
initView()
|
||||||
|
loadImages()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
val preferences = PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
|
|
||||||
|
if (preferences.getBoolean("security_mode", false))
|
||||||
|
window.setFlags(
|
||||||
|
WindowManager.LayoutParams.FLAG_SECURE,
|
||||||
|
WindowManager.LayoutParams.FLAG_SECURE)
|
||||||
|
else
|
||||||
|
window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
|
||||||
|
|
||||||
|
super.onResume()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
||||||
|
menuInflater.inflate(R.menu.reader, menu)
|
||||||
|
this.menu = menu
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
|
||||||
|
when(item?.itemId) {
|
||||||
|
R.id.reader_menu_page_indicator -> {
|
||||||
|
val view = LayoutInflater.from(this).inflate(R.layout.dialog_numberpicker, findViewById(android.R.id.content), false)
|
||||||
|
with(view.reader_dialog_number_picker) {
|
||||||
|
minValue=1
|
||||||
|
maxValue=gallerySize
|
||||||
|
value=currentPage
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
dialog.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
loadJob?.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initView() {
|
||||||
|
with(reader_recyclerview) {
|
||||||
|
adapter = ReaderAdapter(images)
|
||||||
|
|
||||||
|
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 (layoutManager.findFirstVisibleItemPosition() == -1)
|
||||||
|
return
|
||||||
|
currentPage = layoutManager.findFirstVisibleItemPosition()+1
|
||||||
|
menu?.findItem(R.id.reader_menu_page_indicator)?.title = "$currentPage/$gallerySize"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
ItemClickSupport.addTo(this)
|
||||||
|
.setOnItemClickListener { _, _, _ ->
|
||||||
|
val attrs = window.attributes
|
||||||
|
val fullscreen = preferences.getBoolean("reader_fullscreen", false)
|
||||||
|
|
||||||
|
if (fullscreen) {
|
||||||
|
attrs.flags = attrs.flags and WindowManager.LayoutParams.FLAG_FULLSCREEN.inv()
|
||||||
|
supportActionBar?.show()
|
||||||
|
} else {
|
||||||
|
attrs.flags = attrs.flags or WindowManager.LayoutParams.FLAG_FULLSCREEN
|
||||||
|
supportActionBar?.hide()
|
||||||
|
}
|
||||||
|
|
||||||
|
window.attributes = attrs
|
||||||
|
|
||||||
|
preferences.edit().putBoolean("reader_fullscreen", !fullscreen).apply()
|
||||||
|
}.setOnItemLongClickListener { _, _, _ ->
|
||||||
|
val oneByOne = preferences.getBoolean("reader_one_by_one", false)
|
||||||
|
if (oneByOne) {
|
||||||
|
snapHelper.attachToRecyclerView(null)
|
||||||
|
reader_recyclerview.layoutManager = LinearLayoutManager(context)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
snapHelper.attachToRecyclerView(reader_recyclerview)
|
||||||
|
reader_recyclerview.layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
(reader_recyclerview.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(currentPage-1, 0)
|
||||||
|
|
||||||
|
preferences.edit().putBoolean("reader_one_by_one", !oneByOne).apply()
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadImages() {
|
||||||
|
fun webpUrlFromUrl(url: URL) = URL(url.toString().replace("/galleries/", "/webp/") + ".webp")
|
||||||
|
|
||||||
|
loadJob = CoroutineScope(Dispatchers.Default).launch {
|
||||||
|
val reader = reader.await()
|
||||||
|
|
||||||
|
launch(Dispatchers.Main) {
|
||||||
|
with(reader_progressbar) {
|
||||||
|
max = reader.size
|
||||||
|
progress = 0
|
||||||
|
|
||||||
|
visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
|
||||||
|
gallerySize = reader.size
|
||||||
|
menu?.findItem(R.id.reader_menu_page_indicator)?.title = "$currentPage/$gallerySize"
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.chunked(8).forEach { chunked ->
|
||||||
|
chunked.map {
|
||||||
|
async(Dispatchers.IO) {
|
||||||
|
val url = if (it.second?.haswebp == 1) webpUrlFromUrl(it.first) else it.first
|
||||||
|
|
||||||
|
val fileName: String
|
||||||
|
|
||||||
|
with(url.path) {
|
||||||
|
fileName = substring(lastIndexOf('/')+1)
|
||||||
|
}
|
||||||
|
|
||||||
|
val cache = File(cacheDir, "/imageCache/$galleryID/$fileName")
|
||||||
|
|
||||||
|
if (!cache.exists())
|
||||||
|
with(url.openConnection() as HttpsURLConnection) {
|
||||||
|
setRequestProperty("Referer", getReferer(galleryID))
|
||||||
|
|
||||||
|
if (!cache.parentFile.exists())
|
||||||
|
cache.parentFile.mkdirs()
|
||||||
|
|
||||||
|
inputStream.copyTo(FileOutputStream(cache))
|
||||||
|
}
|
||||||
|
|
||||||
|
cache.absolutePath
|
||||||
|
}
|
||||||
|
}.forEach {
|
||||||
|
val cache = it.await()
|
||||||
|
|
||||||
|
launch(Dispatchers.Main) {
|
||||||
|
images.add(cache)
|
||||||
|
reader_recyclerview.adapter?.notifyItemInserted(images.size - 1)
|
||||||
|
reader_progressbar.progress++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
launch(Dispatchers.Main) {
|
||||||
|
reader_progressbar.visibility = View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,12 +2,22 @@ package xyz.quaver.pupil
|
|||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.preference.PreferenceManager
|
import android.preference.PreferenceManager
|
||||||
|
import android.text.Editable
|
||||||
|
import android.text.TextWatcher
|
||||||
|
import android.view.LayoutInflater
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
|
import android.view.View
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
|
import android.widget.AdapterView
|
||||||
|
import android.widget.ArrayAdapter
|
||||||
|
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.preference.Preference
|
import androidx.preference.Preference
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
|
import kotlinx.android.synthetic.main.dialog_default_query.*
|
||||||
|
import kotlinx.android.synthetic.main.dialog_default_query.view.*
|
||||||
|
import xyz.quaver.pupil.types.Tags
|
||||||
import xyz.quaver.pupil.util.Histories
|
import xyz.quaver.pupil.util.Histories
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@@ -109,6 +119,120 @@ class SettingsActivity : AppCompatActivity() {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
with(findPreference<Preference>("default_query")) {
|
||||||
|
this ?: return@with
|
||||||
|
|
||||||
|
val preferences = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
|
||||||
|
summary = preferences.getString("default_query", "") ?: ""
|
||||||
|
|
||||||
|
val languages = resources.getStringArray(R.array.languages).map {
|
||||||
|
it.split("|").let { split ->
|
||||||
|
Pair(split[0], split[1])
|
||||||
|
}
|
||||||
|
}.toMap()
|
||||||
|
val reverseLanguages = languages.entries.associate { (k, v) -> v to k }
|
||||||
|
|
||||||
|
val excludeBL = "-male:yaoi"
|
||||||
|
val excludeGuro = listOf("-female:guro", "-male:guro")
|
||||||
|
|
||||||
|
setOnPreferenceClickListener {
|
||||||
|
val dialogView = LayoutInflater.from(context).inflate(
|
||||||
|
R.layout.dialog_default_query,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
|
||||||
|
val tags = Tags.parse(
|
||||||
|
preferences.getString("default_query", "") ?: ""
|
||||||
|
)
|
||||||
|
|
||||||
|
summary = tags.toString()
|
||||||
|
|
||||||
|
with(dialogView.default_query_dialog_language_selector) {
|
||||||
|
adapter =
|
||||||
|
ArrayAdapter<String>(
|
||||||
|
context,
|
||||||
|
android.R.layout.simple_spinner_dropdown_item,
|
||||||
|
arrayListOf(
|
||||||
|
getString(R.string.default_query_dialog_language_selector_none)
|
||||||
|
).apply {
|
||||||
|
addAll(languages.values)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if (tags.any { it.area == "language" }) {
|
||||||
|
val tag = languages[tags.first { it.area == "language" }.tag]
|
||||||
|
if (tag != null) {
|
||||||
|
setSelection(
|
||||||
|
(adapter as ArrayAdapter<String>).getPosition(tag)
|
||||||
|
)
|
||||||
|
tags.removeByArea("language")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
with(dialogView.default_query_dialog_BL_checkbox) {
|
||||||
|
isChecked = tags.contains(excludeBL)
|
||||||
|
if (tags.contains(excludeBL))
|
||||||
|
tags.remove(excludeBL)
|
||||||
|
}
|
||||||
|
|
||||||
|
with(dialogView.default_query_dialog_guro_checkbox) {
|
||||||
|
isChecked = excludeGuro.all { tags.contains(it) }
|
||||||
|
if (excludeGuro.all { tags.contains(it) })
|
||||||
|
excludeGuro.forEach {
|
||||||
|
tags.remove(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
with(dialogView.default_query_dialog_edittext) {
|
||||||
|
setText(tags.toString(), TextView.BufferType.EDITABLE)
|
||||||
|
addTextChangedListener(object : TextWatcher {
|
||||||
|
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
||||||
|
|
||||||
|
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
|
||||||
|
|
||||||
|
override fun afterTextChanged(s: Editable?) {
|
||||||
|
s ?: return
|
||||||
|
|
||||||
|
if (s.any { it.isUpperCase() })
|
||||||
|
s.replace(0, s.length, s.toString().toLowerCase())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
val dialog = AlertDialog.Builder(context!!).apply {
|
||||||
|
setView(dialogView)
|
||||||
|
}.create()
|
||||||
|
|
||||||
|
dialogView.default_query_dialog_ok.setOnClickListener {
|
||||||
|
val newTags = Tags.parse(dialogView.default_query_dialog_edittext.text.toString())
|
||||||
|
|
||||||
|
with(dialogView.default_query_dialog_language_selector) {
|
||||||
|
if (selectedItemPosition != 0)
|
||||||
|
newTags.add("language:${reverseLanguages[selectedItem]}")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dialogView.default_query_dialog_BL_checkbox.isChecked)
|
||||||
|
newTags.add(excludeBL)
|
||||||
|
|
||||||
|
if (dialogView.default_query_dialog_guro_checkbox.isChecked)
|
||||||
|
excludeGuro.forEach { tag ->
|
||||||
|
newTags.add(tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
preferenceManager.sharedPreferences.edit().putString("default_query", newTags.toString()).apply()
|
||||||
|
summary = preferences.getString("default_query", "") ?: ""
|
||||||
|
tags.clear()
|
||||||
|
tags.addAll(newTags)
|
||||||
|
dialog.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.show()
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,21 @@
|
|||||||
package xyz.quaver.pupil.adapters
|
package xyz.quaver.pupil.adapters
|
||||||
|
|
||||||
import android.graphics.Bitmap
|
import android.graphics.BitmapFactory
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import androidx.cardview.widget.CardView
|
import androidx.cardview.widget.CardView
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.google.android.material.chip.Chip
|
import com.google.android.material.chip.Chip
|
||||||
import kotlinx.android.synthetic.main.item_galleryblock.view.*
|
import kotlinx.android.synthetic.main.item_galleryblock.view.*
|
||||||
|
import kotlinx.coroutines.*
|
||||||
import xyz.quaver.hitomi.GalleryBlock
|
import xyz.quaver.hitomi.GalleryBlock
|
||||||
import xyz.quaver.hitomi.toTag
|
import xyz.quaver.hitomi.toTag
|
||||||
import xyz.quaver.pupil.R
|
import xyz.quaver.pupil.R
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
class GalleryBlockAdapter(private val galleries: List<Pair<GalleryBlock, Bitmap?>>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
class GalleryBlockAdapter(private val galleries: List<Pair<GalleryBlock, Deferred<String>>>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||||
|
|
||||||
private enum class ViewType {
|
private enum class ViewType {
|
||||||
VIEW_ITEM,
|
VIEW_ITEM,
|
||||||
@@ -33,11 +36,6 @@ class GalleryBlockAdapter(private val galleries: List<Pair<GalleryBlock, Bitmap?
|
|||||||
class ViewHolder(val view: CardView) : RecyclerView.ViewHolder(view)
|
class ViewHolder(val view: CardView) : RecyclerView.ViewHolder(view)
|
||||||
class ProgressViewHolder(view: LinearLayout) : RecyclerView.ViewHolder(view)
|
class ProgressViewHolder(view: LinearLayout) : RecyclerView.ViewHolder(view)
|
||||||
|
|
||||||
private var callback: ((Int, String) -> Unit)? = null
|
|
||||||
fun setClickListener(callback: ((Int, String) -> Unit)?) {
|
|
||||||
this.callback = callback
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||||
when(viewType) {
|
when(viewType) {
|
||||||
ViewType.VIEW_ITEM.ordinal -> {
|
ViewType.VIEW_ITEM.ordinal -> {
|
||||||
@@ -70,21 +68,43 @@ class GalleryBlockAdapter(private val galleries: List<Pair<GalleryBlock, Bitmap?
|
|||||||
}.toMap()
|
}.toMap()
|
||||||
val (gallery, thumbnail) = galleries[position]
|
val (gallery, thumbnail) = galleries[position]
|
||||||
|
|
||||||
val artists = gallery.artists.ifEmpty { listOf("N/A") }
|
val artists = gallery.artists
|
||||||
val series = gallery.series.ifEmpty { listOf("N/A") }
|
val series = gallery.series
|
||||||
|
|
||||||
setOnClickListener {
|
CoroutineScope(Dispatchers.Default).launch {
|
||||||
callback?.invoke(gallery.id, gallery.title)
|
val bitmap = BitmapFactory.decodeFile(thumbnail.await())
|
||||||
|
|
||||||
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
|
galleryblock_thumbnail.setImageBitmap(bitmap)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
galleryblock_thumbnail.setImageBitmap(thumbnail)
|
|
||||||
galleryblock_title.text = gallery.title
|
galleryblock_title.text = gallery.title
|
||||||
galleryblock_artist.text = artists.joinToString(", ") { it.wordCapitalize() }
|
with(galleryblock_artist) {
|
||||||
galleryblock_series.text =
|
text = artists.joinToString(", ") { it.wordCapitalize() }
|
||||||
resources.getString(R.string.galleryblock_series, series.joinToString(", ") { it.wordCapitalize() })
|
visibility = when {
|
||||||
|
artists.isNotEmpty() -> View.VISIBLE
|
||||||
|
else -> View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
with(galleryblock_series) {
|
||||||
|
text =
|
||||||
|
resources.getString(
|
||||||
|
R.string.galleryblock_series,
|
||||||
|
series.joinToString(", ") { it.wordCapitalize() })
|
||||||
|
visibility = when {
|
||||||
|
series.isNotEmpty() -> View.VISIBLE
|
||||||
|
else -> View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
galleryblock_type.text = resources.getString(R.string.galleryblock_type, gallery.type).wordCapitalize()
|
galleryblock_type.text = resources.getString(R.string.galleryblock_type, gallery.type).wordCapitalize()
|
||||||
galleryblock_language.text =
|
with(galleryblock_language) {
|
||||||
resources.getString(R.string.galleryblock_language, languages[gallery.language])
|
text =
|
||||||
|
resources.getString(R.string.galleryblock_language, languages[gallery.language])
|
||||||
|
visibility = when {
|
||||||
|
gallery.language.isNotEmpty() -> View.VISIBLE
|
||||||
|
else -> View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
galleryblock_tag_group.removeAllViews()
|
galleryblock_tag_group.removeAllViews()
|
||||||
gallery.relatedTags.forEach {
|
gallery.relatedTags.forEach {
|
||||||
|
|||||||
@@ -1,39 +1,31 @@
|
|||||||
package xyz.quaver.pupil.adapters
|
package xyz.quaver.pupil.adapters
|
||||||
|
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import android.util.Log
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import kotlinx.android.synthetic.main.item_reader.view.*
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import xyz.quaver.pupil.R
|
import xyz.quaver.pupil.R
|
||||||
|
|
||||||
class GalleryAdapter(private val images: List<String>) : RecyclerView.Adapter<GalleryAdapter.ViewHolder>() {
|
class ReaderAdapter(private val images: List<String>) : RecyclerView.Adapter<ReaderAdapter.ViewHolder>() {
|
||||||
|
|
||||||
class ViewHolder(val view: ImageView) : RecyclerView.ViewHolder(view)
|
class ViewHolder(val view: View) : RecyclerView.ViewHolder(view)
|
||||||
|
|
||||||
private var onClick: (() -> Unit)? = null
|
|
||||||
fun setOnClick(callback: (() -> Unit)?) {
|
|
||||||
this.onClick = callback
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
LayoutInflater.from(parent.context).inflate(
|
LayoutInflater.from(parent.context).inflate(
|
||||||
R.layout.item_gallery, parent, false
|
R.layout.item_reader, parent, false
|
||||||
).let {
|
).let {
|
||||||
return ViewHolder(it as ImageView)
|
return ViewHolder(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
with(holder.view) {
|
with(holder.view as ImageView) {
|
||||||
setOnClickListener {
|
|
||||||
onClick?.invoke()
|
|
||||||
}
|
|
||||||
|
|
||||||
CoroutineScope(Dispatchers.Default).launch {
|
CoroutineScope(Dispatchers.Default).launch {
|
||||||
val options = BitmapFactory.Options()
|
val options = BitmapFactory.Options()
|
||||||
|
|
||||||
96
app/src/main/java/xyz/quaver/pupil/types/Tags.kt
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
package xyz.quaver.pupil.types
|
||||||
|
|
||||||
|
data class Tag(val area: String?, val tag: String, val isNegative: Boolean = false) {
|
||||||
|
companion object {
|
||||||
|
fun parseTag(tag: String) : Tag {
|
||||||
|
if (tag.first() == '-') {
|
||||||
|
tag.substring(1).split(Regex(":"), 2).let {
|
||||||
|
return when(it.size) {
|
||||||
|
2 -> Tag(it[0], it[1], true)
|
||||||
|
else -> Tag(null, tag, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tag.split(Regex(":"), 2).let {
|
||||||
|
return when(it.size) {
|
||||||
|
2 -> Tag(it[0], it[1])
|
||||||
|
else -> Tag(null, tag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return (if (isNegative) "-" else "") + when(area) {
|
||||||
|
null -> tag
|
||||||
|
else -> "$area:$tag"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (other !is Tag)
|
||||||
|
return false
|
||||||
|
|
||||||
|
if (other.area == area && other.tag == tag)
|
||||||
|
return true
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return super.hashCode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Tags(tag: List<Tag?>?) : ArrayList<Tag>() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun parse(tags: String) : Tags {
|
||||||
|
return Tags(
|
||||||
|
tags.split(' ').map {
|
||||||
|
if (it.isNotEmpty())
|
||||||
|
Tag.parseTag(it)
|
||||||
|
else
|
||||||
|
null
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
tag?.forEach {
|
||||||
|
if (it != null)
|
||||||
|
add(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun contains(element: String): Boolean {
|
||||||
|
forEach {
|
||||||
|
if (it.toString() == element)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun add(element: String): Boolean {
|
||||||
|
return super.add(Tag.parseTag(element))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun remove(element: String) {
|
||||||
|
filter { it.toString() == element }.forEach {
|
||||||
|
remove(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun removeByArea(area: String) {
|
||||||
|
filter { it.area == area }.forEach {
|
||||||
|
remove(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return joinToString(" ") { it.toString() }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
107
app/src/main/java/xyz/quaver/pupil/util/ItemClickSupport.java
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
package xyz.quaver.pupil.util;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import xyz.quaver.pupil.R;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Source: http://www.littlerobots.nl/blog/Handle-Android-RecyclerView-Clicks/
|
||||||
|
USAGE:
|
||||||
|
|
||||||
|
ItemClickSupport.addTo(mRecyclerView).setOnItemClickListener(new ItemClickSupport.OnItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemClicked(RecyclerView recyclerView, int position, View v) {
|
||||||
|
// do it
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
*/
|
||||||
|
public class ItemClickSupport {
|
||||||
|
private final RecyclerView mRecyclerView;
|
||||||
|
private OnItemClickListener mOnItemClickListener;
|
||||||
|
private OnItemLongClickListener mOnItemLongClickListener;
|
||||||
|
private View.OnClickListener mOnClickListener = new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (mOnItemClickListener != null) {
|
||||||
|
RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
|
||||||
|
mOnItemClickListener.onItemClicked(mRecyclerView, holder.getAdapterPosition(), v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private View.OnLongClickListener mOnLongClickListener = new View.OnLongClickListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onLongClick(View v) {
|
||||||
|
if (mOnItemLongClickListener != null) {
|
||||||
|
RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(v);
|
||||||
|
return mOnItemLongClickListener.onItemLongClicked(mRecyclerView, holder.getAdapterPosition(), v);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private RecyclerView.OnChildAttachStateChangeListener mAttachListener
|
||||||
|
= new RecyclerView.OnChildAttachStateChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onChildViewAttachedToWindow(@NonNull View view) {
|
||||||
|
if (mOnItemClickListener != null) {
|
||||||
|
view.setOnClickListener(mOnClickListener);
|
||||||
|
}
|
||||||
|
if (mOnItemLongClickListener != null) {
|
||||||
|
view.setOnLongClickListener(mOnLongClickListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChildViewDetachedFromWindow(@NonNull View view) {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private ItemClickSupport(RecyclerView recyclerView) {
|
||||||
|
mRecyclerView = recyclerView;
|
||||||
|
mRecyclerView.setTag(R.id.item_click_support, this);
|
||||||
|
mRecyclerView.addOnChildAttachStateChangeListener(mAttachListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ItemClickSupport addTo(RecyclerView view) {
|
||||||
|
ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
|
||||||
|
if (support == null) {
|
||||||
|
support = new ItemClickSupport(view);
|
||||||
|
}
|
||||||
|
return support;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ItemClickSupport removeFrom(RecyclerView view) {
|
||||||
|
ItemClickSupport support = (ItemClickSupport) view.getTag(R.id.item_click_support);
|
||||||
|
if (support != null) {
|
||||||
|
support.detach(view);
|
||||||
|
}
|
||||||
|
return support;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemClickSupport setOnItemClickListener(OnItemClickListener listener) {
|
||||||
|
mOnItemClickListener = listener;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemClickSupport setOnItemLongClickListener(OnItemLongClickListener listener) {
|
||||||
|
mOnItemLongClickListener = listener;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void detach(RecyclerView view) {
|
||||||
|
view.removeOnChildAttachStateChangeListener(mAttachListener);
|
||||||
|
view.setTag(R.id.item_click_support, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface OnItemClickListener {
|
||||||
|
|
||||||
|
void onItemClicked(RecyclerView recyclerView, int position, View v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface OnItemLongClickListener {
|
||||||
|
|
||||||
|
boolean onItemLongClicked(RecyclerView recyclerView, int position, View v);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,12 +20,3 @@ fun checkUpdate(url: String, currentVersion: String) : JsonObject? {
|
|||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getApkUrl(releases: JsonObject, releaseName: String) : Pair<String?, String?>? {
|
|
||||||
releases["assets"]?.jsonArray?.forEach {
|
|
||||||
if (Regex(releaseName).matches(it.jsonObject["name"]?.content ?: ""))
|
|
||||||
return Pair(it.jsonObject["browser_download_url"]?.content, it.jsonObject["name"]?.content)
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
10
app/src/main/res/drawable-anydpi/ic_email.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="#333333">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M20,4L4,4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2zM20,8l-8,5 -8,-5L4,6l8,5 8,-5v2z"/>
|
||||||
|
</vector>
|
||||||
10
app/src/main/res/drawable-anydpi/ic_help.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="#333333">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,19h-2v-2h2v2zM15.07,11.25l-0.9,0.92C13.45,12.9 13,13.5 13,15h-2v-0.5c0,-1.1 0.45,-2.1 1.17,-2.83l1.24,-1.26c0.37,-0.36 0.59,-0.86 0.59,-1.41 0,-1.1 -0.9,-2 -2,-2s-2,0.9 -2,2L8,9c0,-2.21 1.79,-4 4,-4s4,1.79 4,4c0,0.88 -0.36,1.68 -0.93,2.25z"/>
|
||||||
|
</vector>
|
||||||
BIN
app/src/main/res/drawable-hdpi/ic_email.png
Normal file
|
After Width: | Height: | Size: 325 B |
BIN
app/src/main/res/drawable-hdpi/ic_help.png
Normal file
|
After Width: | Height: | Size: 571 B |
BIN
app/src/main/res/drawable-mdpi/ic_email.png
Normal file
|
After Width: | Height: | Size: 235 B |
BIN
app/src/main/res/drawable-mdpi/ic_help.png
Normal file
|
After Width: | Height: | Size: 345 B |
BIN
app/src/main/res/drawable-xhdpi/ic_email.png
Normal file
|
After Width: | Height: | Size: 383 B |
BIN
app/src/main/res/drawable-xhdpi/ic_help.png
Normal file
|
After Width: | Height: | Size: 676 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_email.png
Normal file
|
After Width: | Height: | Size: 550 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_help.png
Normal file
|
After Width: | Height: | Size: 1000 B |
@@ -6,7 +6,6 @@
|
|||||||
android:id="@+id/main_drawer_layout"
|
android:id="@+id/main_drawer_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:fitsSystemWindows="true"
|
|
||||||
tools:openDrawer="start">
|
tools:openDrawer="start">
|
||||||
|
|
||||||
<include layout="@layout/activity_main_content"
|
<include layout="@layout/activity_main_content"
|
||||||
@@ -18,7 +17,6 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_gravity="start"
|
android:layout_gravity="start"
|
||||||
android:fitsSystemWindows="true"
|
|
||||||
app:headerLayout="@layout/nav_header_main"
|
app:headerLayout="@layout/nav_header_main"
|
||||||
app:menu="@menu/activity_main_drawer"/>
|
app:menu="@menu/activity_main_drawer"/>
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
<View
|
<View
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="64dp"
|
android:layout_height="80dp"
|
||||||
android:visibility="invisible"
|
android:visibility="invisible"
|
||||||
android:background="@color/transparent"
|
android:background="@color/transparent"
|
||||||
app:layout_scrollFlags="scroll|enterAlways"
|
app:layout_scrollFlags="scroll|enterAlways"
|
||||||
@@ -50,13 +50,13 @@
|
|||||||
android:id="@+id/main_swipe_layout"
|
android:id="@+id/main_swipe_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginBottom="-64dp">
|
android:layout_marginBottom="-80dp">
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/main_recyclerview"
|
android:id="@+id/main_recyclerview"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:paddingTop="64dp"
|
android:paddingTop="80dp"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:scrollbars="vertical"
|
android:scrollbars="vertical"
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
|
||||||
@@ -71,7 +71,7 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
app:floatingSearch_searchBarMarginLeft="8dp"
|
app:floatingSearch_searchBarMarginLeft="8dp"
|
||||||
app:floatingSearch_searchBarMarginRight="8dp"
|
app:floatingSearch_searchBarMarginRight="8dp"
|
||||||
app:floatingSearch_searchBarMarginTop="8dp"
|
app:floatingSearch_searchBarMarginTop="24dp"
|
||||||
app:floatingSearch_searchHint="@string/search_hint"
|
app:floatingSearch_searchHint="@string/search_hint"
|
||||||
app:floatingSearch_suggestionsListAnimDuration="250"
|
app:floatingSearch_suggestionsListAnimDuration="250"
|
||||||
app:floatingSearch_showSearchKey="true"
|
app:floatingSearch_showSearchKey="true"
|
||||||
|
|||||||
@@ -1,18 +1,25 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context=".GalleryActivity">
|
tools:context=".ReaderActivity">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/reader_recyclerview"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/gallery_framelayout"
|
android:id="@+id/reader_framelayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="4dp">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/gallery_progressbar"
|
android:id="@+id/reader_progressbar"
|
||||||
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
|
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="4dp"
|
android:layout_height="4dp"
|
||||||
@@ -20,11 +27,4 @@
|
|||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
android:id="@+id/gallery_recyclerview"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_below="@id/gallery_framelayout"
|
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
||||||
111
app/src/main/res/layout/dialog_default_query.xml
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/default_query_dialog_title"
|
||||||
|
style="@style/TextAppearance.AppCompat.Large"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/default_query_dialog_title"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"/>
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
tools:ignore="Autofill"
|
||||||
|
android:inputType="text"
|
||||||
|
android:hint="@string/settings_default_query"
|
||||||
|
android:id="@+id/default_query_dialog_edittext"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/default_query_dialog_title"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/default_query_dialog_language_layout"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/default_query_dialog_edittext"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/default_query_dialog_language"/>
|
||||||
|
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/default_query_dialog_language_selector"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/default_query_dialog_BL_layout"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingLeft="0dp"
|
||||||
|
android:paddingStart="0dp"
|
||||||
|
android:paddingEnd="8dp"
|
||||||
|
android:paddingRight="8dp"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/default_query_dialog_language_layout"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/default_query_dialog_filter_BL"/>
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/default_query_dialog_BL_checkbox"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/default_query_dialog_guro_layout"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingLeft="0dp"
|
||||||
|
android:paddingStart="0dp"
|
||||||
|
android:paddingEnd="8dp"
|
||||||
|
android:paddingRight="8dp"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/default_query_dialog_BL_layout"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/default_query_dialog_filter_guro"/>
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/default_query_dialog_guro_checkbox"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/default_query_dialog_ok"
|
||||||
|
style="?borderlessButtonStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/default_query_dialog_guro_layout"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
android:text="@android:string/ok"/>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
35
app/src/main/res/layout/dialog_numberpicker.xml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
style="?android:textAppearanceLarge"
|
||||||
|
android:id="@+id/reader_dialog_title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/reader_go_to_page"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"/>
|
||||||
|
|
||||||
|
<NumberPicker
|
||||||
|
android:id="@+id/reader_dialog_number_picker"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/reader_dialog_title"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/reader_dialog_ok"
|
||||||
|
style="?borderlessButtonStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@android:string/ok"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/reader_dialog_number_picker"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"/>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
@@ -78,8 +78,17 @@
|
|||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
app:layout_constraintTop_toBottomOf="@id/galleryblock_type"
|
app:layout_constraintTop_toBottomOf="@id/galleryblock_type"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/galleryblock_padding"
|
||||||
app:layout_constraintStart_toEndOf="@id/galleryblock_thumbnail" />
|
app:layout_constraintStart_toEndOf="@id/galleryblock_thumbnail" />
|
||||||
|
|
||||||
|
<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"/>
|
||||||
|
|
||||||
<com.google.android.material.chip.ChipGroup
|
<com.google.android.material.chip.ChipGroup
|
||||||
android:id="@+id/galleryblock_tag_group"
|
android:id="@+id/galleryblock_tag_group"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
@@ -90,7 +99,7 @@
|
|||||||
android:layout_marginBottom="16dp"
|
android:layout_marginBottom="16dp"
|
||||||
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_language"
|
app:layout_constraintTop_toBottomOf="@id/galleryblock_padding"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|||||||
@@ -4,6 +4,5 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingBottom="8dp"
|
android:paddingBottom="8dp"
|
||||||
android:adjustViewBounds="true"
|
android:scaleType="fitCenter"
|
||||||
android:clickable="true"
|
android:adjustViewBounds="true"/>
|
||||||
android:focusable="true"/>
|
|
||||||
@@ -12,4 +12,21 @@
|
|||||||
android:icon="@drawable/ic_history"/>
|
android:icon="@drawable/ic_history"/>
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
|
<item android:title="@string/main_drawer_group_contact_title">
|
||||||
|
<menu>
|
||||||
|
<item android:id="@+id/main_drawer_help"
|
||||||
|
android:title="@string/main_drawer_group_contact_help"
|
||||||
|
android:icon="@drawable/ic_help"/>
|
||||||
|
<item android:id="@+id/main_drawer_github"
|
||||||
|
android:title="@string/main_drawer_group_contact_github"
|
||||||
|
android:icon="@drawable/github_circle"/>
|
||||||
|
<item android:id="@+id/main_drawer_homepage"
|
||||||
|
android:title="@string/main_drawer_group_contact_homepage"
|
||||||
|
android:icon="@drawable/ic_home"/>
|
||||||
|
<item android:id="@+id/main_drawer_email"
|
||||||
|
android:title="@string/main_drawer_group_contact_email"
|
||||||
|
android:icon="@drawable/ic_email"/>
|
||||||
|
</menu>
|
||||||
|
</item>
|
||||||
|
|
||||||
</menu>
|
</menu>
|
||||||
9
app/src/main/res/menu/reader.xml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item android:id="@+id/reader_menu_page_indicator"
|
||||||
|
android:title="@string/reader_page_indicator_placeholder"
|
||||||
|
app:showAsAction="always|withText"/>
|
||||||
|
|
||||||
|
</menu>
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
<string name="settings_clear_image_cache">イメージキャッシュクリア</string>
|
<string name="settings_clear_image_cache">イメージキャッシュクリア</string>
|
||||||
<string name="settings_clear_cache_alert_message">キャッシュをクリアするとイメージのロード速度に影響を与えます。実行しますか?</string>
|
<string name="settings_clear_cache_alert_message">キャッシュをクリアするとイメージのロード速度に影響を与えます。実行しますか?</string>
|
||||||
<string name="settings_clear_cache_summary">キャッシュサイズ: %1$d%2$s</string>
|
<string name="settings_clear_cache_summary">キャッシュサイズ: %1$d%2$s</string>
|
||||||
<string name="settings_default_query">デフォルト検索キーワード</string>
|
<string name="settings_default_query">デフォルトキーワード</string>
|
||||||
<string name="permission_explain">権限を拒否すると一部の機能が利用できません</string>
|
<string name="permission_explain">権限を拒否すると一部の機能が利用できません</string>
|
||||||
<string name="settings_galleries_per_page">一回にロードするギャラリー数</string>
|
<string name="settings_galleries_per_page">一回にロードするギャラリー数</string>
|
||||||
<string name="settings_search_title">検索設定</string>
|
<string name="settings_search_title">検索設定</string>
|
||||||
@@ -30,4 +30,17 @@
|
|||||||
<string name="update_release_note"># リリースノート(v%1$s)\n%2$s</string>
|
<string name="update_release_note"># リリースノート(v%1$s)\n%2$s</string>
|
||||||
<string name="settings_security_mode_title">セキュリティーモード</string>
|
<string name="settings_security_mode_title">セキュリティーモード</string>
|
||||||
<string name="settings_security_mode_summary">アプリ履歴でアプリの画面を表示しない</string>
|
<string name="settings_security_mode_summary">アプリ履歴でアプリの画面を表示しない</string>
|
||||||
|
<string name="reader_go_to_page">移動</string>
|
||||||
|
<string name="default_query_dialog_language_selector_none">非選択</string>
|
||||||
|
<string name="default_query_dialog_filter_BL">BLフィルター</string>
|
||||||
|
<string name="default_query_dialog_filter_guro">グロフィルター</string>
|
||||||
|
<string name="default_query_dialog_language">"言語: "</string>
|
||||||
|
<string name="default_query_dialog_title">デフォルトキーワード設定</string>
|
||||||
|
<string name="main_drawer_group_contact_title">お問い合わせ先</string>
|
||||||
|
<string name="main_drawer_group_contact_homepage">ホームページ</string>
|
||||||
|
<string name="main_drawer_group_contact_help">ヘルプ</string>
|
||||||
|
<string name="main_drawer_group_contact_github">Github</string>
|
||||||
|
<string name="main_drawer_group_contact_email">メールを送る</string>
|
||||||
|
<string name="help_dialog_title">準備中</string>
|
||||||
|
<string name="help_dialog_message">準備中です。</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -30,4 +30,17 @@
|
|||||||
<string name="update_release_note"># 릴리즈 노트(v%1$s)\n%2$s</string>
|
<string name="update_release_note"># 릴리즈 노트(v%1$s)\n%2$s</string>
|
||||||
<string name="settings_security_mode_summary">최근 앱 목록 창에서 앱 화면을 보이지 않게 합니다</string>
|
<string name="settings_security_mode_summary">최근 앱 목록 창에서 앱 화면을 보이지 않게 합니다</string>
|
||||||
<string name="settings_security_mode_title">보안 모드 활성화</string>
|
<string name="settings_security_mode_title">보안 모드 활성화</string>
|
||||||
|
<string name="reader_go_to_page">이동</string>
|
||||||
|
<string name="default_query_dialog_language_selector_none">미선택</string>
|
||||||
|
<string name="default_query_dialog_filter_BL">BL물 필터</string>
|
||||||
|
<string name="default_query_dialog_filter_guro">고어물 필터</string>
|
||||||
|
<string name="default_query_dialog_language">"언어: "</string>
|
||||||
|
<string name="default_query_dialog_title">기본 검색어 설정</string>
|
||||||
|
<string name="main_drawer_group_contact_email">메일 보내기!</string>
|
||||||
|
<string name="main_drawer_group_contact_github">Github</string>
|
||||||
|
<string name="main_drawer_group_contact_help">도움말</string>
|
||||||
|
<string name="main_drawer_group_contact_homepage">홈페이지</string>
|
||||||
|
<string name="main_drawer_group_contact_title">문의</string>
|
||||||
|
<string name="help_dialog_title">준비 중</string>
|
||||||
|
<string name="help_dialog_message">준비중입니다.\n만화 화면에서 사진을 길게 누르면 스크롤 방식이 바뀝니다. 알고 계셨나요? :)</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<style name="NoActionBarAppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
|
<style name="NoActionBarAppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
|
||||||
|
<item name="android:windowTranslucentStatus">true</item>
|
||||||
|
<item name="android:windowTranslucentNavigation">true</item>
|
||||||
<item name="android:windowLightStatusBar">true</item>
|
<item name="android:windowLightStatusBar">true</item>
|
||||||
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
|
|
||||||
<item name="android:statusBarColor">@color/transparent</item>
|
|
||||||
<!-- 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>
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
<dimen name="appbar_padding">64dp</dimen>
|
<dimen name="appbar_padding">64dp</dimen>
|
||||||
<dimen name="progress_view_offset">80dp</dimen>
|
<dimen name="progress_view_start">32dp</dimen>
|
||||||
|
<dimen name="progress_view_offset">96dp</dimen>
|
||||||
|
|
||||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||||
|
|||||||
4
app/src/main/res/values/ids.xml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<item name="item_click_support" type="id" />
|
||||||
|
</resources>
|
||||||
@@ -4,10 +4,17 @@
|
|||||||
<string name="release_url" translatable="false">https://api.github.com/repos/tom5079/Pupil-issue/releases</string>
|
<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="release_name" translatable="false">Pupil-v(\\d+\\.)+\\d+\\.apk</string>
|
||||||
|
|
||||||
|
<string name="home_page" translatable="false">https://tom5079.github.io/Pupil</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>
|
||||||
|
|
||||||
<string name="main_settings" translatable="false">Settings</string>
|
<string name="main_settings" translatable="false">Settings</string>
|
||||||
<string name="galleryblock_thumbnail_description" translatable="false">Thumbnail</string>
|
<string name="galleryblock_thumbnail_description" translatable="false">Thumbnail</string>
|
||||||
|
|
||||||
<string name="reader_imageview_description" translatable="false">Content ImageView</string>
|
<string name="reader_imageview_description" translatable="false">Content ImageView</string>
|
||||||
|
<string name="reader_page_indicator_placeholder" translatable="false">-/-</string>
|
||||||
|
|
||||||
|
<string name="plus_to_close" translatable="false">Fab</string>
|
||||||
|
|
||||||
<!-- Translate needed down here -->
|
<!-- Translate needed down here -->
|
||||||
|
|
||||||
@@ -20,6 +27,14 @@
|
|||||||
|
|
||||||
<string name="main_drawer_home">Home</string>
|
<string name="main_drawer_home">Home</string>
|
||||||
<string name="main_drawer_history">History</string>
|
<string name="main_drawer_history">History</string>
|
||||||
|
<string name="main_drawer_group_contact_title">Contact</string>
|
||||||
|
<string name="main_drawer_group_contact_help">Help</string>
|
||||||
|
<string name="main_drawer_group_contact_homepage">Visit homepage</string>
|
||||||
|
<string name="main_drawer_group_contact_github">Visit github</string>
|
||||||
|
<string name="main_drawer_group_contact_email">Email me!</string>
|
||||||
|
|
||||||
|
<string name="help_dialog_title">WIP</string>
|
||||||
|
<string name="help_dialog_message">While in progress!\nOne thing might you don\'t know:\nLong tap an image in reader will change scrolling mode! Go try it :)</string>
|
||||||
|
|
||||||
<string name="update_title">Update available</string>
|
<string name="update_title">Update available</string>
|
||||||
<string name="update_download_started">Download started</string>
|
<string name="update_download_started">Download started</string>
|
||||||
@@ -32,6 +47,8 @@
|
|||||||
<string name="galleryblock_type">Type: %1$s</string>
|
<string name="galleryblock_type">Type: %1$s</string>
|
||||||
<string name="galleryblock_language">Language: %1$s</string>
|
<string name="galleryblock_language">Language: %1$s</string>
|
||||||
|
|
||||||
|
<string name="reader_go_to_page">Go to page</string>
|
||||||
|
|
||||||
<string name="settings_title">Settings</string>
|
<string name="settings_title">Settings</string>
|
||||||
<string name="settings_search_title">Search Settings</string>
|
<string name="settings_search_title">Search Settings</string>
|
||||||
<string name="settings_galleries_per_page">Galleries per page</string>
|
<string name="settings_galleries_per_page">Galleries per page</string>
|
||||||
@@ -49,4 +66,10 @@
|
|||||||
<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="default_query_dialog_title">Set default query</string>
|
||||||
|
<string name="default_query_dialog_language">Language: </string>
|
||||||
|
<string name="default_query_dialog_filter_BL">Filter BL</string>
|
||||||
|
<string name="default_query_dialog_filter_guro">Filter Guro</string>
|
||||||
|
<string name="default_query_dialog_language_selector_none">Any</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
app:defaultValue="25"
|
app:defaultValue="25"
|
||||||
app:useSimpleSummaryProvider="true"/>
|
app:useSimpleSummaryProvider="true"/>
|
||||||
|
|
||||||
<EditTextPreference
|
<Preference
|
||||||
app:key="default_query"
|
app:key="default_query"
|
||||||
app:title="@string/settings_default_query"
|
app:title="@string/settings_default_query"
|
||||||
app:defaultValue=""
|
app:defaultValue=""
|
||||||
|
|||||||