mirror of
https://github.com/sudoxnym/habitica-android.git
synced 2026-04-14 11:46:32 +00:00
Fix a lot of warnings
This commit is contained in:
parent
efa21e28c0
commit
a78e5c0034
56 changed files with 195 additions and 302 deletions
|
|
@ -46,17 +46,18 @@ dependencies {
|
|||
implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'
|
||||
|
||||
//Dependency Injection
|
||||
implementation 'com.google.dagger:dagger:2.40.5'
|
||||
kapt 'com.google.dagger:dagger-compiler:2.40.5'
|
||||
implementation 'com.google.dagger:dagger:2.42'
|
||||
kapt 'com.google.dagger:dagger-compiler:2.42'
|
||||
compileOnly 'javax.annotation:javax.annotation-api:1.3.2'
|
||||
//App Compatibility and Material Design
|
||||
implementation 'androidx.appcompat:appcompat:1.4.1'
|
||||
implementation 'com.google.android.material:material:1.5.0'
|
||||
implementation 'com.google.android.material:material:1.6.0'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.2.1'
|
||||
implementation "androidx.preference:preference:1.2.0"
|
||||
implementation "androidx.preference:preference-ktx:1.2.0"
|
||||
|
||||
//Desugaring
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.9'
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
|
||||
|
||||
// Markdown
|
||||
implementation "io.noties.markwon:core:4.6.2"
|
||||
|
|
@ -69,13 +70,13 @@ dependencies {
|
|||
// IAP Handling / Verification
|
||||
implementation "com.android.billingclient:billing-ktx:4.1.0"
|
||||
//Facebook
|
||||
implementation('com.facebook.android:facebook-android-sdk:12.2.0') {
|
||||
implementation('com.facebook.android:facebook-android-sdk:13.2.0') {
|
||||
transitive = true
|
||||
}
|
||||
implementation 'fr.avianey.com.viewpagerindicator:library:2.4.1@aar'
|
||||
//RxJava
|
||||
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
|
||||
implementation 'io.reactivex.rxjava3:rxjava:3.1.3'
|
||||
implementation 'io.reactivex.rxjava3:rxjava:3.1.4'
|
||||
implementation 'io.reactivex.rxjava3:rxkotlin:3.0.1'
|
||||
implementation 'io.reactivex.rxjava2:rxjava:2.2.21'
|
||||
implementation "com.github.akarnokd:rxjava3-bridge:3.0.2"
|
||||
|
|
@ -87,13 +88,13 @@ dependencies {
|
|||
implementation("io.coil-kt:coil-gif:1.4.0")
|
||||
|
||||
//Tests
|
||||
testImplementation 'io.kotest:kotest-runner-junit5:5.0.3'
|
||||
testImplementation 'io.kotest:kotest-runner-junit5:5.3.0'
|
||||
testImplementation 'androidx.test:core:1.4.0'
|
||||
testImplementation "io.mockk:mockk:1.12.2"
|
||||
testImplementation "io.mockk:mockk-android:1.12.2"
|
||||
testImplementation 'io.kotest:kotest-assertions-core:5.0.3'
|
||||
testImplementation 'io.kotest:kotest-framework-datatest:4.6.2'
|
||||
androidTestImplementation ('com.kaspersky.android-components:kaspresso:1.4.0') {
|
||||
testImplementation 'io.mockk:mockk:1.12.3'
|
||||
testImplementation 'io.mockk:mockk-android:1.12.3'
|
||||
testImplementation 'io.kotest:kotest-assertions-core:5.3.0'
|
||||
testImplementation 'io.kotest:kotest-framework-datatest:5.3.0'
|
||||
androidTestImplementation ('com.kaspersky.android-components:kaspresso:1.4.1') {
|
||||
exclude module: "protobuf-lite"
|
||||
}
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
|
|
@ -103,8 +104,8 @@ dependencies {
|
|||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||
androidTestImplementation 'androidx.test:core-ktx:1.4.0'
|
||||
androidTestImplementation 'androidx.test.ext:junit-ktx:1.1.3'
|
||||
androidTestImplementation "io.mockk:mockk-android:1.12.2"
|
||||
androidTestImplementation 'io.kotest:kotest-assertions-core:5.0.3'
|
||||
androidTestImplementation 'io.mockk:mockk-android:1.12.3'
|
||||
androidTestImplementation 'io.kotest:kotest-assertions-core:5.3.0'
|
||||
androidTestUtil("androidx.test:orchestrator:1.4.1")
|
||||
|
||||
implementation 'androidx.activity:activity-compose:1.4.0'
|
||||
|
|
@ -115,9 +116,9 @@ dependencies {
|
|||
implementation "com.google.accompanist:accompanist-appcompat-theme:0.16.0"
|
||||
|
||||
//Leak Detection
|
||||
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.8'
|
||||
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1'
|
||||
//Push Notifications
|
||||
implementation platform('com.google.firebase:firebase-bom:29.0.0')
|
||||
implementation platform('com.google.firebase:firebase-bom:30.0.0')
|
||||
implementation 'com.google.firebase:firebase-crashlytics-ktx'
|
||||
implementation 'com.google.firebase:firebase-core'
|
||||
implementation 'com.google.firebase:firebase-messaging-ktx'
|
||||
|
|
@ -135,19 +136,19 @@ dependencies {
|
|||
implementation 'androidx.navigation:navigation-ui-ktx:2.4.2'
|
||||
implementation "androidx.fragment:fragment-ktx:1.4.1"
|
||||
implementation "androidx.paging:paging-runtime-ktx:3.1.1"
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1'
|
||||
|
||||
implementation 'com.willowtreeapps:signinwithapplebutton:0.3'
|
||||
|
||||
implementation project(':shared')
|
||||
|
||||
ktlint("com.pinterest:ktlint:0.45.0") {
|
||||
ktlint('com.pinterest:ktlint:0.45.2') {
|
||||
attributes {
|
||||
attribute(Bundling.BUNDLING_ATTRIBUTE, getObjects().named(Bundling, Bundling.EXTERNAL))
|
||||
}
|
||||
}
|
||||
androidTestImplementation "org.jetbrains.kotlin:kotlin-reflect:1.6.20"
|
||||
androidTestImplementation "org.jetbrains.kotlin:kotlin-reflect:1.6.21"
|
||||
}
|
||||
|
||||
android {
|
||||
|
|
@ -168,7 +169,7 @@ android {
|
|||
buildConfigField "String", "TESTING_LEVEL", "\"production\""
|
||||
resConfigs 'en', 'bg', 'de', 'en-rGB', 'es', 'fr', 'hr-rHR', 'in', 'it', 'iw', 'ja', 'ko', 'lt', 'nl', 'pl', 'pt-rBR', 'pt-rPT', 'ru', 'tr', 'zh', 'zh-rTW'
|
||||
|
||||
versionCode 3501
|
||||
versionCode 3502
|
||||
versionName "3.6"
|
||||
|
||||
targetSdkVersion 32
|
||||
|
|
|
|||
|
|
@ -195,15 +195,6 @@
|
|||
android:layout_marginTop="@dimen/spacing_xlarge"
|
||||
style="@style/LoginButton"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/fb_login_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_marginTop="@dimen/spacing_xlarge"
|
||||
android:layout_height="@dimen/diamond_button_height"
|
||||
android:text="@string/login_btn_fb"
|
||||
android:drawableStart="@drawable/facebook_icon"
|
||||
style="@style/LoginButton"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/google_login_button"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<full-backup-content>
|
||||
<!-- TODO Remove the following "exclude" elements to make them a part of the auto backup -->
|
||||
<!-- Exclude the shared preferences file that contains the GCM registrationId -->
|
||||
<exclude
|
||||
domain="sharedpref"
|
||||
|
|
|
|||
|
|
@ -121,8 +121,9 @@ abstract class HabiticaBaseApplication : Application(), Application.ActivityLife
|
|||
val configuration: Configuration = resources.configuration
|
||||
val languageHelper = LanguageHelper(sharedPrefs.getString("language", "en"))
|
||||
if (if (SDK_INT >= Build.VERSION_CODES.N) {
|
||||
configuration.locales.isEmpty || configuration.locales[0] != languageHelper.locale
|
||||
} else {
|
||||
configuration.locales.isEmpty || configuration.locales[0] != languageHelper.locale
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
configuration.locale != languageHelper.locale
|
||||
}
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -248,7 +248,7 @@ interface ApiClient {
|
|||
fun retrieveInboxMessages(uuid: String, page: Int): Flowable<List<ChatMessage>>
|
||||
fun retrieveInboxConversations(): Flowable<List<InboxConversation>>
|
||||
|
||||
fun <T> configureApiCallObserver(): FlowableTransformer<HabitResponse<T>, T>
|
||||
fun <T : Any> configureApiCallObserver(): FlowableTransformer<HabitResponse<T>, T>
|
||||
|
||||
fun openMysteryItem(): Flowable<Equipment>
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ interface TaskRepository : BaseRepository {
|
|||
up: Boolean,
|
||||
force: Boolean,
|
||||
notifyFunc: ((TaskScoringResult) -> Unit)?
|
||||
): Maybe<TaskScoringResult?>
|
||||
): Maybe<TaskScoringResult>
|
||||
fun scoreChecklistItem(taskId: String, itemId: String): Flowable<Task>
|
||||
|
||||
fun getTask(taskId: String): Flowable<Task>
|
||||
|
|
|
|||
|
|
@ -50,8 +50,8 @@ interface UserRepository : BaseRepository {
|
|||
|
||||
fun changeClass(selectedClass: String): Flowable<User>
|
||||
|
||||
fun unlockPath(user: User?, path: String, price: Int): Flowable<UnlockResponse>
|
||||
fun unlockPath(user: User?, customization: Customization): Flowable<UnlockResponse>
|
||||
fun unlockPath(path: String, price: Int): Flowable<UnlockResponse>
|
||||
fun unlockPath(customization: Customization): Flowable<UnlockResponse>
|
||||
|
||||
fun runCron(tasks: MutableList<Task>)
|
||||
fun runCron()
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package com.habitrpg.android.habitica.data.implementation
|
|||
|
||||
import android.content.Context
|
||||
import com.amplitude.api.Amplitude
|
||||
import com.facebook.FacebookSdk.getCacheDir
|
||||
import com.google.gson.JsonSyntaxException
|
||||
import com.habitrpg.android.habitica.BuildConfig
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication
|
||||
|
|
@ -12,6 +11,7 @@ import com.habitrpg.android.habitica.api.GSonFactoryCreator
|
|||
import com.habitrpg.android.habitica.api.HostConfig
|
||||
import com.habitrpg.android.habitica.api.Server
|
||||
import com.habitrpg.android.habitica.data.ApiClient
|
||||
import com.habitrpg.android.habitica.extensions.filterMap
|
||||
import com.habitrpg.android.habitica.helpers.NotificationsManager
|
||||
import com.habitrpg.android.habitica.models.Achievement
|
||||
import com.habitrpg.android.habitica.models.ContentResult
|
||||
|
|
@ -66,6 +66,7 @@ import retrofit2.HttpException
|
|||
import retrofit2.Retrofit
|
||||
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.net.SocketException
|
||||
import java.net.SocketTimeoutException
|
||||
|
|
@ -89,8 +90,7 @@ class ApiClientImpl(
|
|||
|
||||
private val apiCallTransformer = FlowableTransformer<HabitResponse<Any>, Any> { observable ->
|
||||
observable
|
||||
.filter { it.data != null }
|
||||
.map { habitResponse ->
|
||||
.filterMap { habitResponse ->
|
||||
habitResponse.notifications?.let {
|
||||
notificationsManager.setNotifications(it)
|
||||
}
|
||||
|
|
@ -127,7 +127,7 @@ class ApiClientImpl(
|
|||
|
||||
val cacheSize: Long = 10 * 1024 * 1024 // 10 MB
|
||||
|
||||
val cache = getCacheDir()?.let { Cache(it, cacheSize) }
|
||||
val cache = Cache(File(context.cacheDir, "http_cache"), cacheSize)
|
||||
|
||||
val client = OkHttpClient.Builder()
|
||||
.cache(cache)
|
||||
|
|
@ -276,12 +276,11 @@ class ApiClientImpl(
|
|||
val tasksObservable = this.tasks
|
||||
|
||||
userObservable = Flowable.zip(
|
||||
userObservable, tasksObservable,
|
||||
{ habitRPGUser, tasks ->
|
||||
habitRPGUser.tasks = tasks
|
||||
habitRPGUser
|
||||
}
|
||||
)
|
||||
userObservable, tasksObservable
|
||||
) { habitRPGUser, tasks ->
|
||||
habitRPGUser.tasks = tasks
|
||||
habitRPGUser
|
||||
}
|
||||
}
|
||||
return userObservable
|
||||
}
|
||||
|
|
@ -330,7 +329,8 @@ class ApiClientImpl(
|
|||
See here for more info: http://blog.danlew.net/2015/03/02/dont-break-the-chain/
|
||||
*/
|
||||
|
||||
override fun <T> configureApiCallObserver(): FlowableTransformer<HabitResponse<T>, T> {
|
||||
override fun <T : Any> configureApiCallObserver(): FlowableTransformer<HabitResponse<T>, T> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return apiCallTransformer as FlowableTransformer<HabitResponse<T>, T>
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -171,16 +171,16 @@ class InventoryRepositoryImpl(
|
|||
val liveUser = localRepository.getLiveUser(userID)
|
||||
|
||||
if (liveUser != null) {
|
||||
localRepository.modify(liveUser) { liveUser ->
|
||||
localRepository.modify(liveUser) { user ->
|
||||
if (type == "mount") {
|
||||
liveUser.items?.currentMount = key
|
||||
user.items?.currentMount = key
|
||||
} else if (type == "pet") {
|
||||
liveUser.items?.currentPet = key
|
||||
user.items?.currentPet = key
|
||||
}
|
||||
val outfit = if (type == "costume") {
|
||||
liveUser.items?.gear?.costume
|
||||
user.items?.gear?.costume
|
||||
} else {
|
||||
liveUser.items?.gear?.equipped
|
||||
user.items?.gear?.equipped
|
||||
}
|
||||
when (key.split("_").firstOrNull()) {
|
||||
"weapon" -> outfit?.weapon = key
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ class TaskRepositoryImpl(
|
|||
up: Boolean,
|
||||
force: Boolean,
|
||||
notifyFunc: ((TaskScoringResult) -> Unit)?
|
||||
): Maybe<TaskScoringResult?> {
|
||||
): Maybe<TaskScoringResult> {
|
||||
return localRepository.getTask(taskId).firstElement()
|
||||
.flatMap { task -> taskChecked(user, task, up, force, notifyFunc).singleElement() }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ import com.habitrpg.android.habitica.data.TaskRepository
|
|||
import com.habitrpg.android.habitica.data.UserRepository
|
||||
import com.habitrpg.android.habitica.data.local.UserLocalRepository
|
||||
import com.habitrpg.android.habitica.data.local.UserQuestStatus
|
||||
import com.habitrpg.android.habitica.extensions.skipNull
|
||||
import com.habitrpg.android.habitica.extensions.Optional
|
||||
import com.habitrpg.android.habitica.extensions.filterMapEmpty
|
||||
import com.habitrpg.android.habitica.helpers.AppConfigManager
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.models.Achievement
|
||||
|
|
@ -161,7 +162,7 @@ class UserRepositoryImpl(
|
|||
override fun changeClass(selectedClass: String): Flowable<User> = apiClient.changeClass(selectedClass)
|
||||
.flatMap { retrieveUser(false) }
|
||||
|
||||
override fun unlockPath(user: User?, path: String, price: Int): Flowable<UnlockResponse> {
|
||||
override fun unlockPath(path: String, price: Int): Flowable<UnlockResponse> {
|
||||
return zipWithLiveUser(apiClient.unlockPath(path)) { unlockResponse, copiedUser ->
|
||||
val user = localRepository.getUnmanagedCopy(copiedUser)
|
||||
user.preferences = unlockResponse.preferences
|
||||
|
|
@ -173,12 +174,8 @@ class UserRepositoryImpl(
|
|||
}
|
||||
}
|
||||
|
||||
override fun unlockPath(user: User?, customization: Customization): Flowable<UnlockResponse> {
|
||||
var path = customization.path
|
||||
if (path.last() == '.' && customization.type == "background") {
|
||||
path += user?.preferences?.background
|
||||
}
|
||||
return unlockPath(user, path, customization.price ?: 0)
|
||||
override fun unlockPath(customization: Customization): Flowable<UnlockResponse> {
|
||||
return unlockPath(customization.path, customization.price ?: 0)
|
||||
}
|
||||
|
||||
override fun runCron() {
|
||||
|
|
@ -323,22 +320,22 @@ class UserRepositoryImpl(
|
|||
if (appConfigManager.enableLocalChanges()) {
|
||||
localRepository.getUser(userID).firstElement().subscribe(
|
||||
{ liveUser ->
|
||||
localRepository.modify(liveUser) { liveUser ->
|
||||
localRepository.modify(liveUser) { user ->
|
||||
when (type) {
|
||||
"skin" -> liveUser.preferences?.skin = identifier
|
||||
"shirt" -> liveUser.preferences?.shirt = identifier
|
||||
"skin" -> user.preferences?.skin = identifier
|
||||
"shirt" -> user.preferences?.shirt = identifier
|
||||
"hair" -> {
|
||||
when (category) {
|
||||
"color" -> liveUser.preferences?.hair?.color = identifier
|
||||
"flower" -> liveUser.preferences?.hair?.flower = identifier.toInt()
|
||||
"mustache" -> liveUser.preferences?.hair?.mustache = identifier.toInt()
|
||||
"beard" -> liveUser.preferences?.hair?.beard = identifier.toInt()
|
||||
"bangs" -> liveUser.preferences?.hair?.bangs = identifier.toInt()
|
||||
"base" -> liveUser.preferences?.hair?.base = identifier.toInt()
|
||||
"color" -> user.preferences?.hair?.color = identifier
|
||||
"flower" -> user.preferences?.hair?.flower = identifier.toInt()
|
||||
"mustache" -> user.preferences?.hair?.mustache = identifier.toInt()
|
||||
"beard" -> user.preferences?.hair?.beard = identifier.toInt()
|
||||
"bangs" -> user.preferences?.hair?.bangs = identifier.toInt()
|
||||
"base" -> user.preferences?.hair?.base = identifier.toInt()
|
||||
}
|
||||
}
|
||||
"background" -> liveUser.preferences?.background = identifier
|
||||
"chair" -> liveUser.preferences?.chair = identifier
|
||||
"background" -> user.preferences?.background = identifier
|
||||
"chair" -> user.preferences?.chair = identifier
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -401,11 +398,11 @@ class UserRepositoryImpl(
|
|||
|
||||
private fun getLiveUser(): Flowable<User> {
|
||||
return localRepository.getUser(userID)
|
||||
.map { localRepository.getLiveObject(it) }
|
||||
.skipNull()
|
||||
.map { Optional(localRepository.getLiveObject(it)) }
|
||||
.filterMapEmpty()
|
||||
}
|
||||
|
||||
private fun <T> zipWithLiveUser(flowable: Flowable<T>, mergeFunc: BiFunction<T, User, T>): Flowable<T> {
|
||||
private fun <T : Any> zipWithLiveUser(flowable: Flowable<T>, mergeFunc: BiFunction<T, User, T>): Flowable<T> {
|
||||
return Flowable.zip(flowable, getLiveUser().firstElement().toFlowable(), mergeFunc)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ interface TaskLocalRepository : BaseLocalRepository {
|
|||
fun getTasks(taskType: TaskType, userID: String): Flowable<out List<Task>>
|
||||
fun getTasks(userId: String): Flowable<out List<Task>>
|
||||
|
||||
fun saveTasks(userId: String, tasksOrder: TasksOrder, tasks: TaskList)
|
||||
fun saveTasks(ownerID: String, tasksOrder: TasksOrder, tasks: TaskList)
|
||||
|
||||
fun deleteTask(taskID: String)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.habitrpg.android.habitica.data.local.implementation
|
||||
|
||||
import com.habitrpg.android.habitica.data.local.BaseLocalRepository
|
||||
import com.habitrpg.android.habitica.extensions.filterMap
|
||||
import com.habitrpg.android.habitica.models.BaseMainObject
|
||||
import com.habitrpg.android.habitica.models.BaseObject
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
|
|
@ -93,6 +94,7 @@ abstract class RealmBaseLocalRepository internal constructor(override var realm:
|
|||
if (isClosed) return null
|
||||
if (obj !is RealmObject || !obj.isManaged) return obj
|
||||
val baseObject = obj as? BaseMainObject ?: return null
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return realm.where(baseObject.realmClass).equalTo(baseObject.primaryIdentifierName, baseObject.primaryIdentifier).findFirst() as? T
|
||||
}
|
||||
|
||||
|
|
@ -104,6 +106,6 @@ abstract class RealmBaseLocalRepository internal constructor(override var realm:
|
|||
.asFlowable()
|
||||
)
|
||||
.filter { it.isLoaded && it.isValid && !it.isEmpty() }
|
||||
.map { it.first() }
|
||||
.filterMap { it.first() }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.habitrpg.android.habitica.data.local.implementation
|
||||
|
||||
import com.habitrpg.android.habitica.data.local.ChallengeLocalRepository
|
||||
import com.habitrpg.android.habitica.extensions.filterMap
|
||||
import com.habitrpg.android.habitica.models.social.Challenge
|
||||
import com.habitrpg.android.habitica.models.social.ChallengeMembership
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
|
|
@ -28,7 +29,7 @@ class RealmChallengeLocalRepository(realm: Realm) : RealmBaseLocalRepository(rea
|
|||
.findAll()
|
||||
.asFlowable()
|
||||
.filter { it.isLoaded }
|
||||
).map { it.first() }
|
||||
).filterMap { it.first() }
|
||||
|
||||
override fun getChallengeMemberships(userId: String): Flowable<out List<ChallengeMembership>> = RxJavaBridge.toV3Flowable(
|
||||
realm.where(ChallengeMembership::class.java)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package com.habitrpg.android.habitica.data.local.implementation
|
||||
|
||||
import com.habitrpg.android.habitica.data.local.ContentLocalRepository
|
||||
import com.habitrpg.android.habitica.extensions.skipNull
|
||||
import com.habitrpg.android.habitica.models.ContentResult
|
||||
import com.habitrpg.android.habitica.models.WorldState
|
||||
import com.habitrpg.android.habitica.models.inventory.Quest
|
||||
|
|
@ -43,7 +42,6 @@ open class RealmContentLocalRepository(realm: Realm) : RealmBaseLocalRepository(
|
|||
.filter { it.isLoaded && it.size > 0 }
|
||||
.map { it.first() }
|
||||
)
|
||||
.skipNull()
|
||||
}
|
||||
|
||||
override fun saveWorldState(worldState: WorldState) {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.habitrpg.android.habitica.data.local.implementation
|
|||
|
||||
import com.habitrpg.android.habitica.data.local.UserLocalRepository
|
||||
import com.habitrpg.android.habitica.data.local.UserQuestStatus
|
||||
import com.habitrpg.android.habitica.extensions.filterMap
|
||||
import com.habitrpg.android.habitica.models.Achievement
|
||||
import com.habitrpg.android.habitica.models.QuestAchievement
|
||||
import com.habitrpg.android.habitica.models.Skill
|
||||
|
|
@ -27,12 +28,11 @@ class RealmUserLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
|
|||
.findAll()
|
||||
.asFlowable()
|
||||
.filter { groups -> groups.size > 0 }
|
||||
.map { groups -> groups.first() }
|
||||
)
|
||||
).filterMap { it.first() }
|
||||
}
|
||||
.map {
|
||||
when {
|
||||
it?.quest?.members?.find { questMember -> questMember.key == userID } === null -> UserQuestStatus.NO_QUEST
|
||||
it.quest?.members?.find { questMember -> questMember.key == userID } === null -> UserQuestStatus.NO_QUEST
|
||||
it.quest?.progress?.collect?.isNotEmpty() ?: false -> UserQuestStatus.QUEST_COLLECT
|
||||
it.quest?.progress?.hp ?: 0.0 > 0.0 -> UserQuestStatus.QUEST_BOSS
|
||||
else -> UserQuestStatus.QUEST_UNKNOWN
|
||||
|
|
|
|||
|
|
@ -5,11 +5,6 @@ import io.reactivex.rxjava3.core.Flowable
|
|||
import io.reactivex.rxjava3.disposables.Disposable
|
||||
import io.reactivex.rxjava3.functions.Consumer
|
||||
|
||||
fun <T> Flowable<T>.subscribeWithErrorHandler(function: Consumer<T>): Disposable {
|
||||
fun <T : Any> Flowable<T>.subscribeWithErrorHandler(function: Consumer<T>): Disposable {
|
||||
return subscribe(function, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
|
||||
fun <T> Flowable<T?>.skipNull(): Flowable<T> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return skipWhile { it == null } as? Flowable<T> ?: Flowable.empty()
|
||||
}
|
||||
}
|
||||
|
|
@ -2,5 +2,11 @@ package com.habitrpg.android.habitica.extensions
|
|||
|
||||
data class Optional<T>(val value: T?) {
|
||||
val isEmpty = value == null
|
||||
|
||||
val assertedValue: T
|
||||
get() {
|
||||
assert(!isEmpty)
|
||||
return value!!
|
||||
}
|
||||
}
|
||||
fun <T> T?.asOptional() = Optional(this)
|
||||
|
|
|
|||
|
|
@ -5,46 +5,58 @@ import io.reactivex.rxjava3.core.Maybe
|
|||
import io.reactivex.rxjava3.core.Observable
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
|
||||
fun <S, T : Optional<S>> Flowable<T>.filterOptionalDoOnEmpty(function: () -> Unit): Flowable<S> {
|
||||
fun <S : Any, T : Optional<S>> Flowable<T>.filterOptionalDoOnEmpty(function: () -> Unit): Flowable<S> {
|
||||
return this.doOnNext { if (it.isEmpty) function() }
|
||||
.filter { !it.isEmpty }
|
||||
.map { it.value }
|
||||
.map { it.assertedValue }
|
||||
}
|
||||
|
||||
fun <S, T : Optional<S>> Flowable<T>.filterMapEmpty(): Flowable<S> {
|
||||
fun <S : Any, T : Optional<S>> Flowable<T>.filterMapEmpty(): Flowable<S> {
|
||||
return this.filter { !it.isEmpty }
|
||||
.map { it.value }
|
||||
.map { it.assertedValue }
|
||||
}
|
||||
|
||||
fun <S, T : Optional<S>> Observable<T>.filterOptionalDoOnEmpty(function: () -> Unit): Observable<S> {
|
||||
fun <S : Any, T : Any> Flowable<T>.filterMap(function: (T) -> S?): Flowable<S> {
|
||||
return this.map { Optional(function(it)) }
|
||||
.filter { !it.isEmpty }
|
||||
.map { it.assertedValue }
|
||||
}
|
||||
|
||||
fun <S : Any, T : Optional<S>> Observable<T>.filterOptionalDoOnEmpty(function: () -> Unit): Observable<S> {
|
||||
return this.doOnNext { if (it.isEmpty) function() }
|
||||
.filter { !it.isEmpty }
|
||||
.map { it.value }
|
||||
.map { it.assertedValue }
|
||||
}
|
||||
|
||||
fun <S, T : Optional<S>> Observable<T>.filterMapEmpty(): Observable<S> {
|
||||
fun <S : Any, T : Optional<S>> Observable<T>.filterMapEmpty(): Observable<S> {
|
||||
return this.filter { !it.isEmpty }
|
||||
.map { it.value }
|
||||
.map { it.assertedValue }
|
||||
}
|
||||
|
||||
fun <S : Any, T : Any> Observable<T>.filterMap(function: (T) -> S?): Observable<S> {
|
||||
return this.map { Optional(function(it)) }
|
||||
.filter { !it.isEmpty }
|
||||
.map { it.assertedValue }
|
||||
}
|
||||
|
||||
fun <S, T : Optional<S>> Single<T>.filterOptionalDoOnEmpty(function: () -> Unit): Maybe<S> {
|
||||
return this.doOnSuccess { if (it.isEmpty) function() }
|
||||
.filter { !it.isEmpty }
|
||||
.map { it.value }
|
||||
.map { it.assertedValue }
|
||||
}
|
||||
|
||||
fun <S, T : Optional<S>> Single<T>.filterMapEmpty(): Maybe<S> {
|
||||
return this.filter { !it.isEmpty }
|
||||
.map { it.value }
|
||||
.map { it.assertedValue }
|
||||
}
|
||||
|
||||
fun <S, T : Optional<S>> Maybe<T>.filterOptionalDoOnEmpty(function: () -> Unit): Maybe<S> {
|
||||
return this.doOnSuccess { if (it.isEmpty) function() }
|
||||
.filter { !it.isEmpty }
|
||||
.map { it.value }
|
||||
.map { it.assertedValue }
|
||||
}
|
||||
|
||||
fun <S, T : Optional<S>> Maybe<T>.filterMapEmpty(): Maybe<S> {
|
||||
return this.filter { !it.isEmpty }
|
||||
.map { it.value }
|
||||
.map { it.assertedValue }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import java.util.Date
|
|||
class AprilFoolsHandler {
|
||||
|
||||
companion object {
|
||||
var eventEnd = Date(2020, 3, 1)
|
||||
private var eventEnd: Date? = null
|
||||
|
||||
fun handle(name: String?, endDate: Date?) {
|
||||
if (endDate != null) {
|
||||
|
|
|
|||
|
|
@ -11,15 +11,15 @@ import android.os.Handler
|
|||
import android.os.Looper
|
||||
import android.text.TextUtils
|
||||
import androidx.annotation.WorkerThread
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
import java.io.BufferedReader
|
||||
import java.io.IOException
|
||||
import java.io.InputStreamReader
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
import java.util.Locale
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 Jared Rummler
|
||||
|
|
@ -120,32 +120,18 @@ object DeviceName {
|
|||
* @see .getDeviceName
|
||||
*/
|
||||
val deviceName: String?
|
||||
get() = getDeviceName(Build.DEVICE, Build.MODEL, Build.MODEL.capitalize(Locale.getDefault()))
|
||||
get() = getDeviceName(Build.MODEL.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() })
|
||||
|
||||
/**
|
||||
* Get the consumer friendly name of a device.
|
||||
*
|
||||
* @param codename the value of the system property "ro.product.device" ([Build.DEVICE])
|
||||
* *or*
|
||||
* the value of the system property "ro.product.model" ([Build.MODEL])
|
||||
* @param fallback the fallback name if the device is unknown. Usually the value of the system property
|
||||
* "ro.product.model" ([Build.MODEL])
|
||||
* @return the market name of a device or `fallback` if the device is unknown.
|
||||
*/
|
||||
fun getDeviceName(codename: String?, fallback: String?): String? {
|
||||
return getDeviceName(codename, codename, fallback)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the consumer friendly name of a device.
|
||||
*
|
||||
* @param codename the value of the system property "ro.product.device" ([Build.DEVICE]).
|
||||
* @param model the value of the system property "ro.product.model" ([Build.MODEL]).
|
||||
* @param fallback the fallback name if the device is unknown. Usually the value of the system property
|
||||
* "ro.product.model" ([Build.MODEL])
|
||||
* @return the market name of a device or `fallback` if the device is unknown.
|
||||
*/
|
||||
fun getDeviceName(codename: String?, model: String?, fallback: String?): String? {
|
||||
private fun getDeviceName(fallback: String?): String? {
|
||||
val codename = Build.DEVICE
|
||||
val model = Build.MODEL
|
||||
// ----------------------------------------------------------------------------
|
||||
// Google
|
||||
if (codename != null && codename == "walleye") {
|
||||
|
|
@ -371,20 +357,6 @@ object DeviceName {
|
|||
return getDeviceInfo(context.applicationContext, Build.DEVICE, Build.MODEL)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the [DeviceInfo] for the current device. Do not run on the UI thread, as this may
|
||||
* download JSON to retrieve the [DeviceInfo]. JSON is only downloaded once and then
|
||||
* stored to [SharedPreferences].
|
||||
*
|
||||
* @param context the application context.
|
||||
* @param codename the codename of the device
|
||||
* @return [DeviceInfo] for the current device.
|
||||
*/
|
||||
@WorkerThread
|
||||
fun getDeviceInfo(context: Context, codename: String?): DeviceInfo {
|
||||
return getDeviceInfo(context, codename, null)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the [DeviceInfo] for the current device. Do not run on the UI thread, as this may
|
||||
* download JSON to retrieve the [DeviceInfo]. JSON is only downloaded once and then
|
||||
|
|
@ -502,18 +474,6 @@ object DeviceName {
|
|||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the device model to query. You should also set the codename.
|
||||
*
|
||||
* @param model the value of the system property "ro.product.model"
|
||||
* @return This Request object to allow for chaining of calls to set methods.
|
||||
* @see Build.MODEL
|
||||
*/
|
||||
fun setModel(model: String?): Request {
|
||||
this.model = model
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Download information about the device. This saves the results in shared-preferences so
|
||||
* future requests will not need a network connection.
|
||||
|
|
@ -601,6 +561,6 @@ object DeviceName {
|
|||
val name: String?
|
||||
get() = if (!TextUtils.isEmpty(marketName)) {
|
||||
marketName
|
||||
} else model?.capitalize(Locale.getDefault())
|
||||
} else model?.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ class TaskAlarmManager(
|
|||
notificationIntent.putExtra(NotificationPublisher.NOTIFICATION_ID, 1)
|
||||
notificationIntent.putExtra(NotificationPublisher.CHECK_DAILIES, false)
|
||||
|
||||
val alarmManager = context?.getSystemService(Context.ALARM_SERVICE) as? AlarmManager
|
||||
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as? AlarmManager
|
||||
val previousSender = PendingIntent.getBroadcast(
|
||||
context,
|
||||
0,
|
||||
|
|
@ -186,9 +186,7 @@ class TaskAlarmManager(
|
|||
withImmutableFlag(PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
)
|
||||
|
||||
if (context != null) {
|
||||
setAlarm(context, triggerTime, pendingIntent)
|
||||
}
|
||||
setAlarm(context, triggerTime, pendingIntent)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ class GroupActivityNotification(context: Context, identifier: String?) : Habitic
|
|||
private fun makeMessageFromData(data: Map<String, String>): NotificationCompat.MessagingStyle.Message {
|
||||
val sender = Person.Builder().setName(data["senderName"]).build()
|
||||
val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US)
|
||||
val timestamp = dateFormat.parse(data["timestamp"]) ?: Date()
|
||||
val timestamp = data["timestamp"]?.let { dateFormat.parse(it) } ?: Date()
|
||||
val messageText = EmojiParser.parseEmojis(data["message"]?.trim { it <= ' ' })
|
||||
return NotificationCompat.MessagingStyle.Message(
|
||||
messageText,
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ class PushNotificationManager(
|
|||
|
||||
val notificationFactory = HabiticaLocalNotificationFactory()
|
||||
val notification = notificationFactory.build(remoteMessageIdentifier, context)
|
||||
if (userIsSubscribedToNotificationType(remoteMessageIdentifier) && notification != null) {
|
||||
if (userIsSubscribedToNotificationType(remoteMessageIdentifier)) {
|
||||
if (remoteMessage.data.containsKey("sendAnalytics")) {
|
||||
val additionalData = HashMap<String, Any>()
|
||||
additionalData["identifier"] = remoteMessageIdentifier ?: ""
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import androidx.core.util.Pair
|
|||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.data.UserRepository
|
||||
import com.habitrpg.android.habitica.executors.PostExecutionThread
|
||||
import com.habitrpg.android.habitica.extensions.filterMap
|
||||
import com.habitrpg.android.habitica.extensions.round
|
||||
import com.habitrpg.android.habitica.models.user.Stats
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
|
|
@ -48,7 +49,7 @@ constructor(
|
|||
if (requestValues.hasLeveledUp == true) {
|
||||
return@defer levelUpUseCase.observable(LevelUpUseCase.RequestValues(requestValues.user, requestValues.level, requestValues.context, requestValues.snackbarTargetView))
|
||||
.flatMap { userRepository.retrieveUser(true) }
|
||||
.map { it.stats }
|
||||
.filterMap { it.stats }
|
||||
} else {
|
||||
return@defer Flowable.just(stats)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,13 +85,13 @@ class ShowNotificationInteractor(
|
|||
val view = factory.inflate(R.layout.dialog_login_incentive, null)
|
||||
|
||||
val imageView = view.findViewById(R.id.imageView) as? ImageView
|
||||
var imageKey = notificationData?.rewardKey?.get(0)
|
||||
var imageKey = notificationData.rewardKey?.get(0)
|
||||
if (imageKey?.contains("armor") == true) {
|
||||
imageKey = "slim_$imageKey"
|
||||
}
|
||||
DataBindingUtils.loadImage(imageView, imageKey)
|
||||
|
||||
val youEarnedMessage = activity.getString(R.string.checkInRewardEarned, notificationData?.rewardText)
|
||||
val youEarnedMessage = activity.getString(R.string.checkInRewardEarned, notificationData.rewardText)
|
||||
val youEarnedTexView = view.findViewById(R.id.you_earned_message) as? TextView
|
||||
youEarnedTexView?.text = youEarnedMessage
|
||||
|
||||
|
|
|
|||
|
|
@ -73,9 +73,9 @@ class UserRepositoryModule {
|
|||
return TaskRepositoryImpl(
|
||||
localRepository,
|
||||
apiClient,
|
||||
userId!!,
|
||||
appConfigManager!!,
|
||||
analyticsManager!!
|
||||
userId,
|
||||
appConfigManager,
|
||||
analyticsManager
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ class AvatarView : FrameLayout {
|
|||
private var avatarRectF: RectF? = null
|
||||
private val avatarMatrix = Matrix()
|
||||
private val numberLayersInProcess = AtomicInteger(0)
|
||||
private var avatarImageConsumer: Consumer<Bitmap?>? = null
|
||||
private var avatarImageConsumer: ((Bitmap?) -> Unit)? = null
|
||||
private var avatarBitmap: Bitmap? = null
|
||||
private var avatarCanvas: Canvas? = null
|
||||
private var currentLayers: Map<LayerType, String>? = null
|
||||
|
|
@ -405,14 +405,14 @@ class AvatarView : FrameLayout {
|
|||
|
||||
private fun onLayerComplete() {
|
||||
if (numberLayersInProcess.decrementAndGet() == 0) {
|
||||
avatarImageConsumer?.accept(avatarImage)
|
||||
avatarImageConsumer?.invoke(avatarImage)
|
||||
}
|
||||
}
|
||||
|
||||
fun onAvatarImageReady(consumer: Consumer<Bitmap?>) {
|
||||
fun onAvatarImageReady(consumer: ((Bitmap?) -> Unit)) {
|
||||
avatarImageConsumer = consumer
|
||||
if (imageViewHolder.size > 0 && numberLayersInProcess.get() == 0) {
|
||||
avatarImageConsumer?.accept(avatarImage)
|
||||
avatarImageConsumer?.invoke(avatarImage)
|
||||
} else {
|
||||
initAvatarRectMatrix()
|
||||
showLayers(layerMap)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.habitrpg.android.habitica.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.util.AttributeSet
|
||||
import android.util.DisplayMetrics
|
||||
import android.view.WindowManager
|
||||
|
|
@ -47,9 +48,15 @@ class MaxHeightLinearLayout : LinearLayout {
|
|||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||
var heightMeasurement = heightMeasureSpec
|
||||
|
||||
val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as? WindowManager
|
||||
windowManager?.defaultDisplay?.getMetrics(displaymetrics)
|
||||
val height = (displaymetrics.heightPixels * maxHeight).toInt()
|
||||
val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
|
||||
val height = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
windowManager.currentWindowMetrics.bounds.height()
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
windowManager.defaultDisplay?.getMetrics(displaymetrics)
|
||||
(displaymetrics.heightPixels * maxHeight).toInt()
|
||||
}
|
||||
|
||||
heightMeasurement = min(heightMeasurement, MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST))
|
||||
|
||||
super.onMeasure(widthMeasureSpec, heightMeasurement)
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import com.plattysoft.leonids.ParticleSystem
|
|||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
import com.habitrpg.android.habitica.ui.helpers.loadImage
|
||||
|
||||
class ArmoireActivity: BaseActivity() {
|
||||
|
||||
|
|
|
|||
|
|
@ -349,9 +349,8 @@ class ChallengeFormActivity : BaseActivity() {
|
|||
return@flatMap Flowable.empty<Group>()
|
||||
}
|
||||
socialRepository.retrieveGroup(it)
|
||||
},
|
||||
{ user, groups -> Pair(user, groups) }
|
||||
)
|
||||
}
|
||||
) { user, groups -> Pair(user, groups) }
|
||||
.subscribe(
|
||||
{ groups ->
|
||||
val mutableGroups = groups.first.toMutableList()
|
||||
|
|
|
|||
|
|
@ -264,7 +264,7 @@ class ClassSelectionActivity : BaseActivity(), Consumer<User> {
|
|||
}
|
||||
|
||||
private fun displayProgressDialog(progressText: String) {
|
||||
val dialog = HabiticaProgressDialog.show(this, progressText)
|
||||
HabiticaProgressDialog.show(this, progressText)
|
||||
}
|
||||
|
||||
override fun accept(user: User) {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import android.widget.TableRow
|
|||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import coil.load
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.UserComponent
|
||||
|
|
@ -40,14 +41,13 @@ import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
|
|||
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar.SnackbarDisplayType
|
||||
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import java.text.SimpleDateFormat
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.floor
|
||||
import kotlin.math.min
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class FullProfileActivity : BaseActivity() {
|
||||
private var blocks: List<String> = listOf()
|
||||
|
|
@ -193,7 +193,7 @@ class FullProfileActivity : BaseActivity() {
|
|||
|
||||
private fun showSendMessageToUserDialog() {
|
||||
finish()
|
||||
GlobalScope.launch(context = Dispatchers.Main) {
|
||||
lifecycleScope.launch(context = Dispatchers.Main) {
|
||||
delay(1000L)
|
||||
MainNavigationController.navigate(R.id.inboxMessageListFragment, bundleOf(Pair("username", username), Pair("userID", userID)))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -115,10 +115,6 @@ class LoginActivity : BaseActivity() {
|
|||
// Set default values to avoid null-responses when requesting unedited settings
|
||||
PreferenceManager.setDefaultValues(this, R.xml.preferences_fragment, false)
|
||||
|
||||
viewModel.setupFacebookLogin {
|
||||
handleAuthResponse(it)
|
||||
}
|
||||
|
||||
binding.loginBtn.setOnClickListener(loginClick)
|
||||
|
||||
val content = SpannableString(binding.forgotPassword.text)
|
||||
|
|
@ -141,7 +137,6 @@ class LoginActivity : BaseActivity() {
|
|||
binding.showLoginButton.setOnClickListener { showLoginButtonClicked() }
|
||||
binding.backButton.setOnClickListener { backButtonClicked() }
|
||||
binding.forgotPassword.setOnClickListener { onForgotPasswordClicked() }
|
||||
binding.fbLoginButton.setOnClickListener { viewModel.handleFacebookLogin(this) }
|
||||
binding.googleLoginButton.setOnClickListener { viewModel.handleGoogleLogin(this, pickAccountResult) }
|
||||
binding.appleLoginButton.setOnClickListener {
|
||||
viewModel.connectApple(supportFragmentManager) {
|
||||
|
|
@ -213,7 +208,6 @@ class LoginActivity : BaseActivity() {
|
|||
binding.password.setAutofillHints("newPassword")
|
||||
}
|
||||
binding.password.imeOptions = EditorInfo.IME_ACTION_NEXT
|
||||
binding.fbLoginButton.visibility = View.GONE
|
||||
binding.googleLoginButton.setText(R.string.register_btn_google)
|
||||
} else {
|
||||
binding.loginBtn.text = getString(R.string.login_btn)
|
||||
|
|
@ -223,8 +217,6 @@ class LoginActivity : BaseActivity() {
|
|||
binding.password.setAutofillHints("password")
|
||||
}
|
||||
binding.password.imeOptions = EditorInfo.IME_ACTION_DONE
|
||||
binding.fbLoginButton.setText(R.string.login_btn_fb)
|
||||
binding.fbLoginButton.visibility = if (configManager.hideFacebook()) View.GONE else View.VISIBLE
|
||||
binding.googleLoginButton.setText(R.string.login_btn_google)
|
||||
}
|
||||
this.resetLayout()
|
||||
|
|
@ -263,13 +255,6 @@ class LoginActivity : BaseActivity() {
|
|||
)
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
viewModel.onActivityResult(requestCode, resultCode, data) {
|
||||
handleAuthResponse(it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.action_toggleRegistering -> toggleRegistering()
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ import com.habitrpg.android.habitica.extensions.dpToPx
|
|||
import com.habitrpg.android.habitica.extensions.getThemeColor
|
||||
import com.habitrpg.android.habitica.extensions.hideKeyboard
|
||||
import com.habitrpg.android.habitica.extensions.isUsingNightModeResources
|
||||
import com.habitrpg.android.habitica.extensions.observeOnce
|
||||
import com.habitrpg.android.habitica.extensions.subscribeWithErrorHandler
|
||||
import com.habitrpg.android.habitica.extensions.updateStatusBarColor
|
||||
import com.habitrpg.android.habitica.helpers.AdHandler
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ class SkillsRecyclerViewAdapter : RecyclerView.Adapter<SkillsRecyclerViewAdapter
|
|||
field = value
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
var specialItems: RealmList<OwnedItem>?? = null
|
||||
var specialItems: RealmList<OwnedItem>? = null
|
||||
set(value) {
|
||||
field = value
|
||||
notifyDataSetChanged()
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ class TaskSetupAdapter : RecyclerView.Adapter<TaskSetupAdapter.TaskViewHolder>()
|
|||
}
|
||||
|
||||
override fun onClick(v: View) {
|
||||
val position = this.adapterPosition
|
||||
val position = this.bindingAdapterPosition
|
||||
checkedList[position] = !checkedList[position]
|
||||
notifyItemChanged(position)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -147,7 +147,8 @@ class SystemChatMessageViewHolder(itemView: View) : RecyclerView.ViewHolder(item
|
|||
|
||||
fun bind(chatMessage: ChatMessage?, isExpanded: Boolean) {
|
||||
textView.text = chatMessage?.text?.removePrefix("`")?.removeSuffix("`")
|
||||
timestamp.text = dateTime.format(chatMessage?.timestamp?.let { java.util.Date(it) })
|
||||
timestamp.text = chatMessage?.timestamp?.let { java.util.Date(it) }
|
||||
?.let { dateTime.format(it) }
|
||||
if (isExpanded) {
|
||||
binding.systemMessageTimestamp.visibility = View.VISIBLE
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -128,7 +128,11 @@ class GuildListAdapter : BaseRecyclerViewAdapter<Group, RecyclerView.ViewHolder>
|
|||
binding.tagWrapper.removeAllViews()
|
||||
guild.categories?.forEach { category ->
|
||||
val textView = PillTextviewBinding.inflate(itemView.context.layoutInflater, binding.tagWrapper, true)
|
||||
textView.root.text = category.name?.split("_")?.joinToString(" ") { it.capitalize(Locale.getDefault()) }
|
||||
textView.root.text = category.name?.split("_")?.joinToString(" ") { it.replaceFirstChar {
|
||||
if (it.isLowerCase()) it.titlecase(
|
||||
Locale.getDefault()
|
||||
) else it.toString()
|
||||
} }
|
||||
textView.root.background = if (category.slug == "habitica_official") {
|
||||
textView.root.setTextColor(ContextCompat.getColor(itemView.context, R.color.white))
|
||||
ContextCompat.getDrawable(itemView.context, R.drawable.pill_bg_purple_400)
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ class AvatarCustomizationFragment :
|
|||
adapter.getSelectCustomizationEvents()
|
||||
.flatMap { customization ->
|
||||
if (customization.type == "background") {
|
||||
userRepository.unlockPath(userViewModel.user.value, customization)
|
||||
userRepository.unlockPath(customization)
|
||||
.flatMap { userRepository.retrieveUser(false, true, true) }
|
||||
} else {
|
||||
userRepository.useCustomization(customization.type ?: "", customization.category, customization.identifier ?: "")
|
||||
|
|
@ -103,7 +103,6 @@ class AvatarCustomizationFragment :
|
|||
binding?.refreshLayout?.setOnRefreshListener(this)
|
||||
layoutManager.justifyContent = JustifyContent.CENTER
|
||||
layoutManager.alignItems = AlignItems.FLEX_START
|
||||
setGridSpanCount(view.width)
|
||||
binding?.recyclerView?.layoutManager = layoutManager
|
||||
|
||||
binding?.recyclerView?.addItemDecoration(MarginDecoration(context))
|
||||
|
|
@ -212,16 +211,6 @@ class AvatarCustomizationFragment :
|
|||
}
|
||||
}
|
||||
|
||||
private fun setGridSpanCount(width: Int) {
|
||||
val itemWidth = context?.resources?.getDimension(R.dimen.customization_width) ?: 0F
|
||||
var spanCount = (width / itemWidth).toInt()
|
||||
if (spanCount == 0) {
|
||||
spanCount = 1
|
||||
} else if (type == "backgrounds") {
|
||||
spanCount = 3
|
||||
}
|
||||
}
|
||||
|
||||
fun updateUser(user: User?) {
|
||||
if (user == null) return
|
||||
this.updateActiveCustomization(user)
|
||||
|
|
|
|||
|
|
@ -342,7 +342,7 @@ class ItemRecyclerFragment : BaseFragment<FragmentItemsBinding>(), SwipeRefreshL
|
|||
|
||||
compositeSubscription.add(
|
||||
observable.subscribe(
|
||||
{ skillResponse -> this.displaySpecialItemResult(specialItem) },
|
||||
{ this.displaySpecialItemResult(specialItem) },
|
||||
RxErrorHandler.handleEmptyError()
|
||||
)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -206,13 +206,6 @@ class AccountPreferenceFragment :
|
|||
}
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
viewModel.onActivityResult(requestCode, resultCode, data) {
|
||||
viewModel.handleAuthResponse(it)
|
||||
}
|
||||
}
|
||||
|
||||
private val pickAccountResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
if (it.resultCode == Activity.RESULT_OK) {
|
||||
viewModel.googleEmail = it?.data?.getStringExtra(AccountManager.KEY_ACCOUNT_NAME)
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ class TaskSetupFragment : BaseFragment<FragmentSetupTasksBinding>() {
|
|||
this.updateAvatar()
|
||||
}
|
||||
|
||||
binding?.heartIcon?.setImageDrawable(BitmapDrawable(HabiticaIconsHelper.imageOfHeartLightBg()))
|
||||
binding?.heartIcon?.setImageDrawable(BitmapDrawable(resources, HabiticaIconsHelper.imageOfHeartLightBg()))
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,12 @@ import com.habitrpg.android.habitica.databinding.FragmentRefreshRecyclerviewBind
|
|||
import com.habitrpg.android.habitica.extensions.observeOnce
|
||||
import com.habitrpg.android.habitica.extensions.setScaledPadding
|
||||
import com.habitrpg.android.habitica.extensions.subscribeWithErrorHandler
|
||||
import com.habitrpg.android.habitica.helpers.*
|
||||
import com.habitrpg.android.habitica.helpers.AppConfigManager
|
||||
import com.habitrpg.android.habitica.helpers.HapticFeedbackManager
|
||||
import com.habitrpg.android.habitica.helpers.MainNavigationController
|
||||
import com.habitrpg.android.habitica.helpers.NotificationsManager
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.helpers.SoundManager
|
||||
import com.habitrpg.android.habitica.models.responses.TaskDirection
|
||||
import com.habitrpg.android.habitica.models.responses.TaskScoringResult
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
|
|
@ -121,7 +126,7 @@ open class TaskRecyclerViewFragment : BaseFragment<FragmentRefreshRecyclerviewBi
|
|||
RxErrorHandler.handleEmptyError()
|
||||
)?.let { recyclerSubscription.add(it) }
|
||||
recyclerAdapter?.taskOpenEvents?.subscribeWithErrorHandler {
|
||||
openTaskForm(it.first, it.second)
|
||||
openTaskForm(it.first)
|
||||
}?.let { recyclerSubscription.add(it) }
|
||||
recyclerAdapter?.taskScoreEvents
|
||||
?.doOnNext {
|
||||
|
|
@ -485,7 +490,7 @@ open class TaskRecyclerViewFragment : BaseFragment<FragmentRefreshRecyclerviewBi
|
|||
}
|
||||
}
|
||||
|
||||
private fun openTaskForm(task: Task, containerView: View) {
|
||||
private fun openTaskForm(task: Task) {
|
||||
if (Date().time - (TasksFragment.lastTaskFormOpen?.time ?: 0) < 2000 || !task.isValid || !canEditTasks) {
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ class PetViewHolder(
|
|||
}
|
||||
}
|
||||
menu.setSelectionRunnable { index ->
|
||||
val pet = animal as? Pet ?: return@setSelectionRunnable
|
||||
val pet = animal ?: return@setSelectionRunnable
|
||||
when (index) {
|
||||
0 -> {
|
||||
animal?.let {
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ abstract class ChecklistedViewHolder(
|
|||
textView?.text = item.text
|
||||
textView?.setTextColor(ContextCompat.getColor(context, if (item.completed) R.color.text_dimmed else R.color.text_secondary))
|
||||
if (item.text != null) {
|
||||
Observable.just(item.text)
|
||||
Observable.just(item.text ?: "")
|
||||
.map { MarkdownParser.parseMarkdown(it) }
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
|
|
@ -188,11 +188,11 @@ abstract class ChecklistedViewHolder(
|
|||
}
|
||||
|
||||
private fun onChecklistIndicatorClicked() {
|
||||
expandedChecklistRow = if (this.shouldDisplayExpandedChecklist()) null else adapterPosition
|
||||
expandedChecklistRow = if (this.shouldDisplayExpandedChecklist()) null else bindingAdapterPosition
|
||||
if (this.shouldDisplayExpandedChecklist()) {
|
||||
val recyclerView = this.checklistView.parent.parent as? RecyclerView
|
||||
val layoutManager = recyclerView?.layoutManager as? LinearLayoutManager
|
||||
layoutManager?.scrollToPositionWithOffset(this.adapterPosition, 15)
|
||||
layoutManager?.scrollToPositionWithOffset(this.bindingAdapterPosition, 15)
|
||||
}
|
||||
updateChecklistDisplay()
|
||||
}
|
||||
|
|
@ -210,7 +210,7 @@ abstract class ChecklistedViewHolder(
|
|||
}
|
||||
|
||||
private fun shouldDisplayExpandedChecklist(): Boolean {
|
||||
return expandedChecklistRow != null && adapterPosition == expandedChecklistRow
|
||||
return expandedChecklistRow != null && bindingAdapterPosition == expandedChecklistRow
|
||||
}
|
||||
|
||||
private fun onCheckedChanged(isChecked: Boolean) {
|
||||
|
|
|
|||
|
|
@ -9,13 +9,6 @@ import android.os.Build
|
|||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.core.content.edit
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import com.facebook.AccessToken
|
||||
import com.facebook.CallbackManager
|
||||
import com.facebook.FacebookCallback
|
||||
import com.facebook.FacebookException
|
||||
import com.facebook.FacebookSdk
|
||||
import com.facebook.login.LoginManager
|
||||
import com.facebook.login.LoginResult
|
||||
import com.google.android.gms.auth.GoogleAuthException
|
||||
import com.google.android.gms.auth.GoogleAuthUtil
|
||||
import com.google.android.gms.auth.GooglePlayServicesAvailabilityException
|
||||
|
|
@ -33,7 +26,6 @@ import com.habitrpg.android.habitica.data.ApiClient
|
|||
import com.habitrpg.android.habitica.data.UserRepository
|
||||
import com.habitrpg.android.habitica.extensions.addCloseButton
|
||||
import com.habitrpg.android.habitica.helpers.KeyHelper
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.helpers.SignInWithAppleResult
|
||||
import com.habitrpg.android.habitica.helpers.SignInWithAppleService
|
||||
import com.habitrpg.android.habitica.models.auth.UserAuthResponse
|
||||
|
|
@ -65,9 +57,7 @@ class AuthenticationViewModel() {
|
|||
|
||||
private var compositeSubscription = CompositeDisposable()
|
||||
|
||||
private var callbackManager = CallbackManager.Factory.create()
|
||||
var googleEmail: String? = null
|
||||
private var loginManager = LoginManager.getInstance()
|
||||
|
||||
init {
|
||||
HabiticaBaseApplication.userComponent?.inject(this)
|
||||
|
|
@ -96,56 +86,6 @@ class AuthenticationViewModel() {
|
|||
}.show()
|
||||
}
|
||||
|
||||
fun setupFacebookLogin(onSuccess: (UserAuthResponse) -> Unit) {
|
||||
callbackManager = CallbackManager.Factory.create()
|
||||
loginManager.registerCallback(
|
||||
callbackManager,
|
||||
object : FacebookCallback<LoginResult> {
|
||||
override fun onSuccess(result: LoginResult) {
|
||||
val accessToken = AccessToken.getCurrentAccessToken()
|
||||
compositeSubscription.add(
|
||||
apiClient.connectSocial("facebook", accessToken?.userId ?: "", accessToken?.token ?: "")
|
||||
.subscribe({
|
||||
onSuccess(it)
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
)
|
||||
}
|
||||
|
||||
override fun onCancel() { /* no-on */ }
|
||||
|
||||
override fun onError(error: FacebookException) {
|
||||
RxErrorHandler.reportError(error)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun handleFacebookLogin(activity: Activity) {
|
||||
loginManager.logInWithReadPermissions(activity, listOf("user_friends"))
|
||||
}
|
||||
|
||||
fun onActivityResult(
|
||||
requestCode: Int,
|
||||
resultCode: Int,
|
||||
data: Intent?,
|
||||
onSuccess: (UserAuthResponse) -> Unit
|
||||
) {
|
||||
callbackManager.onActivityResult(requestCode, resultCode, data)
|
||||
|
||||
if (requestCode == FacebookSdk.getCallbackRequestCodeOffset()) {
|
||||
// This is necessary because the regular login callback is not called for some reason
|
||||
val accessToken = AccessToken.getCurrentAccessToken()
|
||||
if (accessToken?.token != null) {
|
||||
compositeSubscription.add(
|
||||
apiClient.connectSocial("facebook", accessToken.userId, accessToken.token)
|
||||
.subscribe({
|
||||
onSuccess(it)
|
||||
}, { })
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun handleGoogleLogin(
|
||||
activity: Activity,
|
||||
pickAccountResult: ActivityResultLauncher<Intent>
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ open class NotificationsViewModel : BaseViewModel() {
|
|||
if (isCustomNotification(notification)) {
|
||||
if (isCustomNewStuffNotification(notification)) {
|
||||
customNotifications.onNext(
|
||||
customNotifications.value?.filterNot { it.id == notification.id }
|
||||
customNotifications.value?.filterNot { it.id == notification.id } ?: listOf()
|
||||
)
|
||||
}
|
||||
return
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ class TasksViewModel: BaseViewModel() {
|
|||
init {
|
||||
compositeSubscription.add(userRepository.getTeamPlans()
|
||||
.subscribe({
|
||||
owners = listOf(Pair(userID ?: "", userViewModel.displayName)) + it.map {
|
||||
owners = listOf(Pair(userID, userViewModel.displayName)) + it.map {
|
||||
Pair(
|
||||
it.id,
|
||||
it.summary
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ class ValidatingEditText @JvmOverloads constructor(
|
|||
if (isEditing) return@setOnFocusChangeListener
|
||||
showErrorIfNecessary()
|
||||
}
|
||||
binding.editText.doOnTextChanged { text, start, before, count ->
|
||||
binding.editText.doOnTextChanged { text, _, _, _ ->
|
||||
if (binding.errorText.visibility == View.VISIBLE) {
|
||||
showErrorIfNecessary(text.toString())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.habitrpg.android.habitica.ui.views.login
|
|||
import android.animation.ObjectAnimator
|
||||
import android.animation.ValueAnimator
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.util.AttributeSet
|
||||
import android.util.DisplayMetrics
|
||||
import android.view.View
|
||||
|
|
@ -39,8 +40,13 @@ class LoginBackgroundView(context: Context, attrs: AttributeSet?) : RelativeLayo
|
|||
init {
|
||||
val metrics = DisplayMetrics()
|
||||
val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
|
||||
windowManager.defaultDisplay.getMetrics(metrics)
|
||||
viewHeight = (metrics.heightPixels * SIZE_FACTOR).toInt()
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
viewHeight = windowManager.currentWindowMetrics.bounds.height()
|
||||
} else {
|
||||
@Suppress("DEPRECATION")
|
||||
windowManager.defaultDisplay.getMetrics(metrics)
|
||||
viewHeight = (metrics.heightPixels * SIZE_FACTOR).toInt()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFinishInflate() {
|
||||
|
|
|
|||
|
|
@ -362,7 +362,7 @@ class PurchaseDialog(context: Context, component: UserComponent?, val item: Shop
|
|||
} else if (shopItem.purchaseType == "debuffPotion") {
|
||||
observable = userRepository.useSkill(shopItem.key, null).cast(Any::class.java)
|
||||
} else if (shopItem.purchaseType == "customization" || shopItem.purchaseType == "background" || shopItem.purchaseType == "customizationSet") {
|
||||
observable = userRepository.unlockPath(user, item.path ?: "", item.value).cast(Any::class.java)
|
||||
observable = userRepository.unlockPath(item.path ?: "", item.value).cast(Any::class.java)
|
||||
} else if (shopItem.purchaseType == "debuffPotion") {
|
||||
observable = userRepository.useSkill(shopItem.key, null).cast(Any::class.java)
|
||||
} else if (shopItem.purchaseType == "card") {
|
||||
|
|
|
|||
|
|
@ -22,14 +22,14 @@ class QuestMenuView : LinearLayout {
|
|||
private var questContent: QuestContent? = null
|
||||
|
||||
constructor(context: Context) : super(context) {
|
||||
setupView(context)
|
||||
setupView()
|
||||
}
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
|
||||
setupView(context)
|
||||
setupView()
|
||||
}
|
||||
|
||||
private fun setupView(context: Context) {
|
||||
private fun setupView() {
|
||||
orientation = VERTICAL
|
||||
|
||||
binding.heartIconView.setImageBitmap(HabiticaIconsHelper.imageOfHeartDarkBg())
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ class AvatarStatsWidgetProvider : BaseWidgetProvider() {
|
|||
this.context = context
|
||||
|
||||
if (user == null) {
|
||||
userRepository.getUser().firstElement()?.subscribe({
|
||||
userRepository.getUser().firstElement().subscribe({
|
||||
user = it
|
||||
updateData(appWidgetIds)
|
||||
}, RxErrorHandler.handleEmptyError())
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.6.10'
|
||||
ext.kotlin_version = '1.6.21'
|
||||
|
||||
repositories {
|
||||
google()
|
||||
|
|
@ -12,10 +12,10 @@ buildscript {
|
|||
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
|
||||
classpath 'com.google.gms:google-services:4.3.10'
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.1'
|
||||
classpath "io.realm:realm-gradle-plugin:10.8.1"
|
||||
classpath "io.realm:realm-gradle-plugin:10.10.1"
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.19.0"
|
||||
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.5.0-alpha03"
|
||||
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.5.0-beta01"
|
||||
classpath 'com.google.firebase:perf-plugin:1.4.1'
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
|
@ -1,6 +1,6 @@
|
|||
#Sun May 08 23:57:52 EDT 2022
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
|
|
|||
Loading…
Reference in a new issue