Compare commits

...

12 Commits

Author SHA1 Message Date
tom5079
331cbec5f1 Bug fix 2020-10-14 18:36:36 +09:00
tom5079
7f02284285 Update README.md 2020-10-14 00:26:06 +09:00
tom5079
ac2c3a6d97 Merge remote-tracking branch 'origin/master' into master 2020-10-14 00:25:44 +09:00
tom5079
c3bc80fec6 Bug fix 2020-10-14 00:24:38 +09:00
tom5079
09779a0710 Update README.md 2020-10-13 23:47:56 +09:00
tom5079
e82c6ef866 App built
Possible build time optimization
2020-10-13 23:40:53 +09:00
tom5079
861ae9be64 Merge remote-tracking branch 'origin/dev' into dev 2020-10-13 23:34:28 +09:00
tom5079
96108bc1ec Improves Scroll Jitter 2020-10-13 23:34:16 +09:00
tom5079
016f217db0 Merge pull request #108 from klx7007/patch-1
Fix FloatingSearchView imeOptions to only affect keyboard visibility
2020-10-13 23:05:34 +09:00
tom5079
0688294f18 Dependency update
Support non external storage document Uris

Support non external storage document Uris
2020-10-13 22:59:29 +09:00
klx7007
9ad008255d FloatingSearchView imeOptions 수정
imeOption을 덮어씌워서 search할때 키보드만 숨겨짐
2020-10-13 22:58:13 +09:00
tom5079
4c5a862dd6 Update README.md 2020-10-13 17:57:19 +09:00
20 changed files with 103 additions and 67 deletions

1
.idea/gradle.xml generated
View File

@@ -14,6 +14,7 @@
</set> </set>
</option> </option>
<option name="resolveModulePerSourceSet" value="false" /> <option name="resolveModulePerSourceSet" value="false" />
<option name="useQualifiedModuleNames" value="true" />
</GradleProjectSettings> </GradleProjectSettings>
</option> </option>
</component> </component>

View File

@@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="AndroidLintNewerVersionAvailable" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>

View File

