Implemented new favorite backup/restore feature
This commit is contained in:
@@ -62,7 +62,7 @@ dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-core:1.0.0-RC"
|
||||
//implementation "org.jetbrains.kotlinx:kotlinx-serialization-core:1.0.0-RC"
|
||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
|
||||
implementation 'androidx.preference:preference:1.1.1'
|
||||
@@ -92,7 +92,9 @@ dependencies {
|
||||
implementation 'com.andrognito.patternlockview:patternlockview:1.0.0'
|
||||
//implementation 'com.andrognito.pinlockview:pinlockview:2.1.0'
|
||||
implementation "ru.noties.markwon:core:3.1.0"
|
||||
implementation 'xyz.quaver:libpupil:1.0'
|
||||
implementation ("xyz.quaver:libpupil:1.0") {
|
||||
exclude group: 'org.jetbrains.kotlinx', module: 'kotlinx-serialization-core-jvm'
|
||||
}
|
||||
testImplementation 'junit:junit:4.13'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||
androidTestImplementation 'androidx.test:rules:1.3.0'
|
||||
|
||||
BIN
app/libs/kotlinx-serialization-core-jvm-1.0.0-RC.jar
Normal file
BIN
app/libs/kotlinx-serialization-core-jvm-1.0.0-RC.jar
Normal file
Binary file not shown.
7
app/proguard-rules.pro
vendored
7
app/proguard-rules.pro
vendored
@@ -40,9 +40,10 @@
|
||||
-keepattributes *Annotation*, InnerClasses
|
||||
-dontnote kotlinx.serialization.SerializationKt
|
||||
-keep,includedescriptorclasses class xyz.quaver.**$$serializer { *; } # <-- change package name to your app's
|
||||
-keepclassmembers class xyz.quaver.pupil** { # <-- change package name to your app's
|
||||
-keepclassmembers class xyz.quaver.pupil.** { # <-- change package name to your app's
|
||||
*** Companion;
|
||||
}
|
||||
-keepclasseswithmembers class xyz.quaver.pupil** { # <-- change package name to your app's
|
||||
-keepclasseswithmembers class xyz.quaver.pupil.** { # <-- change package name to your app's
|
||||
kotlinx.serialization.KSerializer serializer(...);
|
||||
}
|
||||
}
|
||||
-keep class xyz.quaver.pupil.ui.fragment.ManageFavoritesFragment
|
||||
@@ -6,9 +6,9 @@
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
|
||||
|
||||
<application
|
||||
@@ -20,6 +20,7 @@
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
tools:replace="android:theme"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
tools:ignore="UnusedAttribute">
|
||||
@@ -36,9 +37,11 @@
|
||||
|
||||
</provider>
|
||||
|
||||
<receiver android:name=".BroadcastReciever" android:exported="true">
|
||||
<receiver
|
||||
android:name=".BroadcastReciever"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.DOWNLOAD_COMPLETE"/>
|
||||
<action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
@@ -204,7 +207,9 @@
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".ui.SettingsActivity"
|
||||
android:label="@string/settings_title" />
|
||||
android:label="@string/settings_title">
|
||||
<tools:validation testUrl="http://ix.io/eer" />
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".ui.MainActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
||||
@@ -215,6 +220,17 @@
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data
|
||||
android:scheme="http"
|
||||
android:host="ix.io"
|
||||
android:pathPattern="/..*" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="net.rdrei.android.dirchooser.DirectoryChooserActivity" />
|
||||
</application>
|
||||
|
||||
@@ -83,6 +83,10 @@ class Pupil : MultiDexApplication() {
|
||||
histories.clear()
|
||||
histories.addAll(it)
|
||||
}
|
||||
favorites.reversed().let {
|
||||
favorites.clear()
|
||||
favorites.addAll(it)
|
||||
}
|
||||
}
|
||||
preference.edit().putBoolean("old_history", false).apply()
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ data class Tag(val area: String?, val tag: String, val isNegative: Boolean = fal
|
||||
}
|
||||
}
|
||||
|
||||
class Tags(tag: List<Tag?>?) : ArrayList<Tag>() {
|
||||
class Tags(val tags: MutableSet<Tag> = mutableSetOf()) : MutableSet<Tag> by tags {
|
||||
|
||||
companion object {
|
||||
fun parse(tags: String) : Tags {
|
||||
@@ -77,20 +77,13 @@ class Tags(tag: List<Tag?>?) : ArrayList<Tag>() {
|
||||
Tag.parse(it)
|
||||
else
|
||||
null
|
||||
}
|
||||
}.filterNotNull().toMutableSet()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
tag?.forEach {
|
||||
if (it != null)
|
||||
add(it)
|
||||
}
|
||||
}
|
||||
|
||||
fun contains(element: String): Boolean {
|
||||
forEach {
|
||||
tags.forEach {
|
||||
if (it.toString() == element)
|
||||
return true
|
||||
}
|
||||
@@ -99,23 +92,25 @@ class Tags(tag: List<Tag?>?) : ArrayList<Tag>() {
|
||||
}
|
||||
|
||||
fun add(element: String): Boolean {
|
||||
return super.add(Tag.parse(element))
|
||||
return tags.add(Tag.parse(element))
|
||||
}
|
||||
|
||||
fun remove(element: String) {
|
||||
filter { it.toString() == element }.forEach {
|
||||
remove(it)
|
||||
tags.filter { it.toString() == element }.forEach {
|
||||
tags.remove(it)
|
||||
}
|
||||
}
|
||||
|
||||
fun removeByArea(area: String, isNegative: Boolean? = null) {
|
||||
filter { it.area == area && (if(isNegative == null) true else (it.isNegative == isNegative)) }.forEach {
|
||||
remove(it)
|
||||
tags.filter { it.area == area && (if(isNegative == null) true else (it.isNegative == isNegative)) }.forEach {
|
||||
tags.remove(it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return joinToString(" ") { it.toString() }
|
||||
return tags.joinToString(" ") { it.toString() }
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -62,7 +62,6 @@ import xyz.quaver.hitomi.getSuggestionsForQuery
|
||||
import xyz.quaver.pupil.Pupil
|
||||
import xyz.quaver.pupil.R
|
||||
import xyz.quaver.pupil.adapters.GalleryBlockAdapter
|
||||
import xyz.quaver.pupil.types.Tag
|
||||
import xyz.quaver.pupil.types.TagSuggestion
|
||||
import xyz.quaver.pupil.types.Tags
|
||||
import xyz.quaver.pupil.ui.dialog.GalleryDialog
|
||||
@@ -153,6 +152,18 @@ class MainActivity : AppCompatActivity() {
|
||||
this@MainActivity.favorites = favorites
|
||||
}
|
||||
|
||||
if (intent.action == Intent.ACTION_VIEW) {
|
||||
intent.dataString?.let { url ->
|
||||
restore(favorites, url,
|
||||
onFailure = {
|
||||
Snackbar.make(this.main_recyclerview, R.string.settings_backup_failed, Snackbar.LENGTH_LONG).show()
|
||||
}, onSuccess = {
|
||||
Snackbar.make(this.main_recyclerview, getString(R.string.settings_restore_success, it.size), Snackbar.LENGTH_LONG).show()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
setContentView(R.layout.activity_main)
|
||||
|
||||
checkUpdate(this)
|
||||
@@ -771,7 +782,7 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
if (!favoritesFile.exists()) {
|
||||
favoritesFile.createNewFile()
|
||||
favoritesFile.writeText(Json.encodeToString(Tags(listOf())))
|
||||
favoritesFile.writeText(Json.encodeToString(Tags()))
|
||||
}
|
||||
|
||||
setOnLeftMenuClickListener(object: FloatingSearchView.OnLeftMenuClickListener {
|
||||
@@ -833,7 +844,7 @@ class MainActivity : AppCompatActivity() {
|
||||
clearSuggestions()
|
||||
|
||||
if (query.isEmpty() or query.endsWith(' ')) {
|
||||
swapSuggestions(Json.decodeFromString<Tags>(favoritesFile.readText()).map {
|
||||
swapSuggestions(Tags(Json.decodeFromString(favoritesFile.readText())).map {
|
||||
TagSuggestion(it.tag, -1, "", it.area ?: "tag")
|
||||
})
|
||||
|
||||
@@ -911,7 +922,7 @@ class MainActivity : AppCompatActivity() {
|
||||
favorites.add(tag)
|
||||
}
|
||||
|
||||
favoritesFile.writeText(Json.encodeToString(favorites))
|
||||
favoritesFile.writeText(Json.encodeToString(favorites.tags))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -951,7 +962,7 @@ class MainActivity : AppCompatActivity() {
|
||||
setOnFocusChangeListener(object: FloatingSearchView.OnFocusChangeListener {
|
||||
override fun onFocus() {
|
||||
if (query.isEmpty() or query.endsWith(' '))
|
||||
swapSuggestions(Tags(Json.decodeFromString<List<Tag>>(favoritesFile.readText())).map {
|
||||
swapSuggestions(Tags(Json.decodeFromString(favoritesFile.readText())).map {
|
||||
TagSuggestion(it.tag, -1, "", it.area ?: "tag")
|
||||
})
|
||||
}
|
||||
@@ -1076,7 +1087,7 @@ class MainActivity : AppCompatActivity() {
|
||||
}
|
||||
Mode.FAVORITE -> {
|
||||
when {
|
||||
query.isEmpty() -> favorites.toList().also {
|
||||
query.isEmpty() -> favorites.reversed().also {
|
||||
totalItems = it.size
|
||||
}
|
||||
else -> {
|
||||
|
||||
@@ -80,7 +80,7 @@ class SettingsActivity : AppCompatActivity() {
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
when(requestCode) {
|
||||
R.id.request_lock -> {
|
||||
R.id.request_lock.normalizeID() -> {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
supportFragmentManager
|
||||
.beginTransaction()
|
||||
@@ -89,7 +89,7 @@ class SettingsActivity : AppCompatActivity() {
|
||||
.commitAllowingStateLoss()
|
||||
}
|
||||
}
|
||||
R.id.request_restore -> {
|
||||
R.id.request_restore.normalizeID() -> {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
val uri = data?.data ?: return
|
||||
|
||||
@@ -103,7 +103,7 @@ class SettingsActivity : AppCompatActivity() {
|
||||
(application as Pupil).favorites.addAll(Json.decodeFromString<List<Int>>(str).also {
|
||||
Snackbar.make(
|
||||
window.decorView,
|
||||
getString(R.string.settings_restore_successful, it.size),
|
||||
getString(R.string.settings_restore_success, it.size),
|
||||
Snackbar.LENGTH_LONG
|
||||
).show()
|
||||
})
|
||||
@@ -116,7 +116,7 @@ class SettingsActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
}
|
||||
R.id.request_download_folder -> {
|
||||
R.id.request_download_folder.normalizeID() -> {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
data?.data?.also { uri ->
|
||||
val takeFlags: Int =
|
||||
@@ -140,7 +140,7 @@ class SettingsActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
}
|
||||
R.id.request_download_folder_old -> {
|
||||
R.id.request_download_folder_old.normalizeID() -> {
|
||||
if (resultCode == DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED) {
|
||||
val directory = data?.getStringExtra(DirectoryChooserActivity.RESULT_SELECTED_DIR)!!
|
||||
|
||||
@@ -163,7 +163,7 @@ class SettingsActivity : AppCompatActivity() {
|
||||
@SuppressLint("InlinedApi")
|
||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
||||
when (requestCode) {
|
||||
R.id.request_write_permission_and_saf -> {
|
||||
R.id.request_write_permission_and_saf.normalizeID() -> {
|
||||
if (grantResults.firstOrNull() == PackageManager.PERMISSION_GRANTED) {
|
||||
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply {
|
||||
putExtra("android.content.extra.SHOW_ADVANCED", true)
|
||||
|
||||
@@ -31,8 +31,7 @@ import xyz.quaver.pupil.ui.LockActivity
|
||||
import xyz.quaver.pupil.util.Lock
|
||||
import xyz.quaver.pupil.util.LockManager
|
||||
|
||||
class LockSettingsFragment :
|
||||
PreferenceFragmentCompat() {
|
||||
class LockSettingsFragment : PreferenceFragmentCompat() {
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package xyz.quaver.pupil.ui.fragment
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.widget.EditText
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import okhttp3.*
|
||||
import xyz.quaver.pupil.Pupil
|
||||
import xyz.quaver.pupil.R
|
||||
import xyz.quaver.pupil.util.restore
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
||||
class ManageFavoritesFragment : PreferenceFragmentCompat() {
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
setPreferencesFromResource(R.xml.manage_favorites_preferences, rootKey)
|
||||
|
||||
initPreferences()
|
||||
}
|
||||
|
||||
private fun initPreferences() {
|
||||
findPreference<Preference>("backup")?.setOnPreferenceClickListener {
|
||||
val request = Request.Builder()
|
||||
.url(getString(R.string.backup_url))
|
||||
.post(
|
||||
FormBody.Builder()
|
||||
.add("f:1", File(ContextCompat.getDataDir(requireContext()), "favorites.json").readText())
|
||||
.build()
|
||||
).build()
|
||||
|
||||
OkHttpClient().newCall(request).enqueue(object: Callback {
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
val view = view ?: return
|
||||
Snackbar.make(view, R.string.settings_backup_failed, Snackbar.LENGTH_LONG).show()
|
||||
}
|
||||
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
Intent(Intent.ACTION_SEND).apply {
|
||||
type = "text/plain"
|
||||
putExtra(Intent.EXTRA_TEXT, response.body()?.use { it.string() }?.replace("\n", ""))
|
||||
}.let {
|
||||
context?.startActivity(Intent.createChooser(it, getString(R.string.settings_backup_share)))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
true
|
||||
}
|
||||
findPreference<Preference>("restore")?.setOnPreferenceClickListener {
|
||||
val editText = EditText(requireContext()).apply {
|
||||
setText(getString(R.string.backup_url), TextView.BufferType.EDITABLE)
|
||||
}
|
||||
|
||||
AlertDialog.Builder(requireContext())
|
||||
.setTitle(R.string.settings_restore_title)
|
||||
.setView(editText)
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
val favorites = (activity?.application as? Pupil)?.favorites ?: return@setPositiveButton
|
||||
restore(favorites, editText.text.toString(),
|
||||
onFailure = onFailure@{
|
||||
val view = view ?: return@onFailure
|
||||
Snackbar.make(view, R.string.settings_restore_failed, Snackbar.LENGTH_LONG).show()
|
||||
}, onSuccess = onSuccess@{
|
||||
val view = view ?: return@onSuccess
|
||||
Snackbar.make(view, getString(R.string.settings_restore_success, it.size), Snackbar.LENGTH_LONG).show()
|
||||
})
|
||||
}.setNegativeButton(android.R.string.cancel) { _, _ ->
|
||||
// Do Nothing
|
||||
}.show()
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -181,23 +181,6 @@ class SettingsFragment :
|
||||
"nomedia" -> {
|
||||
File(getDownloadDirectory(context), ".nomedia").createNewFile()
|
||||
}
|
||||
"backup" -> {
|
||||
File(ContextCompat.getDataDir(requireContext()), "favorites.json").copyTo(
|
||||
File(getDownloadDirectory(requireContext()), "favorites.json"),
|
||||
true
|
||||
)
|
||||
|
||||
Snackbar.make(this@SettingsFragment.listView, R.string.settings_backup_snackbar, Snackbar.LENGTH_LONG)
|
||||
.show()
|
||||
}
|
||||
"restore" -> {
|
||||
val intent = Intent(Intent.ACTION_GET_CONTENT).apply {
|
||||
addCategory(Intent.CATEGORY_OPENABLE)
|
||||
type = "*/*"
|
||||
}
|
||||
|
||||
activity?.startActivityForResult(intent, R.id.request_restore.normalizeID())
|
||||
}
|
||||
"user_id" -> {
|
||||
(context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager).setPrimaryClip(
|
||||
ClipData.newPlainText("user_id", sharedPreference.getString("user_id", ""))
|
||||
@@ -349,10 +332,7 @@ class SettingsFragment :
|
||||
"nomedia" -> {
|
||||
onPreferenceClickListener = this@SettingsFragment
|
||||
}
|
||||
"backup" -> {
|
||||
onPreferenceClickListener = this@SettingsFragment
|
||||
}
|
||||
"restore" -> {
|
||||
"old_import_galleries" -> {
|
||||
onPreferenceClickListener = this@SettingsFragment
|
||||
}
|
||||
"user_id" -> {
|
||||
|
||||
@@ -26,14 +26,15 @@ import java.io.File
|
||||
class GalleryList(private val file: File, private val list: MutableSet<Int> = mutableSetOf()) : MutableSet<Int> by list {
|
||||
|
||||
init {
|
||||
if (!file.exists()) {
|
||||
file.parentFile?.mkdirs()
|
||||
save()
|
||||
}
|
||||
load()
|
||||
}
|
||||
|
||||
fun load() {
|
||||
synchronized(this) {
|
||||
if (!file.exists())
|
||||
file.parentFile?.mkdirs()
|
||||
|
||||
list.clear()
|
||||
list.addAll(
|
||||
Json.decodeFromString<List<Int>>(file.bufferedReader().use { it.readText() })
|
||||
|
||||
@@ -18,42 +18,32 @@
|
||||
|
||||
package xyz.quaver.pupil.util
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.DownloadManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.util.Base64
|
||||
import android.webkit.URLUtil
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.preference.PreferenceManager
|
||||
import kotlinx.coroutines.*
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import kotlinx.android.synthetic.main.activity_main_content.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.*
|
||||
import okhttp3.*
|
||||
import ru.noties.markwon.Markwon
|
||||
import xyz.quaver.hitomi.GalleryBlock
|
||||
import xyz.quaver.hitomi.Reader
|
||||
import xyz.quaver.hitomi.getGalleryBlock
|
||||
import xyz.quaver.hitomi.getReader
|
||||
import xyz.quaver.proxy
|
||||
import xyz.quaver.pupil.BroadcastReciever
|
||||
import xyz.quaver.pupil.BuildConfig
|
||||
import xyz.quaver.pupil.R
|
||||
import xyz.quaver.pupil.util.download.Cache
|
||||
import xyz.quaver.pupil.util.download.Metadata
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.net.URL
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
fun getReleases(url: String) : JsonArray {
|
||||
return try {
|
||||
URL(url).readText().let {
|
||||
Json.decodeFromString(it)
|
||||
Json.parseToJsonElement(it).jsonArray
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
JsonArray(emptyList())
|
||||
@@ -184,4 +174,29 @@ fun checkUpdate(context: Context, force: Boolean = false) {
|
||||
dialog.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun restore(favorites: GalleryList, url: String, onFailure: ((Exception) -> Unit)? = null, onSuccess: ((List<Int>) -> Unit)? = null) {
|
||||
if (!URLUtil.isValidUrl(url)) {
|
||||
onFailure?.invoke(IllegalArgumentException())
|
||||
return
|
||||
}
|
||||
|
||||
val request = Request.Builder()
|
||||
.url(url)
|
||||
.get()
|
||||
.build()
|
||||
|
||||
OkHttpClient().newCall(request).enqueue(object: Callback {
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
onFailure?.invoke(e)
|
||||
}
|
||||
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
Json.decodeFromString<List<Int>>(response.body().use { it?.string() } ?: "[]").let {
|
||||
favorites.addAll(it)
|
||||
onSuccess?.invoke(it)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -54,7 +54,7 @@
|
||||
<string name="settings_clear_downloads">ダウンロード削除</string>
|
||||
<string name="settings_clear_downloads_alert_message">ダウンロードしたギャラリーを全て削除します。\n実行しますか?</string>
|
||||
<string name="settings_mirror_summary">ミラーサーバからイメージをロード</string>
|
||||
<string name="main_drawer_favorite">お気に入り</string>
|
||||
<string name="main_drawer_favorite">ブックマーク</string>
|
||||
<string name="main_open_gallery_by_id">ギャラリー番号で見る</string>
|
||||
<string name="reader_failed_to_find_gallery">エラーが発生しました</string>
|
||||
<string name="settings_storage">ストレージ</string>
|
||||
@@ -91,11 +91,11 @@
|
||||
<string name="settings_nomedia_title">イメージを隠す</string>
|
||||
<string name="main_delete">削除</string>
|
||||
<string name="main_download">ダウンロード</string>
|
||||
<string name="settings_backup_title">お気に入りバックアップ</string>
|
||||
<string name="settings_restore_title">お気に入り復元</string>
|
||||
<string name="settings_backup_snackbar">バックアップファイルを作成しました</string>
|
||||
<string name="settings_backup_title">ブックマークバックアップ</string>
|
||||
<string name="settings_restore_title">ブックマーク復元</string>
|
||||
<string name="settings_backup_file_created">バックアップファイルを作成しました</string>
|
||||
<string name="settings_restore_failed">復元に失敗しました</string>
|
||||
<string name="settings_restore_successful">%1$d項目を復元しました</string>
|
||||
<string name="settings_restore_success">%1$d項目を復元しました</string>
|
||||
<string name="settings_dl_location">ダウンロード場所</string>
|
||||
<string name="settings_dl_location_internal">内部ストレージ</string>
|
||||
<string name="settings_dl_location_removable">外部SDカード</string>
|
||||
@@ -137,4 +137,7 @@
|
||||
<string name="reader_fab_auto">自動スクロール</string>
|
||||
<string name="search_all">全てのギャラリーを対象に検索</string>
|
||||
<string name="settings_rtl">綴じ方向を左にする</string>
|
||||
<string name="settings_manage_favorites">ブックマーク管理</string>
|
||||
<string name="settings_backup_failed">エラーが発生しました</string>
|
||||
<string name="settings_backup_share">バックアップ共有</string>
|
||||
</resources>
|
||||
@@ -91,9 +91,9 @@
|
||||
<string name="main_download">다운로드</string>
|
||||
<string name="settings_backup_title">즐겨찾기 백업</string>
|
||||
<string name="settings_restore_title">즐겨찾기 복원</string>
|
||||
<string name="settings_backup_snackbar">백업 파일을 생성하였습니다</string>
|
||||
<string name="settings_backup_file_created">백업 파일을 생성하였습니다</string>
|
||||
<string name="settings_restore_failed">복원에 실패했습니다</string>
|
||||
<string name="settings_restore_successful">%1$d개 항목을 복원했습니다</string>
|
||||
<string name="settings_restore_success">%1$d개 항목을 복원했습니다</string>
|
||||
<string name="settings_dl_location">다운로드 위치</string>
|
||||
<string name="settings_dl_location_internal">내부 저장공간</string>
|
||||
<string name="settings_dl_location_removable">외부 SD카드</string>
|
||||
@@ -137,4 +137,7 @@
|
||||
<string name="reader_fab_auto">자동 스크롤</string>
|
||||
<string name="search_all">모든 갤러리 검색</string>
|
||||
<string name="settings_rtl">좌측으로 페이지 넘기기</string>
|
||||
<string name="settings_manage_favorites">즐겨찾기 관리</string>
|
||||
<string name="settings_backup_failed">업로드 실패</string>
|
||||
<string name="settings_backup_share">백업 공유</string>
|
||||
</resources>
|
||||
@@ -5,8 +5,6 @@
|
||||
<item name="request_lock" type="id" />
|
||||
<item name="request_restore" type="id" />
|
||||
|
||||
<item name="request_import_old_galleries" type="id" />
|
||||
<item name="request_import_old_galleries_old" type="id" />
|
||||
<item name="request_download_folder" type="id" />
|
||||
<item name="request_download_folder_old" type="id" />
|
||||
<item name="request_write_permission_and_saf" type="id" />
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
<string name="email" translatable="false">mailto:pupil.hentai@gmail.com</string>
|
||||
<string name="discord" translatable="false">https://discord.gg/Stj4b5v</string>
|
||||
|
||||
<string name="backup_url" translatable="false">http://ix.io/</string>
|
||||
|
||||
<string name="main_settings" translatable="false">Settings</string>
|
||||
<string name="galleryblock_thumbnail_description" translatable="false">Thumbnail</string>
|
||||
|
||||
@@ -154,15 +156,21 @@
|
||||
<string name="settings_dark_mode_title">Dark mode</string>
|
||||
<string name="settings_dark_mode_summary">Protect yourself against light attacks!</string>
|
||||
<string name="settings_nomedia_title">Hide image from gallery</string>
|
||||
<string name="settings_backup_title">Backup favorites</string>
|
||||
<string name="settings_backup_snackbar">Backup file created</string>
|
||||
<string name="settings_restore_title">Restore favorites</string>
|
||||
<string name="settings_restore_failed">Restore failed</string>
|
||||
<string name="settings_restore_successful">%1$d entries restored</string>
|
||||
<string name="settings_import_old_galleries">Import old galleries</string>
|
||||
<string name="settings_user_id">User ID</string>
|
||||
<string name="settings_user_id_toast">User ID is copied to clipboard</string>
|
||||
|
||||
<!-- MANAGE FAVORITES -->
|
||||
|
||||
<string name="settings_manage_favorites">Manage favorites</string>
|
||||
<string name="settings_backup_title">Backup favorites</string>
|
||||
<string name="settings_backup_failed">Upload Failed</string>
|
||||
<string name="settings_backup_share">Share Backup</string>
|
||||
<string name="settings_backup_file_created">Backup file created</string>
|
||||
<string name="settings_restore_title">Restore favorites</string>
|
||||
<string name="settings_restore_failed">Restore failed</string>
|
||||
<string name="settings_restore_success">%1$d entries restored</string>
|
||||
|
||||
<!-- SETTINGS/APP LOCK ACTIVITY -->
|
||||
|
||||
<string name="settings_lock_none">None</string>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen
|
||||
<PreferenceScreen
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<Preference
|
||||
@@ -23,4 +23,4 @@
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
</androidx.preference.PreferenceScreen>
|
||||
</PreferenceScreen>
|
||||
30
app/src/main/res/xml/manage_favorites_preferences.xml
Normal file
30
app/src/main/res/xml/manage_favorites_preferences.xml
Normal file
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ 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 <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<Preference
|
||||
app:key="backup"
|
||||
app:title="@string/settings_backup_title"/>
|
||||
|
||||
<Preference
|
||||
app:key="restore"
|
||||
app:title="@string/settings_restore_title"/>
|
||||
|
||||
</PreferenceScreen>
|
||||
25
app/src/main/res/xml/network_security_config.xml
Normal file
25
app/src/main/res/xml/network_security_config.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ 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 <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<network-security-config>
|
||||
<domain-config cleartextTrafficPermitted="true">
|
||||
<domain includeSubdomains="false">ix.io</domain>
|
||||
</domain-config>
|
||||
|
||||
</network-security-config>
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen
|
||||
<PreferenceScreen
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<Preference
|
||||
@@ -101,12 +101,8 @@
|
||||
app:title="@string/settings_nomedia_title"/>
|
||||
|
||||
<Preference
|
||||
app:key="backup"
|
||||
app:title="@string/settings_backup_title"/>
|
||||
|
||||
<Preference
|
||||
app:key="restore"
|
||||
app:title="@string/settings_restore_title"/>
|
||||
app:fragment="xyz.quaver.pupil.ui.fragment.ManageFavoritesFragment"
|
||||
app:title="@string/settings_manage_favorites"/>
|
||||
|
||||
<Preference
|
||||
app:key="user_id"
|
||||
@@ -114,4 +110,4 @@
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
</androidx.preference.PreferenceScreen>
|
||||
</PreferenceScreen>
|
||||
Reference in New Issue
Block a user