Merge pull request #30 from tom5079/Pupil-24

fixed #24
This commit is contained in:
Pupil
2019-12-08 18:45:21 +09:00
committed by GitHub
12 changed files with 139 additions and 13 deletions

View File

@@ -14,7 +14,7 @@ android {
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 29 targetSdkVersion 29
versionCode 31 versionCode 31
versionName "4.2" versionName "4.2-beta1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true multiDexEnabled true
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
@@ -26,7 +26,7 @@ android {
} }
buildTypes.each { buildTypes.each {
it.buildConfigField('boolean', 'PRERELEASE', 'false') it.buildConfigField('boolean', 'PRERELEASE', 'false')
it.buildConfigField('boolean', 'CENSOR', 'true') it.buildConfigField('boolean', 'CENSOR', 'false')
} }
} }
kotlinOptions { kotlinOptions {

View File

@@ -33,6 +33,7 @@ import xyz.quaver.hiyobi.createImgList
import xyz.quaver.hiyobi.getReader import xyz.quaver.hiyobi.getReader
import xyz.quaver.hiyobi.user_agent import xyz.quaver.hiyobi.user_agent
import xyz.quaver.pupil.ui.LockActivity import xyz.quaver.pupil.ui.LockActivity
import xyz.quaver.pupil.util.getDownloadDirectory
import java.net.URL import java.net.URL
import javax.net.ssl.HttpsURLConnection import javax.net.ssl.HttpsURLConnection
@@ -48,6 +49,7 @@ class ExampleInstrumentedTest {
fun useAppContext() { fun useAppContext() {
// Context of the app under test. // Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext val appContext = InstrumentationRegistry.getInstrumentation().targetContext
Log.i("PUPILD", getDownloadDirectory(appContext).absolutePath ?: "")
assertEquals("xyz.quaver.pupil", appContext.packageName) assertEquals("xyz.quaver.pupil", appContext.packageName)
} }
@@ -57,8 +59,6 @@ class ExampleInstrumentedTest {
val appContext = InstrumentationRegistry.getInstrumentation().targetContext val appContext = InstrumentationRegistry.getInstrumentation().targetContext
activityTestRule.launchActivity(Intent()) activityTestRule.launchActivity(Intent())
while(true);
} }
@Test @Test
@@ -76,4 +76,4 @@ class ExampleInstrumentedTest {
Log.d("Pupil", data.size.toString()) Log.d("Pupil", data.size.toString())
} }
} }

View File

@@ -20,6 +20,18 @@
android:theme="@style/AppTheme" android:theme="@style/AppTheme"
tools:replace="android:theme"> tools:replace="android:theme">
<provider
android:authorities="${applicationId}.fileprovider"
android:name="androidx.core.content.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"/>
</provider>
<activity android:name=".ui.LockActivity"/> <activity android:name=".ui.LockActivity"/>
<activity <activity
android:name=".ui.ReaderActivity" android:name=".ui.ReaderActivity"

View File

@@ -338,7 +338,7 @@ class GalleryBlockAdapter(private val glide: RequestManager, private val galleri
holder.view.galleryblock_download.text = when(GalleryDownloader.get(gallery.first.id)) { holder.view.galleryblock_download.text = when(GalleryDownloader.get(gallery.first.id)) {
null -> holder.view.context.getString(R.string.main_download) null -> holder.view.context.getString(R.string.main_download)
else -> holder.view.context.getString(R.string.main_cancel_download) else -> holder.view.context.getString(android.R.string.cancel)
} }
} }

View File

@@ -32,10 +32,15 @@ import android.widget.TextView
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import androidx.core.content.ContextCompat
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.dialog_default_query.view.* import kotlinx.android.synthetic.main.dialog_default_query.view.*
import kotlinx.serialization.ImplicitReflectionSerializer
import kotlinx.serialization.json.Json
import kotlinx.serialization.parseList
import xyz.quaver.pupil.Pupil import xyz.quaver.pupil.Pupil
import xyz.quaver.pupil.R import xyz.quaver.pupil.R
import xyz.quaver.pupil.types.Tags import xyz.quaver.pupil.types.Tags
@@ -43,10 +48,13 @@ import xyz.quaver.pupil.util.Lock
import xyz.quaver.pupil.util.LockManager import xyz.quaver.pupil.util.LockManager
import xyz.quaver.pupil.util.getDownloadDirectory import xyz.quaver.pupil.util.getDownloadDirectory
import java.io.File import java.io.File
import java.nio.charset.Charset
import java.util.*
class SettingsActivity : AppCompatActivity() { class SettingsActivity : AppCompatActivity() {
val REQUEST_LOCK = 38238 val REQUEST_LOCK = 38238
val REQUEST_RESTORE = 16546
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@@ -154,7 +162,7 @@ class SettingsActivity : AppCompatActivity() {
with(findPreference<Preference>("delete_downloads")) { with(findPreference<Preference>("delete_downloads")) {
this!! this!!
val dir = getDownloadDirectory(context)!! val dir = getDownloadDirectory(context)
summary = getDirSize(dir) summary = getDirSize(dir)
@@ -278,7 +286,7 @@ class SettingsActivity : AppCompatActivity() {
s ?: return s ?: return
if (s.any { it.isUpperCase() }) if (s.any { it.isUpperCase() })
s.replace(0, s.length, s.toString().toLowerCase()) s.replace(0, s.length, s.toString().toLowerCase(Locale.getDefault()))
} }
}) })
} }
@@ -352,6 +360,37 @@ class SettingsActivity : AppCompatActivity() {
true true
} }
} }
with(findPreference<Preference>("backup")) {
this!!
onPreferenceClickListener = Preference.OnPreferenceClickListener {
File(ContextCompat.getDataDir(context), "favorites.json").copyTo(
File(getDownloadDirectory(context), "favorites.json"),
true
)
Snackbar.make(this@SettingsFragment.listView, R.string.settings_backup_snackbar, Snackbar.LENGTH_LONG)
.show()
true
}
}
with(findPreference<Preference>("restore")) {
this!!
onPreferenceClickListener = Preference.OnPreferenceClickListener {
val intent = Intent(Intent.ACTION_GET_CONTENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "*/*"
}
activity?.startActivityForResult(intent, (activity as SettingsActivity).REQUEST_RESTORE)
true
}
}
} }
} }
@@ -415,6 +454,7 @@ class SettingsActivity : AppCompatActivity() {
return true return true
} }
@UseExperimental(ImplicitReflectionSerializer::class)
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when(requestCode) { when(requestCode) {
REQUEST_LOCK -> { REQUEST_LOCK -> {
@@ -426,6 +466,33 @@ class SettingsActivity : AppCompatActivity() {
.commitAllowingStateLoss() .commitAllowingStateLoss()
} }
} }
REQUEST_RESTORE -> {
if (resultCode == Activity.RESULT_OK) {
val uri = data?.data ?: return
try {
val json = contentResolver.openInputStream(uri).use { inputStream ->
inputStream!!
inputStream.readBytes().toString(Charset.defaultCharset())
}
(application as Pupil).favorites.addAll(Json.parseList<Int>(json).also {
Snackbar.make(
window.decorView,
getString(R.string.settings_restore_successful, it.size),
Snackbar.LENGTH_LONG
).show()
})
} catch (e: Exception) {
Snackbar.make(
window.decorView,
R.string.settings_restore_failed,
Snackbar.LENGTH_LONG
).show()
}
}
}
else -> super.onActivityResult(requestCode, resultCode, data) else -> super.onActivityResult(requestCode, resultCode, data)
} }
} }

View File

@@ -33,9 +33,9 @@ fun getCachedGallery(context: Context, galleryID: Int): File {
} }
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
fun getDownloadDirectory(context: Context): File? { fun getDownloadDirectory(context: Context): File {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
context.getExternalFilesDir("Pupil") context.getExternalFilesDir("Pupil")!!
else else
File(Environment.getExternalStorageDirectory(), "Pupil") File(Environment.getExternalStorageDirectory(), "Pupil")
} }

View File

@@ -105,4 +105,10 @@
<string name="main_delete">削除</string> <string name="main_delete">削除</string>
<string name="main_download">ダウンロード</string> <string name="main_download">ダウンロード</string>
<string name="main_cancel_download">キャンセル</string> <string name="main_cancel_download">キャンセル</string>
<string name="settings_backup_title">お気に入りバックアップ</string>
<string name="settings_restore_title">お気に入り復元</string>
<string name="settings_backup_snackbar">バックアップファイルを作成しました</string>
<string name="settings_backup_checkout">確認</string>
<string name="settings_restore_failed">復元に失敗しました</string>
<string name="settings_restore_successful">%1$d項目を復元しました</string>
</resources> </resources>

View File

@@ -105,4 +105,10 @@
<string name="main_delete">삭제</string> <string name="main_delete">삭제</string>
<string name="main_download">다운로드</string> <string name="main_download">다운로드</string>
<string name="main_cancel_download">취소</string> <string name="main_cancel_download">취소</string>
<string name="settings_backup_title">즐겨찾기 백업</string>
<string name="settings_restore_title">즐겨찾기 복원</string>
<string name="settings_backup_snackbar">백업 파일을 생성하였습니다</string>
<string name="settings_backup_checkout">확인</string>
<string name="settings_restore_failed">복원에 실패했습니다</string>
<string name="settings_restore_successful">%1$d개 항목을 복원했습니다</string>
</resources> </resources>

View File

@@ -72,7 +72,6 @@
<string name="main_export_error">Error occurred during export</string> <string name="main_export_error">Error occurred during export</string>
<string name="main_download">DOWNLOAD</string> <string name="main_download">DOWNLOAD</string>
<string name="main_cancel_download">CANCEL</string>
<string name="main_delete">DELETE</string> <string name="main_delete">DELETE</string>
<string name="update_title">Update available</string> <string name="update_title">Update available</string>
@@ -133,6 +132,12 @@
<string name="settings_dark_mode_summary">Protect yourself against light attacks!</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_nomedia_title">Hide image from gallery</string>
<string name="settings_nomedia_summary">Hides image from gallery</string> <string name="settings_nomedia_summary">Hides image from gallery</string>
<string name="settings_backup_title">Backup favorites</string>
<string name="settings_backup_snackbar">Backup file created</string>
<string name="settings_backup_checkout">Check out</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_lock_none">None</string> <string name="settings_lock_none">None</string>
<string name="settings_lock_pattern">Pattern</string> <string name="settings_lock_pattern">Pattern</string>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Pupil, Hitomi.la viewer for Android
~ Copyright (C) 2019 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/>.
-->
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external" path="/"/>
</paths>

View File

@@ -74,6 +74,14 @@
app:title="@string/settings_nomedia_title" app:title="@string/settings_nomedia_title"
app:summary="@string/settings_nomedia_title"/> app:summary="@string/settings_nomedia_title"/>
<Preference
app:key="backup"
app:title="@string/settings_backup_title"/>
<Preference
app:key="restore"
app:title="@string/settings_restore_title"/>
</PreferenceCategory> </PreferenceCategory>
</androidx.preference.PreferenceScreen> </androidx.preference.PreferenceScreen>

View File

@@ -1,14 +1,14 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
ext.kotlin_version = '1.3.60' ext.kotlin_version = '1.3.61'
repositories { repositories {
google() google()
jcenter() jcenter()
maven { url 'https://maven.fabric.io/public' } maven { url 'https://maven.fabric.io/public' }
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.5.2' classpath 'com.android.tools.build:gradle:3.5.3'
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"