Some minor stuff from upstream (#547)

* local manga changes from stable

* use device pin instead of biometric when biometric cant be used for some reason

* corektx changes

Co-authored-by: arkon <arkon@users.noreply.github.com>
pull/3963/head
Carlos 4 years ago committed by GitHub
parent 45eab517d0
commit c0228f06f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -90,7 +90,7 @@ dependencies {
implementation("com.github.inorichi:subsampling-scale-image-view:ac0dae7")
implementation("com.github.inorichi:junrar-android:634c1f5")
// Android support library
// Android X libraries
implementation("androidx.appcompat:appcompat:1.1.0")
implementation("androidx.cardview:cardview:1.0.0")
implementation("com.google.android.material:material:1.1.0")
@ -100,12 +100,13 @@ dependencies {
implementation("androidx.browser:browser:1.2.0")
implementation("androidx.biometric:biometric:1.0.1")
implementation("androidx.palette:palette:1.0.0")
implementation ("androidx.core:core-ktx:$1.3.1")
implementation("androidx.constraintlayout:constraintlayout:1.1.3")
implementation("androidx.multidex:multidex:2.0.1")
implementation("com.google.firebase:firebase-core:17.3.0")
implementation("com.google.firebase:firebase-core:17.4.4")
val lifecycleVersion = "2.2.0"
implementation("androidx.lifecycle:lifecycle-extensions:$lifecycleVersion")

@ -7,6 +7,7 @@ import android.net.Uri
import android.os.Build
import android.os.IBinder
import android.os.PowerManager
import androidx.core.net.toUri
import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.util.system.isServiceRunning
@ -108,7 +109,7 @@ class BackupCreateService : Service() {
val backupFlags = intent.getIntExtra(BackupConst.EXTRA_FLAGS, 0)
backupManager = BackupManager(this)
val backupFileUri = Uri.parse(backupManager.createBackup(uri, backupFlags, false))
val backupFileUri = backupManager.createBackup(uri, backupFlags, false)?.toUri()
val unifile = UniFile.fromUri(this, backupFileUri)
notifier.showBackupComplete(unifile)
} catch (e: Exception) {

@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.data.backup
import android.content.Context
import android.net.Uri
import androidx.core.net.toUri
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
@ -19,7 +20,7 @@ class BackupCreatorJob(private val context: Context, workerParams: WorkerParamet
override fun doWork(): Result {
val preferences = Injekt.get<PreferencesHelper>()
val backupManager = BackupManager(context)
val uri = Uri.parse(preferences.backupsDirectory().getOrDefault())
val uri = preferences.backupsDirectory().getOrDefault().toUri()
val flags = BackupCreateService.BACKUP_ALL
return try {
backupManager.createBackup(uri, flags, true)

@ -1,7 +1,7 @@
package eu.kanade.tachiyomi.data.download
import android.content.Context
import android.net.Uri
import androidx.core.net.toUri
import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Chapter
@ -57,7 +57,7 @@ class DownloadCache(
*/
private fun getDirectoryFromPreference(): UniFile {
val dir = preferences.downloadsDirectory().getOrDefault()
return UniFile.fromUri(context, Uri.parse(dir))
return UniFile.fromUri(context, dir.toUri())
}
/**

@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.data.download
import android.content.Context
import android.net.Uri
import androidx.core.net.toUri
import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.DatabaseHelper
@ -31,14 +32,14 @@ class DownloadProvider(private val context: Context) {
* The root directory for downloads.
*/
private var downloadsDir = preferences.downloadsDirectory().getOrDefault().let {
val dir = UniFile.fromUri(context, Uri.parse(it))
val dir = UniFile.fromUri(context, it.toUri())
DiskUtil.createNoMediaFile(dir, context)
dir
}
init {
preferences.downloadsDirectory().asObservable().skip(1)
.subscribe { downloadsDir = UniFile.fromUri(context, Uri.parse(it)) }
.subscribe { downloadsDir = UniFile.fromUri(context, it.toUri()) }
}
/**

@ -1,6 +1,7 @@
package eu.kanade.tachiyomi.data.track.anilist
import android.net.Uri
import androidx.core.net.toUri
import com.github.salomonbrys.kotson.array
import com.github.salomonbrys.kotson.get
import com.github.salomonbrys.kotson.jsonObject
@ -232,7 +233,7 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) {
return baseMangaUrl + mediaId
}
fun authUrl() = Uri.parse("${baseUrl}oauth/authorize").buildUpon()
fun authUrl() = "${baseUrl.toUri()}oauth/authorize".toUri().buildUpon()
.appendQueryParameter("client_id", clientId)
.appendQueryParameter("response_type", "token")
.build()!!

@ -1,6 +1,7 @@
package eu.kanade.tachiyomi.data.track.bangumi
import android.net.Uri
import androidx.core.net.toUri
import com.github.salomonbrys.kotson.array
import com.github.salomonbrys.kotson.obj
import com.google.gson.Gson
@ -56,9 +57,8 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
suspend fun search(search: String): List<TrackSearch> {
return withContext(Dispatchers.IO) {
val url = Uri.parse(
"$apiUrl/search/subject/${URLEncoder.encode(search, Charsets.UTF_8.name())}"
).buildUpon().appendQueryParameter("max_results", "20").build()
val url = "$apiUrl/search/subject/${URLEncoder.encode(search, Charsets.UTF_8.name())}"
.toUri().buildUpon().appendQueryParameter("max_results", "20").build()
val request = Request.Builder().url(url.toString()).get().build()
val netResponse = authClient.newCall(request).await()
@ -159,7 +159,7 @@ class BangumiApi(private val client: OkHttpClient, interceptor: BangumiIntercept
return "$baseMangaUrl/$remoteId"
}
fun authUrl() = Uri.parse(loginUrl).buildUpon().appendQueryParameter("client_id", clientId)
fun authUrl() = loginUrl.toUri().buildUpon().appendQueryParameter("client_id", clientId)
.appendQueryParameter("response_type", "code")
.appendQueryParameter("redirect_uri", redirectUrl).build()

@ -1,6 +1,7 @@
package eu.kanade.tachiyomi.data.track.myanimelist
import android.net.Uri
import androidx.core.net.toUri
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.data.track.model.TrackSearch
@ -182,31 +183,31 @@ class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListI
private fun mangaUrl(remoteId: Int) = baseMangaUrl + remoteId
private fun loginUrl() = Uri.parse(baseUrl).buildUpon().appendPath("login.php").toString()
private fun loginUrl() = baseUrl.toUri().buildUpon().appendPath("login.php").toString()
private fun searchUrl(query: String): String {
val col = "c[]"
return Uri.parse(baseUrl).buildUpon().appendPath("manga.php")
return baseUrl.toUri().buildUpon().appendPath("manga.php")
.appendQueryParameter("q", query).appendQueryParameter(col, "a")
.appendQueryParameter(col, "b").appendQueryParameter(col, "c")
.appendQueryParameter(col, "d").appendQueryParameter(col, "e")
.appendQueryParameter(col, "g").toString()
}
private fun exportListUrl() = Uri.parse(baseUrl).buildUpon().appendPath("panel.php")
private fun exportListUrl() = baseUrl.toUri().buildUpon().appendPath("panel.php")
.appendQueryParameter("go", "export").toString()
private fun updateUrl() =
Uri.parse(baseModifyListUrl).buildUpon().appendPath("edit.json").toString()
baseModifyListUrl.toUri().buildUpon().appendPath("edit.json").toString()
private fun removeUrl(mediaId: Int) = Uri.parse(baseModifyListUrl).buildUpon().appendPath(mediaId.toString())
private fun removeUrl(mediaId: Int) = baseModifyListUrl.toUri().buildUpon().appendPath(mediaId.toString())
.appendPath("delete").toString()
private fun addUrl() =
Uri.parse(baseModifyListUrl).buildUpon().appendPath("add.json").toString()
baseModifyListUrl.toUri().buildUpon().appendPath("add.json").toString()
private fun listEntryUrl(mediaId: Int) =
Uri.parse(baseModifyListUrl).buildUpon().appendPath(mediaId.toString())
baseModifyListUrl.toUri().buildUpon().appendPath(mediaId.toString())
.appendPath("edit").toString()
private fun loginPostBody(username: String, password: String, csrf: String): RequestBody {

@ -1,6 +1,7 @@
package eu.kanade.tachiyomi.data.track.shikimori
import android.net.Uri
import androidx.core.net.toUri
import com.github.salomonbrys.kotson.array
import com.github.salomonbrys.kotson.jsonObject
import com.github.salomonbrys.kotson.nullString
@ -52,7 +53,7 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
suspend fun search(search: String): List<TrackSearch> {
return withContext(Dispatchers.IO) {
val url =
Uri.parse("$apiUrl/mangas").buildUpon().appendQueryParameter("order", "popularity")
"$apiUrl/mangas".toUri().buildUpon().appendQueryParameter("order", "popularity")
.appendQueryParameter("search", search).appendQueryParameter("limit", "20")
.build()
val request = Request.Builder().url(url.toString()).get().build()
@ -96,14 +97,13 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
suspend fun findLibManga(track: Track, user_id: String): Track? {
return withContext(Dispatchers.IO) {
val url = Uri.parse("$apiUrl/v2/user_rates").buildUpon()
val url = "$apiUrl/v2/user_rates".toUri().buildUpon()
.appendQueryParameter("user_id", user_id)
.appendQueryParameter("target_id", track.media_id.toString())
.appendQueryParameter("target_type", "Manga").build()
val request = Request.Builder().url(url.toString()).get().build()
val urlMangas =
Uri.parse("$apiUrl/mangas").buildUpon().appendPath(track.media_id.toString())
val urlMangas ="$apiUrl/mangas".toUri().buildUpon().appendPath(track.media_id.toString())
.build()
val requestMangas = Request.Builder().url(urlMangas.toString()).get().build()
@ -171,7 +171,7 @@ class ShikimoriApi(private val client: OkHttpClient, interceptor: ShikimoriInter
return "$baseMangaUrl/$remoteId"
}
fun authUrl() = Uri.parse(loginUrl).buildUpon().appendQueryParameter("client_id", clientId)
fun authUrl() = loginUrl.toUri().buildUpon().appendQueryParameter("client_id", clientId)
.appendQueryParameter("redirect_uri", redirectUrl)
.appendQueryParameter("response_type", "code").build()

@ -7,6 +7,7 @@ import android.content.Intent
import android.content.IntentFilter
import android.net.Uri
import android.os.Environment
import androidx.core.net.toUri
import com.jakewharton.rxrelay.PublishRelay
import eu.kanade.tachiyomi.extension.model.Extension
import eu.kanade.tachiyomi.extension.model.InstallStep
@ -63,7 +64,7 @@ internal class ExtensionInstaller(private val context: Context) {
// Register the receiver after removing (and unregistering) the previous download
downloadReceiver.register()
val downloadUri = Uri.parse(url)
val downloadUri = url.toUri()
val request = DownloadManager.Request(downloadUri)
.setTitle(extension.name)
.setMimeType(APK_MIME)
@ -141,7 +142,7 @@ internal class ExtensionInstaller(private val context: Context) {
* @param pkgName The package name of the extension to uninstall
*/
fun uninstallApk(pkgName: String) {
val packageUri = Uri.parse("package:$pkgName")
val packageUri = "package:$pkgName".toUri()
val intent = Intent(Intent.ACTION_UNINSTALL_PACKAGE, packageUri)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)

@ -31,17 +31,19 @@ import java.util.zip.ZipFile
class LocalSource(private val context: Context) : CatalogueSource {
companion object {
const val ID = 0L
const val HELP_URL = "https://tachiyomi.org/help/guides/reading-local-manga/"
private const val COVER_NAME = "cover.jpg"
private val SUPPORTED_ARCHIVE_TYPES = setOf("zip", "rar", "cbr", "cbz", "epub")
private val POPULAR_FILTERS = FilterList(OrderBy())
private val LATEST_FILTERS =
FilterList(OrderBy().apply { state = Filter.Sort.Selection(1, false) })
private val LATEST_THRESHOLD = TimeUnit.MILLISECONDS.convert(7, TimeUnit.DAYS)
const val ID = 0L
fun updateCover(context: Context, manga: SManga, input: InputStream): File? {
val dir = getBaseDirectories(context).firstOrNull()
val dir = getBaseDirectories(context).asSequence().firstOrNull()
if (dir == null) {
input.close()
return null
@ -85,12 +87,12 @@ class LocalSource(private val context: Context) : CatalogueSource {
val time =
if (filters === LATEST_FILTERS) System.currentTimeMillis() - LATEST_THRESHOLD else 0L
var mangaDirs = baseDirs.mapNotNull { it.listFiles()?.toList() }.flatten().filter {
it.isDirectory && if (time == 0L) it.name.contains(
query,
ignoreCase = true
) else it.lastModified() >= time
}.distinctBy { it.name }
var mangaDirs = baseDirs
.asSequence()
.mapNotNull { it.listFiles()?.toList() }.flatten()
.filter { it.isDirectory }
.filter { if (time == 0L) it.name.contains(query, ignoreCase = true) else it.lastModified() >= time }
.distinctBy { it.name }
val state = ((if (filters.isEmpty()) POPULAR_FILTERS else filters)[0] as OrderBy).state
when (state?.index) {
@ -134,15 +136,17 @@ class LocalSource(private val context: Context) : CatalogueSource {
}
}
}
return Observable.just(MangasPage(mangas, false))
return Observable.just(MangasPage(mangas.toList(), false))
}
override fun fetchLatestUpdates(page: Int) = fetchSearchManga(page, "", LATEST_FILTERS)
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
val baseDirs = getBaseDirectories(context)
baseDirs.mapNotNull { File(it, manga.url).listFiles()?.toList() }
.flatten().filter { it.extension == "json" }.firstOrNull()?.apply {
baseDirs
.mapNotNull { File(it, manga.url).listFiles()?.toList() }
.flatten()
.filter { it.extension == "json" }.firstOrNull()?.apply {
val json = Gson().fromJson(
Scanner(this).useDelimiter("\\Z").next(),
JsonObject::class.java
@ -155,6 +159,7 @@ class LocalSource(private val context: Context) : CatalogueSource {
?: manga.genre
manga.status = json["status"]?.asInt ?: manga.status
}
val url = manga.url
// Try to find the cover
for (dir in baseDirs) {
@ -249,7 +254,7 @@ class LocalSource(private val context: Context) : CatalogueSource {
}
private fun isSupportedFile(extension: String): Boolean {
return extension.toLowerCase() in setOf("zip", "rar", "cbr", "cbz", "epub")
return extension.toLowerCase() in SUPPORTED_ARCHIVE_TYPES
}
fun getFormat(chapter: SChapter): Format {
@ -283,10 +288,11 @@ class LocalSource(private val context: Context) : CatalogueSource {
val format = getFormat(chapter)
return when (format) {
is Format.Directory -> {
val entry = format.file.listFiles().sortedWith(Comparator<File> { f1, f2 ->
val entry = format.file.listFiles()
?.sortedWith(Comparator<File> { f1, f2 ->
f1.name.compareToCaseInsensitiveNaturalOrder(f2.name)
})
.find { !it.isDirectory && ImageUtil.isImage(it.name) { FileInputStream(it) } }
?.find { !it.isDirectory && ImageUtil.isImage(it.name) { FileInputStream(it) } }
entry?.let { updateCover(context, manga, it.inputStream()) }
}

@ -5,6 +5,7 @@ import android.net.Uri
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import androidx.core.net.toUri
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
@ -117,7 +118,7 @@ class TrackingBottomSheet(private val controller: MangaDetailsController) : Bott
if (track.tracking_url.isBlank()) {
activity.toast(R.string.url_not_set_click_again)
} else {
activity.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(track.tracking_url)))
activity.startActivity(Intent(Intent.ACTION_VIEW, track.tracking_url.toUri()))
controller.refreshTracker = position
}
}

@ -18,6 +18,7 @@ import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.net.toUri
import coil.api.loadAny
import coil.request.CachePolicy
import com.davemorrissey.labs.subscaleview.ImageSource
@ -465,7 +466,7 @@ class PagerPageHolder(
}
setText(R.string.open_in_browser)
setOnClickListener {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(imageUrl))
val intent = Intent(Intent.ACTION_VIEW, imageUrl.toUri())
context.startActivity(intent)
}

@ -15,6 +15,7 @@ import android.widget.LinearLayout
import android.widget.TextView
import androidx.appcompat.widget.AppCompatButton
import androidx.appcompat.widget.AppCompatImageView
import androidx.core.net.toUri
import coil.api.clear
import coil.api.loadAny
import coil.request.CachePolicy
@ -458,7 +459,7 @@ class WebtoonPageHolder(
}
setText(R.string.open_in_browser)
setOnClickListener {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(imageUrl))
val intent = Intent(Intent.ACTION_VIEW, imageUrl.toUri())
context.startActivity(intent)
}

@ -33,7 +33,7 @@ class BiometricActivity : BaseActivity() {
val promptInfo = BiometricPrompt.PromptInfo.Builder()
.setTitle(getString(R.string.unlock_library))
.setNegativeButtonText(getString(android.R.string.cancel))
.setDeviceCredentialAllowed(true)
.build()
biometricPrompt.authenticate(promptInfo)

@ -4,6 +4,7 @@ import android.app.Dialog
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import androidx.core.net.toUri
import androidx.preference.PreferenceScreen
import com.afollestad.materialdialogs.MaterialDialog
import com.google.android.gms.oss.licenses.OssLicensesMenuActivity
@ -58,7 +59,7 @@ class AboutController : SettingsController() {
val url = "https://tachiyomi.org"
summary = url
onClick {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
val intent = Intent(Intent.ACTION_VIEW, url.toUri())
startActivity(intent)
}
}
@ -68,7 +69,7 @@ class AboutController : SettingsController() {
val url = "https://discord.gg/tachiyomi"
summary = url
onClick {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
val intent = Intent(Intent.ACTION_VIEW, url.toUri())
startActivity(intent)
}
}
@ -77,7 +78,7 @@ class AboutController : SettingsController() {
val url = "https://github.com/Jays2Kings/tachiyomiJ2K"
summary = url
onClick {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
val intent = Intent(Intent.ACTION_VIEW, url.toUri())
startActivity(intent)
}
}
@ -86,13 +87,12 @@ class AboutController : SettingsController() {
titleRes = R.string.whats_new
onClick {
val intent = Intent(
Intent.ACTION_VIEW, Uri.parse(
Intent.ACTION_VIEW,
if (BuildConfig.DEBUG) {
"https://github.com/Jays2Kings/tachiyomiJ2K/commits/master"
} else {
"https://github.com/Jays2Kings/tachiyomiJ2K/releases/tag/v${BuildConfig.VERSION_NAME}"
}
)
}.toUri()
)
startActivity(intent)
}

@ -10,6 +10,7 @@ import android.os.Bundle
import android.os.PowerManager
import android.provider.Settings
import android.widget.Toast
import androidx.core.net.toUri
import androidx.preference.PreferenceScreen
import com.afollestad.materialdialogs.MaterialDialog
import eu.kanade.tachiyomi.R
@ -122,7 +123,7 @@ class SettingsAdvancedController : SettingsController() {
if (!pm.isIgnoringBatteryOptimizations(packageName)) {
val intent = Intent().apply {
action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
data = Uri.parse("package:$packageName")
data = "package:$packageName".toUri()
}
startActivity(intent)
} else {

@ -8,6 +8,7 @@ import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.View
import androidx.core.net.toUri
import androidx.preference.PreferenceScreen
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.list.listItemsMultiChoice
@ -102,7 +103,7 @@ class SettingsBackupController : SettingsController() {
preferences.backupsDirectory().asObservable()
.subscribeUntilDestroy { path ->
val dir = UniFile.fromUri(context, Uri.parse(path))
val dir = UniFile.fromUri(context, path.toUri())
summary = dir.filePath + "/automatic"
}
}

@ -8,6 +8,7 @@ import android.net.Uri
import android.os.Bundle
import android.os.Environment
import androidx.core.content.ContextCompat
import androidx.core.net.toUri
import androidx.preference.PreferenceScreen
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.list.listItemsSingleChoice
@ -42,7 +43,7 @@ class SettingsDownloadController : SettingsController() {
preferences.downloadsDirectory().asObservable()
.subscribeUntilDestroy { path ->
val dir = UniFile.fromUri(context, Uri.parse(path))
val dir = UniFile.fromUri(context, path.toUri())
summary = dir.filePath ?: path
}
}

@ -25,6 +25,7 @@ import androidx.annotation.StringRes
import androidx.browser.customtabs.CustomTabsIntent
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import androidx.core.net.toUri
import com.nononsenseapps.filepicker.FilePickerActivity
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.widget.CustomLayoutPickerActivity
@ -223,7 +224,7 @@ fun Context.isServiceRunning(serviceClass: Class<*>): Boolean {
*/
fun Context.openInBrowser(url: String) {
try {
val parsedUrl = Uri.parse(url)
val parsedUrl = url.toUri()
val intent = CustomTabsIntent.Builder()
.setToolbarColor(getResourceColor(R.attr.colorPrimaryVariant))
.build()

Loading…
Cancel
Save