@@ -2,7 +2,7 @@
*Pupil, Hitomi.la viewer for Android* *Pupil, Hitomi.la viewer for Android*
![](https://img.shields.io/github/downloads/tom5079/Pupil/total) ![](https://img.shields.io/github/downloads/tom5079/Pupil/total)
[![](https://img.shields.io/github/downloads/tom5079/Pupil/5.1.4/Pupil-v5.1.4.apk?color=%234fc3f7&label=DOWNLOAD%20APP&style=for-the-badge)](https://github.com/tom5079/Pupil/releases/download/5.1.4/Pupil-v5.1.4.apk) [![](https://img.shields.io/github/downloads/tom5079/Pupil/5.1.5-hotfix2/Pupil-v5.1.5-hotfix2.apk?color=%234fc3f7&label=DOWNLOAD%20APP&style=for-the-badge)](https://github.com/tom5079/Pupil/releases/download/5.1.5-hotfix2/Pupil-v5.1.5-hotfix2.apk)
[![](https://discordapp.com/api/guilds/610452916612104194/embed.png?style=banner2)](https://discord.gg/Stj4b5v) [![](https://discordapp.com/api/guilds/610452916612104194/embed.png?style=banner2)](https://discord.gg/Stj4b5v)
# Features # Features

View File

@@ -38,7 +38,7 @@ android {
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 30 targetSdkVersion 30
versionCode 63 versionCode 63
versionName "5.1.4-hotfix1" versionName "5.1.5-hotfix2"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
} }
@@ -77,13 +77,13 @@ android {
dependencies { dependencies {
implementation fileTree(dir: "libs", include: ["*.jar", "*.aar"]) implementation fileTree(dir: "libs", include: ["*.jar", "*.aar"])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.0-M1"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.0-RC2" implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.0"
implementation "androidx.appcompat:appcompat:1.2.0" implementation "androidx.appcompat:appcompat:1.2.0"
implementation "androidx.activity:activity-ktx:1.2.0-beta01" implementation "androidx.activity:activity-ktx:1.2.0-beta01"
implementation "androidx.fragment:fragment-ktx:1.3.0-beta01" implementation "androidx.fragment:fragment-ktx:1.3.0-beta01"
implementation "androidx.preference:preference:1.1.1" implementation "androidx.preference:preference-ktx:1.1.1"
implementation "androidx.constraintlayout:constraintlayout:2.0.2" implementation "androidx.constraintlayout:constraintlayout:2.0.2"
implementation "androidx.gridlayout:gridlayout:1.0.0" implementation "androidx.gridlayout:gridlayout:1.0.0"
implementation "androidx.biometric:biometric:1.0.1" implementation "androidx.biometric:biometric:1.0.1"
@@ -123,7 +123,7 @@ dependencies {
implementation "ru.noties.markwon:core:3.1.0" implementation "ru.noties.markwon:core:3.1.0"
implementation "xyz.quaver:libpupil:1.7.2" implementation "xyz.quaver:libpupil:1.7.2"
implementation "xyz.quaver:documentfilex:0.3.1" implementation "xyz.quaver:documentfilex:0.4-alpha02"
implementation "xyz.quaver:floatingsearchview:1.0.7" implementation "xyz.quaver:floatingsearchview:1.0.7"
testImplementation "junit:junit:4.13" testImplementation "junit:junit:4.13"

View File

@@ -1,19 +1,17 @@
{ {
"version": 1, "version": 2,
"artifactType": { "artifactType": {
"type": "APK", "type": "APK",
"kind": "Directory" "kind": "Directory"
}, },
"applicationId": "xyz.quaver.pupil", "applicationId": "xyz.quaver.pupil",
"variantName": "release", "variantName": "processReleaseResources",
"elements": [ "elements": [
{ {
"type": "SINGLE", "type": "SINGLE",
"filters": [], "filters": [],
"properties": [],
"versionCode": 63, "versionCode": 63,
"versionName": "5.1.4-hotfix1", "versionName": "5.1.5-hotfix2",
"enabled": true,
"outputFile": "app-release.apk" "outputFile": "app-release.apk"
} }
] ]

View File

@@ -18,7 +18,10 @@
package xyz.quaver.pupil package xyz.quaver.pupil
import android.app.* import android.app.Application
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri

View File

@@ -20,6 +20,7 @@ package xyz.quaver.pupil.adapters
import android.content.Context import android.content.Context
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.util.Log
import android.util.SparseBooleanArray import android.util.SparseBooleanArray
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@@ -229,24 +230,29 @@ class GalleryBlockAdapter(private val galleries: List<Int>) : RecyclerSwipeAdapt
} }
tags.clear() tags.clear()
tags.addAll(
galleryBlock.relatedTags.sortedBy {
val tag = Tag.parse(it)
if (favoriteTags.contains(tag)) CoroutineScope(Dispatchers.IO).launch {
-1 tags.addAll(
else galleryBlock.relatedTags.sortedBy {
when(Tag.parse(it).area) { val tag = Tag.parse(it)
"female" -> 0
"male" -> 1 if (favoriteTags.contains(tag))
else -> 2 -1
} else
}.map { when(Tag.parse(it).area) {
Tag.parse(it) "female" -> 0
"male" -> 1
else -> 2
}
}.map {
Tag.parse(it)
}
)
launch(Dispatchers.Main) {
refresh()
} }
) }
refresh()
} }
galleryblock_id.text = galleryBlock.id.toString() galleryblock_id.text = galleryBlock.id.toString()

View File

@@ -255,13 +255,15 @@ class SettingsFragment :
isEnabled = false isEnabled = false
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {
val languages = getAvailableLanguages().distinct().toTypedArray() kotlin.runCatching {
val languages = getAvailableLanguages().distinct().toTypedArray()
entries = languages.map { Locale(it).let { loc -> loc.getDisplayLanguage(loc) } }.toTypedArray() entries = languages.map { Locale(it).let { loc -> loc.getDisplayLanguage(loc) } }.toTypedArray()
entryValues = languages entryValues = languages
launch(Dispatchers.Main) { launch(Dispatchers.Main) {
isEnabled = true isEnabled = true
}
} }
} }

View File

@@ -57,7 +57,7 @@ class FloatingSearchView @JvmOverloads constructor(context: Context, attrs: Attr
var onFavoriteHistorySwitchClickListener: (() -> Unit)? = null var onFavoriteHistorySwitchClickListener: (() -> Unit)? = null
init { init {
searchInputView.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI searchInputView.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI or searchInputView.imeOptions
searchInputView.addTextChangedListener(this) searchInputView.addTextChangedListener(this)
onSearchListener = this onSearchListener = this
@@ -215,4 +215,4 @@ class FloatingSearchView @JvmOverloads constructor(context: Context, attrs: Attr
} }
} }
} }
} }

View File

@@ -21,8 +21,10 @@ package xyz.quaver.pupil.ui.view
import android.content.Context import android.content.Context
import android.content.res.TypedArray import android.content.res.TypedArray
import android.util.AttributeSet import android.util.AttributeSet
import android.util.Log
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
import com.google.android.material.chip.ChipGroup import com.google.android.material.chip.ChipGroup
import kotlinx.coroutines.*
import xyz.quaver.pupil.R import xyz.quaver.pupil.R
import xyz.quaver.pupil.types.Tag import xyz.quaver.pupil.types.Tag
import xyz.quaver.pupil.types.Tags import xyz.quaver.pupil.types.Tags
@@ -66,19 +68,27 @@ class TagChipGroup @JvmOverloads constructor(context: Context, attr: AttributeSe
maxChipSize = attr.getInt(R.styleable.TagChipGroup_maxTag, Defaults.maxChipSize) maxChipSize = attr.getInt(R.styleable.TagChipGroup_maxTag, Defaults.maxChipSize)
} }
private var refreshJob: Job? = null
fun refresh() { fun refresh() {
refreshJob?.cancel()
this.removeAllViews() this.removeAllViews()
tags.take(maxChipSize).forEach { refreshJob = CoroutineScope(Dispatchers.Main).launch {
this.addView(TagChip(context, it).apply { tags.take(maxChipSize).map {
setOnClickListener { CoroutineScope(Dispatchers.Default).async {
onClickListener?.invoke(this.tag) TagChip(context, it).apply {
setOnClickListener {
onClickListener?.invoke(this.tag)
}
}
} }
}) }.forEach {
} addView(it.await())
}
if (maxChipSize > 0 && this.size > maxChipSize) if (maxChipSize > 0 && tags.size > maxChipSize && parent == null)
addView(moreView) addView(moreView)
}
} }
init { init {

View File

@@ -24,7 +24,7 @@ import kotlinx.serialization.json.Json
import java.io.File import java.io.File
import java.util.* import java.util.*
class SavedSet <T: Any> (private val file: File, private val any: T, private val set: MutableSet<T> = Collections.synchronizedSet(mutableSetOf())) : MutableSet<T> by set { class SavedSet <T: Any> (private val file: File, private val any: T, private val set: MutableSet<T> = mutableSetOf()) : MutableSet<T> by set {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
@OptIn(ExperimentalSerializationApi::class) @OptIn(ExperimentalSerializationApi::class)
@@ -39,24 +39,23 @@ class SavedSet <T: Any> (private val file: File, private val any: T, private val
load() load()
} }
@Synchronized
fun load() { fun load() {
synchronized(this) { set.clear()
set.clear() kotlin.runCatching {
kotlin.runCatching { Json.decodeFromString(serializer, file.readText())
Json.decodeFromString(serializer, file.readText()) }.onSuccess {
}.onSuccess { set.addAll(it)
set.addAll(it)
}
} }
} }
@Synchronized
@OptIn(ExperimentalSerializationApi::class) @OptIn(ExperimentalSerializationApi::class)
fun save() { fun save() {
synchronized(this) { file.writeText(Json.encodeToString(serializer, set.toList()))
file.writeText(Json.encodeToString(serializer, set.toList()))
}
} }
@Synchronized
override fun add(element: T): Boolean { override fun add(element: T): Boolean {
load() load()
@@ -67,6 +66,7 @@ class SavedSet <T: Any> (private val file: File, private val any: T, private val
} }
} }
@Synchronized
override fun addAll(elements: Collection<T>): Boolean { override fun addAll(elements: Collection<T>): Boolean {
load() load()
@@ -77,6 +77,7 @@ class SavedSet <T: Any> (private val file: File, private val any: T, private val
} }
} }
@Synchronized
override fun remove(element: T): Boolean { override fun remove(element: T): Boolean {
load() load()
@@ -85,6 +86,7 @@ class SavedSet <T: Any> (private val file: File, private val any: T, private val
} }
} }
@Synchronized
override fun clear() { override fun clear() {
set.clear() set.clear()
save() save()

View File

@@ -80,7 +80,7 @@ class DownloadManager private constructor(context: Context) : ContextWrapper(con
}.invoke() }.invoke()
} }
return downloadFolderMapInstance!! return downloadFolderMapInstance ?: mutableMapOf()
} }

