Dependency update / Dropped features that supports <Android 21 / Dropped support for hiyobi.me

This commit is contained in:
tom5079
2021-05-15 06:43:14 +09:00
parent 00c8078642
commit 51851addc1
21 changed files with 64 additions and 268 deletions

2
.idea/compiler.xml generated
View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="1.8" />
<bytecodeTargetLevel target="11" />
</component>
</project>

1
.idea/gradle.xml generated
View File

@@ -14,7 +14,6 @@
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
<option name="useQualifiedModuleNames" value="true" />
</GradleProjectSettings>
</option>
</component>

2
.idea/misc.xml generated
View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">

View File

@@ -3,6 +3,7 @@
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />

View File

@@ -14,23 +14,6 @@ if (file("google-services.json").exists()) {
logger.lifecycle("Firebase Disabled")
}
ext {
okhttp_version = "3.12.12"
}
configurations {
all {
resolutionStrategy {
eachDependency { DependencyResolveDetails details ->
if (details.requested.group == "com.squareup.okhttp3" && details.requested.name == "okhttp") {
// OkHttp drops support before 5.0 since 3.13.0
details.useVersion okhttp_version
}
}
}
}
}
android {
compileSdkVersion 30
defaultConfig {
@@ -75,7 +58,6 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildToolsVersion = "29.0.3"
lintOptions {
abortOnError false
@@ -84,27 +66,27 @@ android {
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar", "*.aar"])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.1"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.5.0"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0-RC"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.0"
implementation "androidx.appcompat:appcompat:1.2.0"
implementation "androidx.activity:activity-ktx:1.3.0-alpha05"
implementation "androidx.fragment:fragment-ktx:1.3.2"
implementation "androidx.activity:activity-ktx:1.3.0-alpha07"
implementation "androidx.fragment:fragment-ktx:1.3.3"
implementation "androidx.preference:preference-ktx:1.1.1"
implementation "androidx.recyclerview:recyclerview:1.1.0"
implementation "androidx.recyclerview:recyclerview:1.2.0"
implementation "androidx.constraintlayout:constraintlayout:2.0.4"
implementation "androidx.gridlayout:gridlayout:1.0.0"
implementation "androidx.biometric:biometric:1.1.0"
implementation "androidx.work:work-runtime-ktx:2.5.0"
implementation "androidx.work:work-runtime-ktx:2.6.0-alpha02"
implementation 'org.kodein.di:kodein-di-framework-android-x:7.4.0'
implementation 'org.kodein.di:kodein-di-framework-android-x:7.5.0'
implementation "com.daimajia.swipelayout:library:1.2.0@aar"
implementation "com.google.android.material:material:1.3.0"
implementation platform("com.google.firebase:firebase-bom:26.1.0")
implementation platform("com.google.firebase:firebase-bom:28.0.0")
implementation "com.google.firebase:firebase-analytics-ktx"
implementation "com.google.firebase:firebase-crashlytics"
implementation "com.google.firebase:firebase-perf"
@@ -115,26 +97,23 @@ dependencies {
//implementation "com.quiph.ui:recyclerviewfastscroller:0.2.1"
implementation 'com.github.piasy:BigImageViewer:1.7.0'
implementation 'com.github.piasy:FrescoImageLoader:1.7.0'
implementation 'com.github.piasy:FrescoImageViewFactory:1.7.0'
implementation 'com.github.piasy:BigImageViewer:1.8.0'
implementation 'com.github.piasy:FrescoImageLoader:1.8.0'
implementation 'com.github.piasy:FrescoImageViewFactory:1.8.0'
//noinspection GradleDependency
implementation "com.squareup.okhttp3:okhttp:$okhttp_version"
implementation "com.squareup.okhttp3:okhttp:4.9.0"
implementation "com.tbuonomo.andrui:viewpagerdotsindicator:4.1.2"
implementation "com.tbuonomo:dotsindicator:4.2"
implementation "net.rdrei.android.dirchooser:library:3.2@aar"
implementation "com.gu:option:1.3"
implementation "com.andrognito.patternlockview:patternlockview:1.0.0"
//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.9.7"
implementation "xyz.quaver:documentfilex:0.5-SNAPSHOT"
implementation "xyz.quaver:floatingsearchview:1.1.3-SNAPSHOT"
implementation "xyz.quaver:libpupil:2.0.0"
implementation "xyz.quaver:documentfilex:0.6.1"
implementation "xyz.quaver:floatingsearchview:1.1.7"
implementation "com.orhanobut:logger:2.2.0"

Binary file not shown.

View File

@@ -143,8 +143,7 @@ val sourceModule = DI.Module(name = "source") {
bind() from setBinding<SourceEntry>()
listOf(
Hitomi(),
Hiyobi()
Hitomi()
).forEach { source ->
bind<SourceEntry>().inSet() with multiton { _: Unit -> source.name to (source as AnySource) }
}

View File

@@ -227,7 +227,7 @@ class Hitomi : Source<Hitomi.SortMode, Hitomi.TagSuggestion>() {
}.getOrDefault("") },
ExtraType.SERIES to CoroutineScope(Dispatchers.Unconfined).async { galleryBlock.series.joinToString { it.wordCapitalize() } },
ExtraType.TYPE to CoroutineScope(Dispatchers.Unconfined).async { galleryBlock.type.wordCapitalize() },
ExtraType.LANGUAGE to CoroutineScope(Dispatchers.Unconfined).async { galleryBlock.language },
ExtraType.LANGUAGE to CoroutineScope(Dispatchers.Unconfined).async { languageMap[galleryBlock.language] },
ExtraType.PAGECOUNT to CoroutineScope(Dispatchers.IO).async { kotlin.runCatching {
getGalleryInfo(galleryBlock.id).files.size.toString()
}.getOrNull() },

View File

@@ -1,140 +0,0 @@
/*
* 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.sources
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import okhttp3.Request
import xyz.quaver.floatingsearchview.databinding.SearchSuggestionItemBinding
import xyz.quaver.hiyobi.*
import xyz.quaver.pupil.R
import xyz.quaver.pupil.client
import xyz.quaver.pupil.util.wordCapitalize
import java.io.IOException
import java.util.*
class Hiyobi : Source<DefaultSortMode, DefaultSearchSuggestion>() {
override val name: String = "hiyobi.me"
override val iconResID: Int = R.drawable.ic_hiyobi
override val availableSortMode: Array<DefaultSortMode> = DefaultSortMode.values()
override suspend fun search(query: String, range: IntRange, sortMode: Enum<*>): Pair<Channel<ItemInfo>, Int> {
val channel = Channel<ItemInfo>()
val (results, total) = if (query.isEmpty())
list(range)
else
search(query.trim(), range)
CoroutineScope(Dispatchers.Unconfined).launch {
results.forEach {
channel.send(transform(name, it))
}
channel.close()
}
return Pair(channel, total)
}
override suspend fun suggestion(query: String): List<DefaultSearchSuggestion> {
val result = mutableSetOf<String>()
for (tag in allTags.await()) {
if (result.size >= 10)
break
val lowQuery = query.toLowerCase(Locale.ROOT)
if (tag.contains(lowQuery, true))
result.add(tag)
}
return result.map { DefaultSearchSuggestion(it) }
}
override suspend fun images(itemID: String): List<String> {
return createImgList(itemID, getGalleryInfo(itemID), true).map {
it.path
}
}
override suspend fun info(itemID: String): ItemInfo {
return transform(name, getGalleryBlock(itemID))
}
override fun onSuggestionBind(binding: SearchSuggestionItemBinding, item: DefaultSearchSuggestion) {
val split = item.body.split(':', limit = 2)
if (split.size != 2)
return
binding.leftIcon.setImageResource(
when(split.first()) {
"female" -> R.drawable.gender_female
"male" -> R.drawable.gender_male
"language" -> R.drawable.translate
"group" -> R.drawable.account_group
"character" -> R.drawable.account_star
"series" -> R.drawable.book_open
"artist" -> R.drawable.brush
else -> R.drawable.tag
}
)
binding.body.text = split.last()
}
companion object {
private fun downloadAllTagsAsync(): Deferred<List<String>> = CoroutineScope(Dispatchers.IO).async {
Json.decodeFromString(kotlin.runCatching {
client.newCall(Request.Builder().url("https://api.hiyobi.me/auto.json").build()).execute().also { if (it.code() != 200) throw IOException() }.body()?.use { it.string() }
}.getOrNull() ?: "[]")
}
private var _allTags: Deferred<List<String>>? = null
val allTags: Deferred<List<String>>
get() = if (_allTags == null || (_allTags!!.isCompleted && runBlocking { _allTags!!.await() }.isEmpty())) downloadAllTagsAsync().also {
_allTags = it
} else _allTags!!
suspend fun transform(name: String, galleryBlock: GalleryBlock): ItemInfo = withContext(Dispatchers.IO) {
ItemInfo(
name,
galleryBlock.id,
galleryBlock.title,
"https://cdn.$hiyobi/tn/${galleryBlock.id}.jpg",
galleryBlock.artists.joinToString { it.value.wordCapitalize() },
mapOf(
ItemInfo.ExtraType.CHARACTER to async { galleryBlock.characters.joinToString { it.value.wordCapitalize() } },
ItemInfo.ExtraType.SERIES to async { galleryBlock.parodys.joinToString { it.value.wordCapitalize() } },
ItemInfo.ExtraType.TYPE to async { galleryBlock.type.name.replace('_', ' ').wordCapitalize() },
ItemInfo.ExtraType.PAGECOUNT to async { getGalleryInfo(galleryBlock.id).files.size.toString() },
ItemInfo.ExtraType.GROUP to async { galleryBlock.groups.joinToString { it.value.wordCapitalize() } },
ItemInfo.ExtraType.TAGS to async { galleryBlock.tags.joinToString() { it.value } }
)
)
}
}
}

View File

@@ -29,8 +29,6 @@ import androidx.core.content.ContextCompat
import androidx.core.net.toUri
import androidx.fragment.app.DialogFragment
import com.google.android.material.snackbar.Snackbar
import net.rdrei.android.dirchooser.DirectoryChooserActivity
import net.rdrei.android.dirchooser.DirectoryChooserConfig
import org.kodein.di.DIAware
import org.kodein.di.android.x.di
import org.kodein.di.instance
@@ -63,8 +61,7 @@ class DownloadLocationDialogFragment : DialogFragment(), DIAware {
it.data?.data?.let { uri ->
val takeFlags: Int = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
context.contentResolver.takePersistableUriPermission(uri, takeFlags)
context.contentResolver.takePersistableUriPermission(uri, takeFlags)
if (kotlin.runCatching { FileX(context, uri).canWrite() }.getOrDefault(false)) {
entries[null]?.locationAvailable?.text = uri.toFile(context)?.canonicalPath
@@ -85,32 +82,6 @@ class DownloadLocationDialogFragment : DialogFragment(), DIAware {
}
}
private val requestDownloadFolderOldLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
val context = context ?: return@registerForActivityResult
val dialog = dialog ?: return@registerForActivityResult
if (it.resultCode == DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED) {
val directory = it.data?.getStringExtra(DirectoryChooserActivity.RESULT_SELECTED_DIR)!!
if (!File(directory).canWrite()) {
Snackbar.make(
dialog.window!!.decorView.rootView,
R.string.settings_download_folder_not_writable,
Snackbar.LENGTH_LONG
).show()
val downloadFolder = downloadManager.downloadFolder.canonicalPath
val key = entries.keys.firstOrNull { it?.canonicalPath == downloadFolder }
entries[key]!!.button.isChecked = true
if (key == null) entries[key]!!.locationAvailable.text = downloadFolder
}
else {
entries[null]?.locationAvailable?.text = directory
Preferences["download_folder"] = File(directory).toURI().toString()
}
}
}
private fun initView() {
val externalFilesDirs = ContextCompat.getExternalFilesDirs(requireContext(), null)
@@ -145,29 +116,16 @@ class DownloadLocationDialogFragment : DialogFragment(), DIAware {
}
button.performClick()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply {
addFlags(
Intent.FLAG_GRANT_READ_URI_PERMISSION
or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
or Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
)
putExtra("android.content.extra.SHOW_ADVANCED", true)
}
requestDownloadFolderLauncher.launch(intent)
} else { // Can't use SAF on old Androids!
val config = DirectoryChooserConfig.builder()
.newDirectoryName("Pupil")
.allowNewDirectoryNameModification(true)
.build()
val intent = Intent(context, DirectoryChooserActivity::class.java).apply {
putExtra(DirectoryChooserActivity.EXTRA_CONFIG, config)
}
requestDownloadFolderOldLauncher.launch(intent)
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply {
addFlags(
Intent.FLAG_GRANT_READ_URI_PERMISSION
or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
or Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
)
putExtra("android.content.extra.SHOW_ADVANCED", true)
}
requestDownloadFolderLauncher.launch(intent)
}
entries[null] = this
}

View File

@@ -26,6 +26,7 @@ import androidx.fragment.app.DialogFragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import org.kodein.di.*
import org.kodein.di.android.x.closestDI
import org.kodein.di.android.x.di
import org.kodein.type.jvmType
import xyz.quaver.floatingsearchview.suggestions.model.SearchSuggestion
@@ -36,7 +37,7 @@ import xyz.quaver.pupil.sources.SourceEntries
class SourceSelectDialog : DialogFragment(), DIAware {
override val di by di()
override val di by closestDI()
var onSourceSelectedListener: ((String) -> Unit)? = null

View File

@@ -29,6 +29,7 @@ import androidx.preference.PreferenceFragmentCompat
import com.google.android.material.snackbar.Snackbar
import okhttp3.*
import org.kodein.di.DIAware
import org.kodein.di.android.x.closestDI
import org.kodein.di.android.x.di
import xyz.quaver.pupil.R
import xyz.quaver.pupil.client
@@ -38,7 +39,7 @@ import java.io.IOException
class ManageFavoritesFragment : PreferenceFragmentCompat(), DIAware {
override val di by di()
override val di by closestDI()
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.manage_favorites_preferences, rootKey)
@@ -65,14 +66,14 @@ class ManageFavoritesFragment : PreferenceFragmentCompat(), DIAware {
}
override fun onResponse(call: Call, response: Response) {
if (response.code() != 200) {
if (response.code != 200) {
response.close()
return
}
Intent(Intent.ACTION_SEND).apply {
type = "text/plain"
putExtra(Intent.EXTRA_TEXT, response.body()?.use { it.string() }?.replace("\n", ""))
putExtra(Intent.EXTRA_TEXT, response.body?.use { it.string() }?.replace("\n", ""))
}.let {
getContext()?.startActivity(Intent.createChooser(it, getString(R.string.settings_backup_share)))
}

View File

@@ -41,7 +41,7 @@ import xyz.quaver.pupil.types.NoResultSuggestion
import java.util.*
class FloatingSearchView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
FloatingSearchView(context, attrs),
xyz.quaver.floatingsearchview.FloatingSearchView(context, attrs),
FloatingSearchView.OnSearchListener,
TextWatcher
{

View File

@@ -26,6 +26,7 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.*
import okhttp3.Headers
import okhttp3.Headers.Companion.toHeaders
import okhttp3.Request
import org.kodein.di.DIAware
import org.kodein.di.android.x.di
@@ -73,7 +74,7 @@ class ReaderViewModel(app: Application) : AndroidViewModel(app), DIAware {
val file = cache.load(
Request.Builder()
.url(image)
.headers(Headers.of(source.getHeadersForImage(itemID, image)))
.headers(source.getHeadersForImage(itemID, image).toHeaders())
.build()
)

View File

@@ -62,8 +62,8 @@ class ImageCache(context: Context) : DIAware {
}
fun free(images: List<String>) {
client.dispatcher().let { it.queuedCalls() + it.runningCalls() }
.filter { it.request().url().toString() in images }
client.dispatcher.let { it.queuedCalls() + it.runningCalls() }
.filter { it.request().url.toString() in images }
.forEach { it.cancel() }
images.forEach { _channels.remove(it) }
@@ -71,7 +71,7 @@ class ImageCache(context: Context) : DIAware {
@Synchronized
suspend fun clear() = coroutineScope {
client.dispatcher().queuedCalls().forEach { it.cancel() }
client.dispatcher.queuedCalls().forEach { it.cancel() }
cacheFolder.listFiles()?.forEach { it.delete() }
cache.clear()
@@ -79,7 +79,7 @@ class ImageCache(context: Context) : DIAware {
@OptIn(ExperimentalCoroutinesApi::class)
fun load(request: Request): File {
val key = request.url().toString()
val key = request.url.toString()
val channel = if (_channels[key]?.isClosedForSend == false)
_channels[key]!!
@@ -93,16 +93,16 @@ class ImageCache(context: Context) : DIAware {
client.newCall(request).enqueue(object: Callback {
override fun onFailure(call: Call, e: IOException) {
file.delete()
cache.remove(call.request().url().toString())
cache.remove(call.request().url.toString())
FirebaseCrashlytics.getInstance().recordException(e)
channel.close(e)
}
override fun onResponse(call: Call, response: Response) {
if (response.code() != 200) {
if (response.code != 200) {
file.delete()
cache.remove(call.request().url().toString())
cache.remove(call.request().url.toString())
channel.close(IOException("HTTP Response code is not 200"))
@@ -110,7 +110,7 @@ class ImageCache(context: Context) : DIAware {
return
}
response.body()?.use { body ->
response.body?.use { body ->
if (!file.exists())
file.createNewFile()

View File

@@ -46,7 +46,7 @@ data class ProxyInfo(
Authenticator { _, response ->
val credential = Credentials.basic(username, password)
response.request().newBuilder()
response.request.newBuilder()
.header("Proxy-Authorization", credential)
.build()
}

View File

@@ -44,10 +44,10 @@ fun updateTranslations() = CoroutineScope(Dispatchers.IO).launch {
translations = emptyMap()
kotlin.runCatching {
translations = Json.decodeFromString<Map<String, String>>(client.newCall(
Request.Builder()
.url(contentURL + "${Preferences["tag_translation", ""].let { if (it.isEmpty()) Locale.getDefault().language else it }}.json")
.build()
).execute().also { if (it.code() != 200) return@launch }.body()?.use { it.string() } ?: return@launch).filterValues { it.isNotEmpty() }
Request.Builder()
.url(contentURL + "${Preferences["tag_translation", ""].let { if (it.isEmpty()) Locale.getDefault().language else it }}.json")
.build()
).execute().also { if (it.code != 200) return@launch }.body?.use { it.string() } ?: return@launch).filterValues { it.isNotEmpty() }
}
}
@@ -58,7 +58,7 @@ fun getAvailableLanguages(): List<String> {
Request.Builder()
.url(filesURL)
.build()
).execute().also { if (it.code() != 200) throw IOException() }.body()?.use { it.string() } ?: return emptyList())
).execute().also { if (it.code != 200) throw IOException() }.body?.use { it.string() } ?: return emptyList())
return listOf("en") + (json["tree"]?.jsonArray?.mapNotNull {
val name = it["path"]?.jsonPrimitive?.content?.takeWhile { c -> c != '.' }

View File

@@ -199,7 +199,7 @@ fun restore(context: Context, url: String, onFailure: ((Throwable) -> Unit)? = n
override fun onResponse(call: Call, response: Response) {
val favorites = object: DIAware { override val di by di(context); val favorites: SavedSourceSet by instance(tag = "favorites") }
kotlin.runCatching {
Json.decodeFromString<Set<String>>(response.also { if (it.code() != 200) throw IOException() }.body().use { it?.string() } ?: "[]").let {
Json.decodeFromString<Set<String>>(response.also { if (it.code != 200) throw IOException() }.body.use { it?.string() } ?: "[]").let {
favorites.favorites.addAll(mapOf("hitomi.la" to it))
onSuccess?.invoke(it)
}

View File

@@ -3,32 +3,29 @@
buildscript {
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.3'
classpath 'com.android.tools.build:gradle:4.2.1'
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"
classpath "com.google.gms:google-services:4.3.5"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
classpath "com.google.firebase:firebase-crashlytics-gradle:2.5.2"
classpath "com.google.firebase:perf-plugin:1.3.5"
classpath "com.google.android.gms:oss-licenses-plugin:0.10.2"
classpath "com.google.firebase:firebase-crashlytics-gradle:2.6.0"
classpath "com.google.firebase:perf-plugin:1.4.0"
classpath "com.google.android.gms:oss-licenses-plugin:0.10.4"
}
}
allprojects {
repositories {
maven { url "https://dl.bintray.com/piasy/maven" }
google()
mavenCentral()
jcenter()
mavenLocal()
maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
maven { url "https://jitpack.io" }
maven { url "https://guardian.github.com/maven/repo-releases" }
}
}

View File

@@ -21,4 +21,4 @@ android.enableJetifier=true
android.useAndroidX=true
android.enableBuildCache=true
kotlin_version=1.4.32
kotlin_version=1.5.0

View File

@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip