Implemented new favorite backup/restore feature

This commit is contained in:
tom5079
2020-08-26 23:40:36 +09:00
parent 68c94d1d8b
commit 3558d826fb
21 changed files with 292 additions and 106 deletions

View File

@@ -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'

Binary file not shown.

View File

@@ -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

View File

@@ -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,7 +37,9 @@
</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" />
</intent-filter>
@@ -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>

View File

@@ -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()
}

View File

@@ -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() }
}
}

View File

@@ -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 -> {

View File

@@ -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)

View File

@@ -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()

View File

@@ -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
}
}
}

View File

@@ -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" -> {

View File

@@ -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() })

View File

@@ -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())
@@ -185,3 +175,28 @@ fun checkUpdate(context: Context, force: Boolean = false) {
}
}
}
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)
}
}
})
}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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" />

View File

@@ -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>

View File

@@ -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>

View 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>

View 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>

View File

@@ -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>