diff --git a/app/build.gradle b/app/build.gradle index 28714094..4f2955cf 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -38,7 +38,7 @@ android { minSdkVersion 16 targetSdkVersion 30 versionCode 61 - versionName "5.1.1-hotfix3" + versionName "5.1.2" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true } @@ -90,6 +90,7 @@ dependencies { implementation "androidx.constraintlayout:constraintlayout:2.0.1" implementation "androidx.gridlayout:gridlayout:1.0.0" implementation "androidx.biometric:biometric:1.0.1" + implementation "androidx.work:work-runtime-ktx:2.4.0" implementation "com.daimajia.swipelayout:library:1.2.0@aar" @@ -125,8 +126,8 @@ dependencies { implementation "ru.noties.markwon:core:3.1.0" implementation "xyz.quaver:libpupil:1.7.2" - implementation "xyz.quaver:documentfilex:0.2.15" - implementation "xyz.quaver:floatingsearchview:1.0.5" + implementation "xyz.quaver:documentfilex:0.3" + implementation "xyz.quaver:floatingsearchview:1.0.7" testImplementation "junit:junit:4.13" androidTestImplementation "androidx.test.ext:junit:1.1.2" diff --git a/app/release/output-metadata.json b/app/release/output-metadata.json index 5557886d..ad5b9e23 100644 --- a/app/release/output-metadata.json +++ b/app/release/output-metadata.json @@ -12,7 +12,7 @@ "filters": [], "properties": [], "versionCode": 61, - "versionName": "5.1.1-hotfix3", + "versionName": "5.1.2", "enabled": true, "outputFile": "app-release.apk" } diff --git a/app/src/main/java/xyz/quaver/pupil/Pupil.kt b/app/src/main/java/xyz/quaver/pupil/Pupil.kt index 8b6381ea..314dc9fb 100644 --- a/app/src/main/java/xyz/quaver/pupil/Pupil.kt +++ b/app/src/main/java/xyz/quaver/pupil/Pupil.kt @@ -112,6 +112,11 @@ class Pupil : Application() { Preferences.remove("download_folder") } + if (!Preferences["reset_secure", false]) { + Preferences["security_mode"] = false + Preferences["reset_secure"] = true + } + histories = SavedSet(File(ContextCompat.getDataDir(this), "histories.json"), 0) favorites = SavedSet(File(ContextCompat.getDataDir(this), "favorites.json"), 0) favoriteTags = SavedSet(File(ContextCompat.getDataDir(this), "favorites_tags.json"), Tag.parse("")) diff --git a/app/src/main/java/xyz/quaver/pupil/adapters/GalleryBlockAdapter.kt b/app/src/main/java/xyz/quaver/pupil/adapters/GalleryBlockAdapter.kt index c95849af..47bbe696 100644 --- a/app/src/main/java/xyz/quaver/pupil/adapters/GalleryBlockAdapter.kt +++ b/app/src/main/java/xyz/quaver/pupil/adapters/GalleryBlockAdapter.kt @@ -36,13 +36,13 @@ import com.daimajia.swipe.interfaces.SwipeAdapterInterface import com.github.piasy.biv.loader.ImageLoader import kotlinx.android.synthetic.main.item_galleryblock.view.* import kotlinx.coroutines.* +import xyz.quaver.hitomi.getGallery import xyz.quaver.hitomi.getReader import xyz.quaver.io.util.getChild import xyz.quaver.pupil.R import xyz.quaver.pupil.favoriteTags import xyz.quaver.pupil.favorites import xyz.quaver.pupil.types.Tag -import xyz.quaver.pupil.ui.view.TagChip import xyz.quaver.pupil.util.Preferences import xyz.quaver.pupil.util.downloader.Cache import xyz.quaver.pupil.util.downloader.DownloadManager @@ -57,13 +57,22 @@ class GalleryBlockAdapter(private val galleries: List) : RecyclerSwipeAdapt PREV } - var update = true + var updateAll = true var thin: Boolean = Preferences["thin"] inner class GalleryViewHolder(val view: View) : RecyclerView.ViewHolder(view) { - var updateJob: Job? = null + private var galleryID: Int = 0 - private fun updateProgress(context: Context, galleryID: Int) { + init { + CoroutineScope(Dispatchers.Main).launch { + while (updateAll) { + updateProgress(view.context) + delay(1000) + } + } + } + + private fun updateProgress(context: Context) { val cache = Cache.getInstance(context, galleryID) CoroutineScope(Dispatchers.Main).launch { @@ -116,9 +125,13 @@ class GalleryBlockAdapter(private val galleries: List) : RecyclerSwipeAdapt } fun bind(galleryID: Int) { + this.galleryID = galleryID + val cache = Cache.getInstance(view.context, galleryID) - val galleryBlock = cache.metadata.galleryBlock ?: return + val galleryBlock = runBlocking { + cache.getGalleryBlock() + } ?: return with(view) { val resources = context.resources @@ -162,21 +175,30 @@ class GalleryBlockAdapter(private val galleries: List) : RecyclerSwipeAdapt } } - if (updateJob == null) - updateJob = CoroutineScope(Dispatchers.Main).launch { - while (update) { - updateProgress(context, galleryID) - delay(1000) - } - } - galleryblock_title.text = galleryBlock.title with(galleryblock_artist) { - text = artists.joinToString(", ") { it.wordCapitalize() } + text = artists.joinToString { it.wordCapitalize() } visibility = when { artists.isNotEmpty() -> View.VISIBLE else -> View.GONE } + + CoroutineScope(Dispatchers.IO).launch { + val gallery = runCatching { + getGallery(galleryID) + }.getOrNull() + + if (gallery?.groups?.isNotEmpty() != true) + return@launch + + launch(Dispatchers.Main) { + text = context.getString( + R.string.galleryblock_artist_with_group, + artists.joinToString { it.wordCapitalize() }, + gallery.groups.joinToString { it.wordCapitalize() } + ) + } + } } with(galleryblock_series) { text = @@ -198,27 +220,32 @@ class GalleryBlockAdapter(private val galleries: List) : RecyclerSwipeAdapt } } - galleryblock_tag_group.removeAllViews() - CoroutineScope(Dispatchers.Default).launch { - galleryBlock.relatedTags.sortedBy { - val tag = Tag.parse(it) + with(galleryblock_tag_group) { + onClickListener = { + onChipClickedHandler.forEach { callback -> + callback.invoke(it) + } + } - if (favoriteTags.contains(tag)) - -1 - else - when(Tag.parse(it).area) { - "female" -> 0 - "male" -> 1 - else -> 2 - } - }.map { - TagChip(context, Tag.parse(it)).apply { - setOnClickListener { view -> - for (callback in onChipClickedHandler) - callback.invoke((view as TagChip).tag) - } + tags.clear() + tags.addAll( + galleryBlock.relatedTags.sortedBy { + val tag = Tag.parse(it) + + if (favoriteTags.contains(tag)) + -1 + else + when(Tag.parse(it).area) { + "female" -> 0 + "male" -> 1 + else -> 2 + } + }.map { + Tag.parse(it) } - }.let { launch(Dispatchers.Main) { it.forEach { galleryblock_tag_group.addView(it) } } } + ) + + refresh() } galleryblock_id.text = galleryBlock.id.toString() @@ -262,8 +289,6 @@ class GalleryBlockAdapter(private val galleries: List) : RecyclerSwipeAdapt // Make some views invisible to make it thinner if (thin) { - galleryblock_language.visibility = View.GONE - galleryblock_type.visibility = View.GONE galleryblock_tag_group.visibility = View.GONE } } @@ -358,15 +383,6 @@ class GalleryBlockAdapter(private val galleries: List) : RecyclerSwipeAdapt } } - override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) { - super.onViewDetachedFromWindow(holder) - - if (holder is GalleryViewHolder) { - holder.updateJob?.cancel() - holder.updateJob = null - } - } - override fun getItemCount() = galleries.size + (if (showNext) 1 else 0) + diff --git a/app/src/main/java/xyz/quaver/pupil/adapters/ReaderAdapter.kt b/app/src/main/java/xyz/quaver/pupil/adapters/ReaderAdapter.kt index f62199d1..ce47fb60 100644 --- a/app/src/main/java/xyz/quaver/pupil/adapters/ReaderAdapter.kt +++ b/app/src/main/java/xyz/quaver/pupil/adapters/ReaderAdapter.kt @@ -62,7 +62,14 @@ class ReaderAdapter( class ViewHolder(val view: View) : RecyclerView.ViewHolder(view) { fun clear() { - view.image.ssiv?.recycle() + view.image.mainView.let { + when (it) { + is SubsamplingScaleImageView -> + it.recycle() + is SimpleDraweeView -> + it.controller = null + } + } } } diff --git a/app/src/main/java/xyz/quaver/pupil/services/DownloadService.kt b/app/src/main/java/xyz/quaver/pupil/services/DownloadService.kt index 1fcacd4f..f6bc889f 100644 --- a/app/src/main/java/xyz/quaver/pupil/services/DownloadService.kt +++ b/app/src/main/java/xyz/quaver/pupil/services/DownloadService.kt @@ -42,6 +42,7 @@ import xyz.quaver.pupil.R import xyz.quaver.pupil.client import xyz.quaver.pupil.interceptors import xyz.quaver.pupil.ui.ReaderActivity +import xyz.quaver.pupil.util.cleanCache import xyz.quaver.pupil.util.downloader.Cache import xyz.quaver.pupil.util.downloader.DownloadManager import xyz.quaver.pupil.util.ellipsize @@ -295,6 +296,8 @@ class DownloadService : Service() { } fun download(galleryID: Int, priority: Boolean = false, startId: Int? = null): Job = CoroutineScope(Dispatchers.IO).launch { + cleanCache(this@DownloadService) + if (progress.containsKey(galleryID)) cancel(galleryID) diff --git a/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt b/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt index cb586e3c..3b34fd3d 100644 --- a/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt +++ b/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt @@ -23,6 +23,7 @@ import android.content.Intent import android.net.Uri import android.os.Bundle import android.text.InputType +import android.text.util.Linkify import android.view.KeyEvent import android.view.MenuItem import android.view.MotionEvent @@ -31,6 +32,7 @@ import android.widget.* import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatDelegate import androidx.cardview.widget.CardView +import androidx.core.text.util.LinkifyCompat import androidx.core.view.GravityCompat import com.google.android.material.appbar.AppBarLayout import com.google.android.material.navigation.NavigationView @@ -58,6 +60,7 @@ import xyz.quaver.pupil.util.checkUpdate import xyz.quaver.pupil.util.downloader.Cache import xyz.quaver.pupil.util.downloader.DownloadManager import xyz.quaver.pupil.util.restore +import java.util.regex.Pattern import kotlin.math.abs import kotlin.math.ceil import kotlin.math.min @@ -122,8 +125,6 @@ class MainActivity : checkUpdate(this) - - initView() } @@ -146,7 +147,7 @@ class MainActivity : override fun onDestroy() { super.onDestroy() - (main_recyclerview?.adapter as? GalleryBlockAdapter)?.update = false + (main_recyclerview?.adapter as? GalleryBlockAdapter)?.updateAll = false } override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { @@ -204,6 +205,8 @@ class MainActivity : } ) + Linkify.addLinks(main_noresult, Pattern.compile(getString(R.string.https_text)), null, null, { _, _ -> getString(R.string.https) }) + //NavigationView main_nav_view.setNavigationItemSelectedListener(this) @@ -284,12 +287,22 @@ class MainActivity : setTitle(R.string.main_open_gallery_by_id) setPositiveButton(android.R.string.ok) { _, _ -> - val galleryID = editText.text.toString().toIntOrNull() ?: return@setPositiveButton - val intent = Intent(this@MainActivity, ReaderActivity::class.java).apply { - putExtra("galleryID", galleryID) - } + val galleryID = editText.text.toString().toIntOrNull() ?: return@setPositiveButton + + GalleryDialog(this@MainActivity, galleryID).apply { + onChipClickedHandler.add { + runOnUiThread { + query = it.toQuery() + currentPage = 0 - startActivity(intent) + cancelFetch() + clearGalleries() + fetchGalleries(query, sortMode) + loadBlocks() + } + dismiss() + } + }.show() } }.show() } diff --git a/app/src/main/java/xyz/quaver/pupil/ui/dialog/GalleryDialog.kt b/app/src/main/java/xyz/quaver/pupil/ui/dialog/GalleryDialog.kt index d9417caa..8c869a36 100644 --- a/app/src/main/java/xyz/quaver/pupil/ui/dialog/GalleryDialog.kt +++ b/app/src/main/java/xyz/quaver/pupil/ui/dialog/GalleryDialog.kt @@ -42,7 +42,6 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import xyz.quaver.hitomi.Gallery import xyz.quaver.hitomi.getGallery -import xyz.quaver.pupil.BuildConfig import xyz.quaver.pupil.R import xyz.quaver.pupil.adapters.GalleryBlockAdapter import xyz.quaver.pupil.adapters.ThumbnailPageAdapter @@ -54,6 +53,8 @@ import xyz.quaver.pupil.ui.view.TagChip import xyz.quaver.pupil.util.ItemClickSupport import xyz.quaver.pupil.util.downloader.Cache import xyz.quaver.pupil.util.wordCapitalize +import java.util.* +import kotlin.collections.ArrayList class GalleryDialog(context: Context, private val galleryID: Int) : AlertDialog(context) { @@ -113,7 +114,12 @@ class GalleryDialog(context: Context, private val galleryID: Int) : AlertDialog( addRelated(gallery) } } catch (e: Exception) { - Snackbar.make(gallery_layout, R.string.unable_to_connect, Snackbar.LENGTH_INDEFINITE).show() + Snackbar.make(gallery_layout, R.string.unable_to_connect, Snackbar.LENGTH_INDEFINITE).apply { + if (Locale.getDefault().language == "ko") + setAction(context.getText(R.string.https_text)) { + context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(context.getString(R.string.https)))) + } + }.show() } } } diff --git a/app/src/main/java/xyz/quaver/pupil/ui/fragment/ManageStorageFragment.kt b/app/src/main/java/xyz/quaver/pupil/ui/fragment/ManageStorageFragment.kt index 9afdb6eb..628a7f9b 100644 --- a/app/src/main/java/xyz/quaver/pupil/ui/fragment/ManageStorageFragment.kt +++ b/app/src/main/java/xyz/quaver/pupil/ui/fragment/ManageStorageFragment.kt @@ -31,6 +31,7 @@ import xyz.quaver.io.util.deleteRecursively import xyz.quaver.pupil.R import xyz.quaver.pupil.histories import xyz.quaver.pupil.util.byteToString +import xyz.quaver.pupil.util.downloader.Cache import xyz.quaver.pupil.util.downloader.DownloadManager import java.io.File @@ -61,6 +62,8 @@ class ManageStorageFragment : PreferenceFragmentCompat(), Preference.OnPreferenc if (dir.exists()) dir.deleteRecursively() + Cache.instances.clear() + summary = context.getString(R.string.settings_storage_usage, byteToString(0)) CoroutineScope(Dispatchers.IO).launch { var size = 0L diff --git a/app/src/main/java/xyz/quaver/pupil/ui/view/TagChipGroup.kt b/app/src/main/java/xyz/quaver/pupil/ui/view/TagChipGroup.kt new file mode 100644 index 00000000..7e76dd26 --- /dev/null +++ b/app/src/main/java/xyz/quaver/pupil/ui/view/TagChipGroup.kt @@ -0,0 +1,90 @@ +/* + * Pupil, Hitomi.la viewer for Android + * Copyright (C) 2020 tom5079 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package xyz.quaver.pupil.ui.view + +import android.content.Context +import android.content.res.TypedArray +import android.util.AttributeSet +import com.google.android.material.chip.Chip +import com.google.android.material.chip.ChipGroup +import xyz.quaver.pupil.R +import xyz.quaver.pupil.types.Tag +import xyz.quaver.pupil.types.Tags + +class TagChipGroup @JvmOverloads constructor(context: Context, attr: AttributeSet? = null, attrStyle: Int = R.attr.chipGroupStyle, val tags: Tags = Tags()) : ChipGroup(context, attr, attrStyle), MutableSet by tags { + + object Defaults { + val maxChipSize = 10 + } + + var maxChipSize: Int = Defaults.maxChipSize + set(value) { + field = value + + refresh() + } + + private val moreView = Chip(context).apply { + text = "…" + + setEnsureMinTouchTargetSize(false) + + setOnClickListener { + removeView(this) + + for (i in maxChipSize until tags.size) { + val tag = tags.elementAt(i) + + addView(TagChip(context, tag).apply { + setOnClickListener { + onClickListener?.invoke(tag) + } + }) + } + } + } + + var onClickListener: ((Tag) -> Unit)? = null + + private fun applyAttributes(attr: TypedArray) { + maxChipSize = attr.getInt(R.styleable.TagChipGroup_maxTag, Defaults.maxChipSize) + } + + fun refresh() { + this.removeAllViews() + + tags.take(maxChipSize).forEach { + this.addView(TagChip(context, it).apply { + setOnClickListener { + onClickListener?.invoke(this.tag) + } + }) + } + + if (maxChipSize > 0 && this.size > maxChipSize) + addView(moreView) + } + + init { + applyAttributes(context.obtainStyledAttributes(attr, R.styleable.TagChipGroup)) + + refresh() + } + +} \ No newline at end of file diff --git a/app/src/main/java/xyz/quaver/pupil/util/downloader/Cache.kt b/app/src/main/java/xyz/quaver/pupil/util/downloader/Cache.kt index f2e4cc70..5c4aa5f1 100644 --- a/app/src/main/java/xyz/quaver/pupil/util/downloader/Cache.kt +++ b/app/src/main/java/xyz/quaver/pupil/util/downloader/Cache.kt @@ -186,13 +186,14 @@ class Cache private constructor(context: Context, val galleryID: Int) : ContextW } fun getImage(index: Int): FileX? = - metadata.imageList?.get(index)?.let { findFile(it) } + metadata.imageList?.getOrNull(index)?.let { findFile(it) } @Suppress("BlockingMethodInNonBlockingContext") fun putImage(index: Int, fileName: String, data: ByteArray) { val file = cacheFolder.getChild(fileName) - file.createNewFile() + if (!file.exists()) + file.createNewFile() file.writeBytes(data) setMetadata { metadata -> metadata.imageList!![index] = fileName } } diff --git a/app/src/main/java/xyz/quaver/pupil/util/file.kt b/app/src/main/java/xyz/quaver/pupil/util/file.kt index 7579f986..2df6e90e 100644 --- a/app/src/main/java/xyz/quaver/pupil/util/file.kt +++ b/app/src/main/java/xyz/quaver/pupil/util/file.kt @@ -19,35 +19,63 @@ package xyz.quaver.pupil.util import android.content.Context -import android.os.storage.StorageManager -import androidx.core.content.ContextCompat -import androidx.core.net.toUri +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock +import xyz.quaver.pupil.histories +import xyz.quaver.pupil.util.downloader.Cache +import xyz.quaver.pupil.util.downloader.DownloadManager import java.io.File -import java.io.FileOutputStream -import java.lang.reflect.Array -import java.net.URL - -@Suppress("DEPRECATION") -@Deprecated("Use downloader.Cache instead") -fun getCachedGallery(context: Context, galleryID: Int) = - File(getDownloadDirectory(context), galleryID.toString()).let { - if (it.exists()) - it - else - File(context.cacheDir, "imageCache/$galleryID") - } -@Suppress("DEPRECATION") -@Deprecated("Use downloader.Cache instead") -fun getDownloadDirectory(context: Context) = - Preferences.get("dl_location").let { - if (it.isNotEmpty() && !it.startsWith("content")) - File(it) - else - context.getExternalFilesDir(null)!! - } +val mutex = Mutex() +fun cleanCache(context: Context) = CoroutineScope(Dispatchers.IO).launch { + if (mutex.isLocked) return@launch + + mutex.withLock { + val cacheFolder = File(context.cacheDir, "imageCache") + val downloadManager = DownloadManager.getInstance(context) + + cacheFolder.listFiles { file -> + val galleryID = file.name.toIntOrNull() ?: return@listFiles true + + !(downloadManager.downloadFolderMap.containsKey(galleryID) || histories.contains(galleryID)) + }?.forEach { + it.deleteRecursively() + } + + DownloadManager.getInstance(context).downloadFolderMap.keys.forEach { + val folder = File(cacheFolder, it.toString()) + + if (!downloadManager.isDownloading(it) && folder.exists()) { + folder.deleteRecursively() + } + } -@Suppress("DEPRECATION") -@Deprecated("Use FileX instead") -fun File.isParentOf(another: File) = - another.absolutePath.startsWith(this.absolutePath) \ No newline at end of file + val limit = (Preferences.get("cache_limit").toLongOrNull() ?: 0L)*1024*1024*1024 + + if (limit == 0L) return@withLock + + val cacheSize = { + var size = 0L + + cacheFolder.walk().forEach { + size += it.length() + } + + size + } + + if (cacheSize.invoke() > limit) + while (cacheSize.invoke() > limit/2) { + val caches = cacheFolder.list() ?: return@withLock + + (histories.firstOrNull { + caches.contains(it.toString()) && !downloadManager.isDownloading(it) + } ?: return@withLock).let { + Cache.delete(it) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main_content.xml b/app/src/main/res/layout/activity_main_content.xml index 201e31c7..cbe12f09 100644 --- a/app/src/main/res/layout/activity_main_content.xml +++ b/app/src/main/res/layout/activity_main_content.xml @@ -47,22 +47,6 @@ - - - - + + + + + app:layout_constraintBottom_toTopOf="@id/barrier"/> - - - @@ -188,7 +183,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" app:barrierDirection="bottom" - app:constraint_referenced_ids="galleryblock_tag_group"/> + app:constraint_referenced_ids="galleryblock_thumbnail, galleryblock_tag_group"/> カメラ権限が拒否されているため、まばたき検知使用できません この機器には前面カメラが装着されていません エラー + キャッシュサイズ制限 + 制限なし \ No newline at end of file diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 2331da30..58979aec 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -15,7 +15,7 @@ 업데이트 다운로드중… 업데이트가 있습니다! 경고 - 결과 없음 + 결과 없음\n해결법 기타 기록 삭제 기록을 삭제하시겠습니까? @@ -150,4 +150,6 @@ 카메라 권한이 거부되었기 때문에 눈 깜빡임 감지가 불가능합니다 이 장치에는 전면 카메라가 없습니다 오류 + 캐시 크기 제한 + 무제한 \ No newline at end of file diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 8e9b419a..69abcd7e 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -58,4 +58,24 @@ SOCKS + + 0 + 1 + 2 + 4 + 8 + 16 + 32 + + + + @string/settings_cache_unlimited + 1G + 2G + 4G + 8G + 16G + 32G + + \ No newline at end of file diff --git a/app/src/main/res/values/attr.xml b/app/src/main/res/values/attr.xml new file mode 100644 index 00000000..d13a3706 --- /dev/null +++ b/app/src/main/res/values/attr.xml @@ -0,0 +1,24 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f3dbedae..53d185b4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -9,6 +9,10 @@ mailto:pupil.hentai@gmail.com https://discord.gg/Stj4b5v + + 해결법 + https://bit.ly/34dUBwy + http://ix.io/ Settings @@ -17,6 +21,8 @@ Content ImageView -/- + %s (%s) + Warning @@ -155,6 +161,9 @@ %s available Custom Location This folder is not writable. Please select another folder. + Cache Limit + Unlimited + Hide image from gallery Low quality images Load low quality images to improve load speed and data usage @@ -173,7 +182,6 @@ Enable security mode to make the screen invisible on recent app window Dark mode Protect yourself against light attacks! - Hide image from gallery Import old galleries User ID User ID is copied to clipboard diff --git a/app/src/main/res/xml/root_preferences.xml b/app/src/main/res/xml/root_preferences.xml index 7a5e9cba..ff67535d 100644 --- a/app/src/main/res/xml/root_preferences.xml +++ b/app/src/main/res/xml/root_preferences.xml @@ -44,6 +44,14 @@ app:key="download_folder" app:title="@string/settings_download_folder"/> + + diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index f6b961fd..f3d88b1c 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 29e5e6d4..e7a75faf 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,4 +1,4 @@ -#Thu Jun 18 15:48:09 KST 2020 +#Thu Oct 01 20:54:37 KST 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index cccdd3d5..2fe81a7d 100644 --- a/gradlew +++ b/gradlew @@ -1,5 +1,21 @@ #!/usr/bin/env sh +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + ############################################################################## ## ## Gradle start up script for UN*X @@ -28,7 +44,7 @@ APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" @@ -109,8 +125,8 @@ if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` JAVACMD=`cygpath --unix "$JAVACMD"` @@ -138,19 +154,19 @@ if $cygwin ; then else eval `echo args$i`="\"$arg\"" fi - i=$((i+1)) + i=`expr $i + 1` done case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi @@ -159,14 +175,9 @@ save () { for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done echo " " } -APP_ARGS=$(save "$@") +APP_ARGS=`save "$@"` # Collect all arguments for the java command, following the shell quoting and substitution rules eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index f9553162..9618d8d9 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -14,7 +30,7 @@ set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome