ugh
This commit is contained in:
@@ -61,6 +61,7 @@ dependencies {
|
|||||||
implementation 'androidx.preference:preference:1.1.0'
|
implementation 'androidx.preference:preference:1.1.0'
|
||||||
implementation 'androidx.gridlayout:gridlayout:1.0.0'
|
implementation 'androidx.gridlayout:gridlayout:1.0.0'
|
||||||
implementation "androidx.biometric:biometric:1.0.1"
|
implementation "androidx.biometric:biometric:1.0.1"
|
||||||
|
implementation "androidx.documentfile:documentfile:1.0.1"
|
||||||
implementation 'com.android.support:multidex:1.0.3'
|
implementation 'com.android.support:multidex:1.0.3'
|
||||||
implementation "com.daimajia.swipelayout:library:1.2.0@aar"
|
implementation "com.daimajia.swipelayout:library:1.2.0@aar"
|
||||||
implementation 'com.google.android.material:material:1.2.0-alpha04'
|
implementation 'com.google.android.material:material:1.2.0-alpha04'
|
||||||
|
|||||||
@@ -6,9 +6,7 @@
|
|||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||||
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
|
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
|
||||||
<uses-permission
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
|
||||||
android:maxSdkVersion="21" />
|
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".Pupil"
|
android:name=".Pupil"
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import android.app.Notification
|
|||||||
import android.app.NotificationChannel
|
import android.app.NotificationChannel
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
@@ -41,6 +40,7 @@ class Pupil : MultiDexApplication() {
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
|
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
@@ -49,17 +49,6 @@ class Pupil : MultiDexApplication() {
|
|||||||
histories = Histories(File(ContextCompat.getDataDir(this), "histories.json"))
|
histories = Histories(File(ContextCompat.getDataDir(this), "histories.json"))
|
||||||
favorites = Histories(File(ContextCompat.getDataDir(this), "favorites.json"))
|
favorites = Histories(File(ContextCompat.getDataDir(this), "favorites.json"))
|
||||||
|
|
||||||
val download = try {
|
|
||||||
preference.getString("dl_location", null)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
preference.edit().remove("dl_location").apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (download == null) {
|
|
||||||
val default = ContextCompat.getExternalFilesDirs(this, null)[0]
|
|
||||||
preference.edit().putString("dl_location", Uri.fromFile(default).toString()).apply()
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ProviderInstaller.installIfNeeded(this)
|
ProviderInstaller.installIfNeeded(this)
|
||||||
} catch (e: GooglePlayServicesRepairableException) {
|
} catch (e: GooglePlayServicesRepairableException) {
|
||||||
|
|||||||
@@ -124,10 +124,8 @@ class SettingsActivity : AppCompatActivity() {
|
|||||||
REQUEST_DOWNLOAD_FOLDER -> {
|
REQUEST_DOWNLOAD_FOLDER -> {
|
||||||
if (resultCode == Activity.RESULT_OK) {
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
data?.data?.also { uri ->
|
data?.data?.also { uri ->
|
||||||
val takeFlags: Int = intent.flags and (Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
|
||||||
contentResolver.takePersistableUriPermission(uri, takeFlags)
|
contentResolver.takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||||
|
|
||||||
if (DocumentFile.fromTreeUri(this, uri)?.canWrite() == false)
|
if (DocumentFile.fromTreeUri(this, uri)?.canWrite() == false)
|
||||||
Snackbar.make(settings, R.string.settings_dl_location_not_writable, Snackbar.LENGTH_LONG).show()
|
Snackbar.make(settings, R.string.settings_dl_location_not_writable, Snackbar.LENGTH_LONG).show()
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import xyz.quaver.pupil.R
|
|||||||
import xyz.quaver.pupil.util.REQUEST_DOWNLOAD_FOLDER
|
import xyz.quaver.pupil.util.REQUEST_DOWNLOAD_FOLDER
|
||||||
import xyz.quaver.pupil.util.REQUEST_DOWNLOAD_FOLDER_OLD
|
import xyz.quaver.pupil.util.REQUEST_DOWNLOAD_FOLDER_OLD
|
||||||
import xyz.quaver.pupil.util.byteToString
|
import xyz.quaver.pupil.util.byteToString
|
||||||
|
import xyz.quaver.pupil.util.getDownloadDirectory
|
||||||
|
|
||||||
@SuppressLint("InflateParams")
|
@SuppressLint("InflateParams")
|
||||||
class DownloadLocationDialog(val activity: Activity) : AlertDialog(activity) {
|
class DownloadLocationDialog(val activity: Activity) : AlertDialog(activity) {
|
||||||
@@ -106,9 +107,9 @@ class DownloadLocationDialog(val activity: Activity) : AlertDialog(activity) {
|
|||||||
buttons.add(button to null)
|
buttons.add(button to null)
|
||||||
})
|
})
|
||||||
|
|
||||||
val pref = Uri.parse(preference.getString("dl_location", null))
|
val pref = getDownloadDirectory(context)
|
||||||
val index = externalFilesDirs.indexOfFirst {
|
val index = externalFilesDirs.indexOfFirst {
|
||||||
Uri.fromFile(it).toString() == pref.toString()
|
Uri.fromFile(it).toString() == pref.uri.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
|
|||||||
@@ -21,4 +21,5 @@ package xyz.quaver.pupil.util
|
|||||||
const val REQUEST_LOCK = 38238
|
const val REQUEST_LOCK = 38238
|
||||||
const val REQUEST_RESTORE = 16546
|
const val REQUEST_RESTORE = 16546
|
||||||
const val REQUEST_DOWNLOAD_FOLDER = 3874
|
const val REQUEST_DOWNLOAD_FOLDER = 3874
|
||||||
const val REQUEST_DOWNLOAD_FOLDER_OLD = 3425
|
const val REQUEST_DOWNLOAD_FOLDER_OLD = 3425
|
||||||
|
const val REQUEST_DOWNLOAD_FOLDER_AND_PERMISSION = 34257
|
||||||
@@ -207,10 +207,7 @@ class Cache(context: Context) : ContextWrapper(context) {
|
|||||||
throw IllegalArgumentException("File name is not a number")
|
throw IllegalArgumentException("File name is not a number")
|
||||||
|
|
||||||
cache.let {
|
cache.let {
|
||||||
if (it.findFile(name) != null)
|
it.findFile(name) ?: it.createFile("null", name)
|
||||||
it
|
|
||||||
else
|
|
||||||
it.createFile("null", name)
|
|
||||||
}?.writeBytes(this, data)
|
}?.writeBytes(this, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,11 +218,14 @@ class Cache(context: Context) : ContextWrapper(context) {
|
|||||||
val download = getDownloadDirectory(this)
|
val download = getDownloadDirectory(this)
|
||||||
|
|
||||||
if (!download.isParentOf(cache)) {
|
if (!download.isParentOf(cache)) {
|
||||||
|
val target = getDownloadDirectory(this).let {
|
||||||
|
it.findFile(galleryID.toString()) ?: it.createDirectory(galleryID.toString())
|
||||||
|
}
|
||||||
|
|
||||||
cache.copyRecursively(this, download)
|
cache.copyRecursively(this, download)
|
||||||
cache.deleteRecursively()
|
cache.deleteRecursively()
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
getDownloadDirectory(this).createDirectory(galleryID.toString())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isDownloading(galleryID: Int) = getCachedMetadata(galleryID)?.isDownloading == true
|
fun isDownloading(galleryID: Int) = getCachedMetadata(galleryID)?.isDownloading == true
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import android.content.Context
|
|||||||
import android.content.ContextWrapper
|
import android.content.ContextWrapper
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
|
import android.util.Log
|
||||||
import android.util.SparseArray
|
import android.util.SparseArray
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
@@ -152,12 +153,6 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
|
|||||||
val request = chain.request()
|
val request = chain.request()
|
||||||
var response = chain.proceed(request)
|
var response = chain.proceed(request)
|
||||||
|
|
||||||
var retry = preferences.getInt("retry", 3)
|
|
||||||
while (!response.isSuccessful && retry > 0) {
|
|
||||||
response = chain.proceed(request)
|
|
||||||
retry--
|
|
||||||
}
|
|
||||||
|
|
||||||
response.newBuilder()
|
response.newBuilder()
|
||||||
.body(ProgressResponseBody(request.tag(), response.body(), progressListener))
|
.body(ProgressResponseBody(request.tag(), response.body(), progressListener))
|
||||||
.build()
|
.build()
|
||||||
@@ -288,6 +283,7 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
|
|||||||
for (i in reader.galleryInfo.indices) {
|
for (i in reader.galleryInfo.indices) {
|
||||||
val callback = object : Callback {
|
val callback = object : Callback {
|
||||||
override fun onFailure(call: Call, e: IOException) {
|
override fun onFailure(call: Call, e: IOException) {
|
||||||
|
Log.i("PUPILD", "FAILED $i")
|
||||||
if (Fabric.isInitialized())
|
if (Fabric.isInitialized())
|
||||||
Crashlytics.logException(e)
|
Crashlytics.logException(e)
|
||||||
|
|
||||||
@@ -307,6 +303,7 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onResponse(call: Call, response: Response) {
|
override fun onResponse(call: Call, response: Response) {
|
||||||
|
Log.i("PUPILD", "SUCCESS $i")
|
||||||
response.body().use {
|
response.body().use {
|
||||||
val res = it.bytes()
|
val res = it.bytes()
|
||||||
val ext =
|
val ext =
|
||||||
|
|||||||
@@ -33,17 +33,22 @@ fun getCachedGallery(context: Context, galleryID: Int) =
|
|||||||
DocumentFile.fromFile(File(context.cacheDir, "imageCache/$galleryID"))
|
DocumentFile.fromFile(File(context.cacheDir, "imageCache/$galleryID"))
|
||||||
|
|
||||||
fun getDownloadDirectory(context: Context) : DocumentFile {
|
fun getDownloadDirectory(context: Context) : DocumentFile {
|
||||||
val uri = PreferenceManager.getDefaultSharedPreferences(context).getString("dl_location", null).let {
|
return runCatching {
|
||||||
|
val uri = PreferenceManager.getDefaultSharedPreferences(context).getString("dl_location", null).let {
|
||||||
if (it != null)
|
if (it != null)
|
||||||
Uri.parse(it)
|
Uri.parse(it)
|
||||||
else
|
else
|
||||||
Uri.fromFile(context.getExternalFilesDir(null))
|
Uri.fromFile(context.getExternalFilesDir(null))
|
||||||
}
|
}
|
||||||
|
|
||||||
return if (uri.toString().startsWith("file"))
|
if (uri.toString().startsWith("file"))
|
||||||
DocumentFile.fromFile(File(uri.path!!))
|
DocumentFile.fromFile(File(uri.path!!))
|
||||||
else
|
else
|
||||||
DocumentFile.fromTreeUri(context, uri) ?: DocumentFile.fromFile(context.getExternalFilesDir(null)!!)
|
DocumentFile.fromTreeUri(context, uri) ?: DocumentFile.fromFile(context.getExternalFilesDir(null)!!)
|
||||||
|
}.getOrElse {
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(context).edit().remove("dl_location").apply()
|
||||||
|
DocumentFile.fromFile(context.getExternalFilesDir(null)!!)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun convertUpdateUri(context: Context, uri: Uri) : Uri =
|
fun convertUpdateUri(context: Context, uri: Uri) : Uri =
|
||||||
@@ -104,32 +109,26 @@ fun DocumentFile.copyRecursively(
|
|||||||
if (!exists())
|
if (!exists())
|
||||||
throw Exception("The source file doesn't exist.")
|
throw Exception("The source file doesn't exist.")
|
||||||
|
|
||||||
if (this.isFile) {
|
this.listFiles().forEach { child ->
|
||||||
target.let {
|
try {
|
||||||
if (it.findFile(name!!) != null)
|
if (child.isFile) {
|
||||||
it
|
target.findFile(name!!) ?: target.createFile("null", name!!)!!
|
||||||
else
|
.writeBytes(
|
||||||
createFile("null", name!!)!!
|
context,
|
||||||
}.writeBytes(
|
readBytes(context)
|
||||||
context,
|
)
|
||||||
readBytes(context)
|
} else if (child.isDirectory) {
|
||||||
)
|
target.findFile(name!!) ?: target.createDirectory(name!!).also { newTarget ->
|
||||||
} else if (this.isDirectory) {
|
child.copyRecursively(context, newTarget!!)
|
||||||
target.createDirectory(name!!).also { newTarget ->
|
}
|
||||||
listFiles().forEach { child ->
|
|
||||||
child.copyRecursively(context, newTarget!!)
|
|
||||||
}
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun DocumentFile.deleteRecursively() {
|
fun DocumentFile.deleteRecursively() {
|
||||||
|
|
||||||
if (this.isDirectory)
|
|
||||||
listFiles().forEach {
|
|
||||||
it.deleteRecursively()
|
|
||||||
}
|
|
||||||
|
|
||||||
this.delete()
|
this.delete()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ abstract class DocumentFileX {
|
|||||||
abstract fun createDirectory(displayName: String): DocumentFileX?
|
abstract fun createDirectory(displayName: String): DocumentFileX?
|
||||||
abstract fun getUri(): Uri
|
abstract fun getUri(): Uri
|
||||||
abstract fun getName(): String
|
abstract fun getName(): String
|
||||||
abstract fun getParentFile(): DocumentFileX?
|
|
||||||
abstract fun isDirectory(): Boolean
|
abstract fun isDirectory(): Boolean
|
||||||
abstract fun isFile(): Boolean
|
abstract fun isFile(): Boolean
|
||||||
abstract fun length(): Long
|
abstract fun length(): Long
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class RawDocumentFileX(private var file: File) : DocumentFileX() {
|
|||||||
|
|
||||||
override fun getName() = file.name
|
override fun getName() = file.name
|
||||||
|
|
||||||
override fun getParentFile() =
|
fun getParentFile() =
|
||||||
file.parentFile.let {
|
file.parentFile.let {
|
||||||
if (it == null)
|
if (it == null)
|
||||||
null
|
null
|
||||||
|
|||||||
@@ -73,21 +73,25 @@ class TreeDocumentFileX(
|
|||||||
val uri = kotlin.runCatching {
|
val uri = kotlin.runCatching {
|
||||||
DocumentsContract.createDocument(context.contentResolver, uri, "null", displayName)
|
DocumentsContract.createDocument(context.contentResolver, uri, "null", displayName)
|
||||||
}.getOrNull() ?: return null
|
}.getOrNull() ?: return null
|
||||||
|
|
||||||
|
return TreeDocumentFileX(context, uri, displayName, DocumentsContract.getDocumentId(uri), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getUri() = uri
|
override fun getUri() = uri
|
||||||
|
|
||||||
override fun getName() = name ?: "null"
|
override fun getName() = name ?: "null"
|
||||||
|
|
||||||
override fun getParentFile(): DocumentFileX?
|
|
||||||
|
|
||||||
override fun isDirectory() = name?.contains('.') == false
|
override fun isDirectory() = name?.contains('.') == false
|
||||||
override fun isFile() = name?.contains('.') == true
|
override fun isFile() = name?.contains('.') == true
|
||||||
|
|
||||||
override fun length() = length ?: -1
|
override fun length() = length ?: -1
|
||||||
|
|
||||||
override fun canRead(): Boolean
|
override fun canRead(): Boolean {
|
||||||
override fun canWrite(): Boolean
|
TODO("Not impelmented")
|
||||||
|
}
|
||||||
|
override fun canWrite(): Boolean {
|
||||||
|
TODO("Not impelmented")
|
||||||
|
}
|
||||||
|
|
||||||
override fun delete() =
|
override fun delete() =
|
||||||
kotlin.runCatching {
|
kotlin.runCatching {
|
||||||
@@ -111,8 +115,12 @@ class TreeDocumentFileX(
|
|||||||
).use {
|
).use {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TODO("Not impelmented")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun findFile(displayName: String): DocumentFileX?
|
override fun findFile(displayName: String): DocumentFileX? {
|
||||||
|
TODO("Not impelmented")
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user