diff --git a/app/build.gradle b/app/build.gradle
index bf27adc7..9f4d114b 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,6 +1,7 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
+apply plugin: 'kotlinx-serialization'
android {
compileSdkVersion 28
@@ -22,9 +23,10 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
- implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.1'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.2.1'
+ implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.11.0"
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.preference:preference:1.1.0-alpha05'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index ae7692db..1bdffc64 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -3,6 +3,8 @@
package="xyz.quaver.pupil">
+
+
+
+
+
+
+
>()
private var isLoading = false
@@ -35,6 +52,10 @@ class MainActivity : AppCompatActivity() {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
+ checkPermission()
+
+ update()
+
main_appbar_layout.addOnOffsetChangedListener(
AppBarLayout.OnOffsetChangedListener { _, p1 ->
main_searchview.translationY = p1.toFloat()
@@ -58,6 +79,79 @@ class MainActivity : AppCompatActivity() {
fetchGalleries(query)
}
+ private fun checkPermission() {
+ val permissions = arrayOf(
+ Manifest.permission.WRITE_EXTERNAL_STORAGE
+ )
+
+ if (permissions.any { ContextCompat.checkSelfPermission(this, it) != PackageManager.PERMISSION_GRANTED }) {
+ if (permissions.any { ActivityCompat.shouldShowRequestPermissionRationale(this, it) })
+ AlertDialog.Builder(this).apply {
+ setTitle(R.string.warning)
+ setMessage(R.string.permission_explain)
+ setPositiveButton(android.R.string.ok) { _, _ -> }
+ }.show()
+ else
+ ActivityCompat.requestPermissions(this, permissions, PERMISSION_REQUEST_CODE)
+ }
+ }
+
+ private fun update() {
+ if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)
+ return
+
+ CoroutineScope(Dispatchers.Default).launch {
+ val update =
+ checkUpdate(getString(R.string.release_url), BuildConfig.VERSION_NAME) ?: return@launch
+
+ val (url, fileName) = getApkUrl(update, getString(R.string.release_name)) ?: return@launch
+
+ val dialog = AlertDialog.Builder(this@MainActivity).apply {
+ setTitle(R.string.update_title)
+ setMessage(getString(R.string.update_message, update["tag_name"], BuildConfig.VERSION_NAME))
+ setPositiveButton(android.R.string.yes) { _, _ ->
+ val dest = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), fileName)
+ val desturi =
+ FileProvider.getUriForFile(
+ applicationContext,
+ "xyz.quaver.pupil.provider",
+ dest
+ )
+
+ if (dest.exists())
+ dest.delete()
+
+ val request = DownloadManager.Request(Uri.parse(url)).apply {
+ setDescription(getString(R.string.update_notification_description))
+ setTitle(getString(R.string.app_name))
+ setDestinationUri(Uri.fromFile(dest))
+ }
+
+ val manager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
+ val id = manager.enqueue(request)
+
+ registerReceiver(object: BroadcastReceiver() {
+ override fun onReceive(context: Context?, intent: Intent?) {
+ val install = Intent(Intent.ACTION_VIEW).apply {
+ flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_GRANT_READ_URI_PERMISSION
+ setDataAndType(desturi, manager.getMimeTypeForDownloadedFile(id))
+ }
+
+ startActivity(install)
+ unregisterReceiver(this)
+ finish()
+ }
+ }, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
+ }
+ setNegativeButton(android.R.string.no) { _, _ ->}
+ }
+
+ launch(Dispatchers.Main) {
+ dialog.show()
+ }
+ }
+ }
+
private fun setupRecyclerView() {
with(main_recyclerview) {
adapter = GalleryBlockAdapter(galleries).apply {
diff --git a/app/src/main/java/xyz/quaver/pupil/SettingsActivity.kt b/app/src/main/java/xyz/quaver/pupil/SettingsActivity.kt
index f179742e..3df30a5a 100644
--- a/app/src/main/java/xyz/quaver/pupil/SettingsActivity.kt
+++ b/app/src/main/java/xyz/quaver/pupil/SettingsActivity.kt
@@ -51,8 +51,8 @@ class SettingsActivity : AppCompatActivity() {
setOnPreferenceClickListener {
AlertDialog.Builder(context).apply {
- setTitle(getString(R.string.settings_delete_cache_alert_title))
- setMessage(getString(R.string.settings_delete_cache_alert_message))
+ setTitle(R.string.warning)
+ setMessage(R.string.settings_delete_cache_alert_message)
setPositiveButton(android.R.string.yes) { _, _ ->
with(context.cacheDir) {
if (exists())
diff --git a/app/src/main/java/xyz/quaver/pupil/util/update.kt b/app/src/main/java/xyz/quaver/pupil/util/update.kt
new file mode 100644
index 00000000..e5037094
--- /dev/null
+++ b/app/src/main/java/xyz/quaver/pupil/util/update.kt
@@ -0,0 +1,31 @@
+package xyz.quaver.pupil.util
+
+import kotlinx.serialization.json.*
+import java.net.URL
+
+fun getReleases(url: String) : JsonArray {
+ return URL(url).readText().let {
+ Json(JsonConfiguration.Stable).parse(JsonArray.serializer(), it)
+ }
+}
+
+fun checkUpdate(url: String, currentVersion: String) : JsonObject? {
+ val releases = getReleases(url)
+
+ if (releases.isEmpty())
+ return null
+
+ if (currentVersion != releases[0].jsonObject["tag_name"]?.content)
+ return releases[0].jsonObject
+
+ return null
+}
+
+fun getApkUrl(releases: JsonObject, releaseName: String) : Pair? {
+ releases["assets"]?.jsonArray?.forEach {
+ if (Regex(releaseName).matches(it.jsonObject["name"]?.content ?: ""))
+ return Pair(it.jsonObject["browser_download_url"]?.content, it.jsonObject["name"]?.content)
+ }
+
+ return null
+}
\ 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 f8f2a91e..ea030bd9 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,6 +1,17 @@
+ Warning
+
Pupil
+ Denying any permission can deactivate some functions
+
+ https://api.github.com/repos/tom5079/Pupil-issue/releases
+ Pupil-v(\\d+\\.)+\\d+\\.apk
+
+ Update available
+ Version %1$s is available!\n(current version is %2$s)\nDo you want to update?
+ Downloading apk…
+
Settings
Search
No result
@@ -26,7 +37,6 @@
Delete Cache
Currently using %1$d%2$s of cache
- Warning
Deleting cache can affect image loading speed. Do you want to continue?
diff --git a/app/src/main/res/xml/filepaths.xml b/app/src/main/res/xml/filepaths.xml
new file mode 100644
index 00000000..39d4696d
--- /dev/null
+++ b/app/src/main/res/xml/filepaths.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/test/java/xyz/quaver/pupil/ExampleUnitTest.kt b/app/src/test/java/xyz/quaver/pupil/ExampleUnitTest.kt
index d5e91efa..763e19e4 100644
--- a/app/src/test/java/xyz/quaver/pupil/ExampleUnitTest.kt
+++ b/app/src/test/java/xyz/quaver/pupil/ExampleUnitTest.kt
@@ -1,5 +1,8 @@
package xyz.quaver.pupil
+import org.junit.Test
+import xyz.quaver.pupil.util.checkUpdate
+
/**
* Example local unit test, which will execute on the development machine (host).
*
@@ -8,4 +11,9 @@ package xyz.quaver.pupil
class ExampleUnitTest {
+ @Test
+ fun test() {
+ print(checkUpdate("https://api.github.com/repos/tom5079/Pupil-issue/releases", "0.0.1"))
+ }
+
}
diff --git a/build.gradle b/build.gradle
index c136f825..f65a220a 100644
--- a/build.gradle
+++ b/build.gradle
@@ -5,12 +5,12 @@ buildscript {
repositories {
google()
jcenter()
-
}
dependencies {
classpath 'com.android.tools.build:gradle:3.4.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
+ classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
diff --git a/libpupil/build.gradle b/libpupil/build.gradle
index 17a6560d..b616a77e 100644
--- a/libpupil/build.gradle
+++ b/libpupil/build.gradle
@@ -4,7 +4,7 @@ apply plugin: 'kotlinx-serialization'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
- implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.1'
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.11.0"
implementation 'org.jsoup:jsoup:1.11.3'
@@ -19,7 +19,6 @@ buildscript {
mavenCentral()
}
dependencies {
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
}
diff --git a/libpupil/src/main/java/xyz/quaver/hitomi/readers.kt b/libpupil/src/main/java/xyz/quaver/hitomi/readers.kt
index 23d43b58..8ceb06f9 100644
--- a/libpupil/src/main/java/xyz/quaver/hitomi/readers.kt
+++ b/libpupil/src/main/java/xyz/quaver/hitomi/readers.kt
@@ -3,6 +3,8 @@ package xyz.quaver.hitomi
import kotlinx.serialization.ImplicitReflectionSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
+import kotlinx.serialization.json.JsonConfiguration
+import kotlinx.serialization.list
import kotlinx.serialization.parseList
import org.jsoup.Jsoup
import java.net.URL
@@ -21,7 +23,6 @@ data class Reader(
val images: List>
)
//Set header `Referer` to reader url to avoid 403 error
-@UseExperimental(ImplicitReflectionSerializer::class)
fun getReader(galleryID: Int) : Reader {
val readerUrl = "https://hitomi.la/reader/$galleryID.html"
val galleryInfoUrl = "https://ltn.hitomi.la/galleries/$galleryID.js"
@@ -36,8 +37,10 @@ fun getReader(galleryID: Int) : Reader {
val galleryInfo = ArrayList()
- galleryInfo.addAll(Json.parseList(
- Regex("""\[.+\]""").find(
+ galleryInfo.addAll(
+ Json(JsonConfiguration.Stable).parse(
+ GalleryInfo.serializer().list,
+ Regex("""\[.+]""").find(
URL(galleryInfoUrl).readText()
)?.value ?: "[]"
)