View File

@@ -55,10 +55,12 @@ fun cleanCache(context: Context) = CoroutineScope(Dispatchers.IO).launch {
while (cacheSize.invoke() > limit/2) { while (cacheSize.invoke() > limit/2) {
val caches = cacheFolder.list() ?: return@withLock val caches = cacheFolder.list() ?: return@withLock
(histories.toList().firstOrNull { synchronized(histories) {
caches.contains(it.toString()) && !downloadManager.isDownloading(it) (histories.firstOrNull {
} ?: return@withLock).let { caches.contains(it.toString()) && !downloadManager.isDownloading(it)
Cache.delete(context, it) } ?: return@withLock).let {
Cache.delete(context, it)
}
} }
} }
} }

View File

@@ -42,11 +42,13 @@ var translations: Map<String, String> = run {
@Suppress("BlockingMethodInNonBlockingContext") @Suppress("BlockingMethodInNonBlockingContext")
fun updateTranslations() = CoroutineScope(Dispatchers.IO).launch { fun updateTranslations() = CoroutineScope(Dispatchers.IO).launch {
translations = emptyMap() translations = emptyMap()
translations = Json.decodeFromString<Map<String, String>>(client.newCall( kotlin.runCatching {
Request.Builder() translations = Json.decodeFromString<Map<String, String>>(client.newCall(
.url(contentURL + "${Preferences["tag_language", ""]}.json") Request.Builder()
.build() .url(contentURL + "${Preferences["tag_language", ""]}.json")
).execute().also { if (it.code() != 200) return@launch }.body()?.use { it.string() } ?: return@launch).filterValues { it.isNotEmpty() } .build()
).execute().also { if (it.code() != 200) return@launch }.body()?.use { it.string() } ?: return@launch).filterValues { it.isNotEmpty() }
}
} }
fun getAvailableLanguages(): List<String> { fun getAvailableLanguages(): List<String> {

View File

@@ -154,4 +154,5 @@
<string name="settings_cache_unlimited">制限なし</string> <string name="settings_cache_unlimited">制限なし</string>
<string name="settings_tag_language">タグ言語</string> <string name="settings_tag_language">タグ言語</string>
<string name="settings_tag_language_message">Githubにて翻訳に参加できます</string> <string name="settings_tag_language_message">Githubにて翻訳に参加できます</string>
<string name="settings_concurrent_download">並列ダウンロード</string>
</resources> </resources>

View File

@@ -154,4 +154,5 @@
<string name="settings_cache_unlimited">무제한</string> <string name="settings_cache_unlimited">무제한</string>
<string name="settings_tag_language">태그 언어</string> <string name="settings_tag_language">태그 언어</string>
<string name="settings_tag_language_message">Github에서 번역에 참여하세요</string> <string name="settings_tag_language_message">Github에서 번역에 참여하세요</string>
<string name="settings_concurrent_download">병렬 다운로드</string>
</resources> </resources>

View File

@@ -176,6 +176,7 @@
<string name="settings_miscellaneous_title">Miscellaneous</string> <string name="settings_miscellaneous_title">Miscellaneous</string>
<string name="settings_tag_language">Tag Language</string> <string name="settings_tag_language">Tag Language</string>
<string name="settings_concurrent_download">Concurrent Download</string>
<string name="settings_tag_language_message">Participate in translation on Github</string> <string name="settings_tag_language_message">Participate in translation on Github</string>
<string name="settings_mirror_summary">Load images from mirrors</string> <string name="settings_mirror_summary">Load images from mirrors</string>
<string name="settings_proxy_title">Proxy</string> <string name="settings_proxy_title">Proxy</string>

View File

@@ -6,7 +6,7 @@ buildscript {
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:4.0.2' classpath 'com.android.tools.build:gradle:4.1.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"

View File

@@ -15,6 +15,7 @@ org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx2048M"
org.gradle.parallel=true org.gradle.parallel=true
org.gradle.daemon=true org.gradle.daemon=true
org.gradle.configureondemand=true org.gradle.configureondemand=true
org.gradle.caching=true
kotlin.code.style=official kotlin.code.style=official
android.enableJetifier=true android.enableJetifier=true
android.useAndroidX=true android.useAndroidX=true

View File

@@ -1,6 +1,6 @@
#Thu Oct 01 20:54:37 KST 2020 #Tue Oct 13 22:37:11 KST 2020
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip