mirror of
https://github.com/sudoxnym/habitica-android.git
synced 2026-05-19 20:29:02 +00:00
Improve notification handling
This commit is contained in:
parent
910b2f2b0a
commit
2f9f342768
22 changed files with 358 additions and 316 deletions
|
|
@ -13,7 +13,6 @@ buildscript {
|
|||
mavenLocal()
|
||||
google()
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.0.4'
|
||||
|
|
@ -47,8 +46,8 @@ dependencies {
|
|||
implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'
|
||||
|
||||
//Dependency Injection
|
||||
implementation 'com.google.dagger:dagger:2.39.1'
|
||||
kapt 'com.google.dagger:dagger-compiler:2.39.1'
|
||||
implementation 'com.google.dagger:dagger:2.40.5'
|
||||
kapt 'com.google.dagger:dagger-compiler:2.40.5'
|
||||
compileOnly 'javax.annotation:javax.annotation-api:1.3.2'
|
||||
compileOnly 'com.github.pengrad:jdk9-deps:1.0'
|
||||
//App Compatibility and Material Design
|
||||
|
|
@ -64,44 +63,51 @@ dependencies {
|
|||
implementation "io.noties.markwon:image:4.6.2"
|
||||
implementation "io.noties.markwon:recycler:4.6.2"
|
||||
//Eventbus
|
||||
implementation 'org.greenrobot:eventbus:3.2.0'
|
||||
implementation 'org.greenrobot:eventbus:3.3.1'
|
||||
// IAP Handling / Verification
|
||||
implementation 'org.solovyev.android:checkout:1.2.3'
|
||||
//Facebook
|
||||
implementation('com.facebook.android:facebook-android-sdk:11.3.0') {
|
||||
implementation('com.facebook.android:facebook-android-sdk:12.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.1'
|
||||
implementation 'io.reactivex.rxjava3:rxjava:3.1.3'
|
||||
implementation 'io.reactivex.rxjava3:rxkotlin:3.0.1'
|
||||
implementation 'io.reactivex.rxjava2:rxjava:2.2.21'
|
||||
implementation "com.github.akarnokd:rxjava3-bridge:3.0.0"
|
||||
implementation "com.github.akarnokd:rxjava3-bridge:3.0.2"
|
||||
|
||||
//Analytics
|
||||
implementation 'com.amplitude:android-sdk:2.30.0'
|
||||
implementation 'com.amplitude:android-sdk:3.35.1'
|
||||
// Image Management Library
|
||||
implementation("io.coil-kt:coil:1.4.0")
|
||||
implementation("io.coil-kt:coil-gif:1.4.0")
|
||||
|
||||
//Tests
|
||||
testImplementation 'io.kotest:kotest-runner-junit5:4.6.2'
|
||||
testImplementation 'io.kotest:kotest-runner-junit5:5.0.3'
|
||||
testImplementation 'androidx.test:core:1.4.0'
|
||||
testImplementation "io.mockk:mockk:1.12.0"
|
||||
testImplementation "io.mockk:mockk-android:1.12.0"
|
||||
testImplementation 'io.kotest:kotest-assertions-core:4.6.2'
|
||||
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.2.1'
|
||||
androidTestImplementation 'com.kaspersky.android-components:kaspresso:1.4.0'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
androidTestImplementation 'androidx.test:runner:1.4.0'
|
||||
androidTestImplementation 'androidx.test:rules:1.4.0'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||
androidTestImplementation "io.mockk:mockk-android:1.12.0"
|
||||
androidTestImplementation "io.mockk:mockk-android:1.12.2"
|
||||
|
||||
implementation 'androidx.activity:activity-compose:1.4.0'
|
||||
implementation 'androidx.compose.material:material:1.0.5'
|
||||
implementation 'androidx.compose.animation:animation:1.0.5'
|
||||
implementation 'androidx.compose.ui:ui-tooling:1.0.5'
|
||||
implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.4.0'
|
||||
implementation "com.google.accompanist:accompanist-appcompat-theme:0.16.0"
|
||||
|
||||
|
||||
//Leak Detection
|
||||
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.7'
|
||||
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.8'
|
||||
//Push Notifications
|
||||
implementation platform('com.google.firebase:firebase-bom:29.0.0')
|
||||
implementation 'com.google.firebase:firebase-crashlytics-ktx'
|
||||
|
|
@ -109,7 +115,7 @@ dependencies {
|
|||
implementation 'com.google.firebase:firebase-messaging-ktx'
|
||||
implementation 'com.google.firebase:firebase-config-ktx'
|
||||
implementation 'com.google.firebase:firebase-perf-ktx'
|
||||
implementation 'com.google.android.gms:play-services-auth:19.2.0'
|
||||
implementation 'com.google.android.gms:play-services-auth:20.0.0'
|
||||
implementation 'com.nex3z:flow-layout:1.2.2'
|
||||
|
||||
implementation 'androidx.core:core-ktx:1.7.0'
|
||||
|
|
@ -121,14 +127,14 @@ dependencies {
|
|||
implementation 'com.plattysoft.leonids:LeonidsLib:1.3.2'
|
||||
implementation "androidx.fragment:fragment-ktx:1.4.0"
|
||||
implementation "androidx.paging:paging-runtime-ktx:3.1.0"
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0'
|
||||
|
||||
implementation 'com.willowtreeapps:signinwithapplebutton:0.3'
|
||||
|
||||
implementation project(':shared')
|
||||
|
||||
ktlint("com.pinterest:ktlint:0.42.1") {
|
||||
ktlint("com.pinterest:ktlint:0.43.2") {
|
||||
attributes {
|
||||
attribute(Bundling.BUNDLING_ATTRIBUTE, getObjects().named(Bundling, Bundling.EXTERNAL))
|
||||
}
|
||||
|
|
@ -136,7 +142,7 @@ dependencies {
|
|||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 31
|
||||
compileSdkVersion 32
|
||||
buildToolsVersion '30.0.2'
|
||||
testOptions {
|
||||
unitTests {
|
||||
|
|
@ -153,9 +159,9 @@ android {
|
|||
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 3128
|
||||
versionName "3.4.2"
|
||||
versionName "3.5"
|
||||
|
||||
targetSdkVersion 31
|
||||
targetSdkVersion 32
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,8 +80,6 @@ class ApiClientImpl // private OnHabitsAPIResult mResultListener;
|
|||
private var lastAPICallURL: String? = null
|
||||
|
||||
init {
|
||||
this.notificationsManager.setApiClient(this)
|
||||
|
||||
HabiticaBaseApplication.userComponent?.inject(this)
|
||||
analyticsManager.setUserIdentifier(this.hostConfig.userID)
|
||||
buildRetrofit()
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
package com.habitrpg.android.habitica.events
|
||||
|
||||
/**
|
||||
* Created by Negue on 29.11.2015.
|
||||
*/
|
||||
class BoughtGemsEvent(var NewGemsToAdd: Int)
|
||||
|
|
@ -2,4 +2,4 @@ package com.habitrpg.android.habitica.events
|
|||
|
||||
import com.habitrpg.android.habitica.models.shops.ShopItem
|
||||
|
||||
class GearPurchasedEvent(val item: ShopItem)
|
||||
class GearPurchasedEvent(val item: ShopItem)
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
package com.habitrpg.android.habitica.events
|
||||
|
||||
class ShowAchievementDialog(var type: String, val id: String, val message: String? = null, val text: String? = null, val isLastOnboardingAchievement: Boolean = false)
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
package com.habitrpg.android.habitica.events
|
||||
|
||||
import com.habitrpg.android.habitica.models.Notification
|
||||
|
||||
class ShowCheckinDialog(var notification: Notification, var nextUnlockText: String, var nextUnlockCount: Int)
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
package com.habitrpg.android.habitica.events
|
||||
|
||||
class ShowFirstDropDialog(val egg: String, val hatchingPotion: String, val id: String)
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
package com.habitrpg.android.habitica.events
|
||||
|
||||
import com.habitrpg.android.habitica.models.notifications.ChallengeWonData
|
||||
|
||||
class ShowWonChallengeDialog(val id: String, val data: ChallengeWonData?)
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package com.habitrpg.android.habitica.helpers
|
||||
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.google.firebase.analytics.FirebaseAnalytics
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.data.ApiClient
|
||||
|
|
@ -12,22 +13,35 @@ import com.habitrpg.android.habitica.models.notifications.FirstDropData
|
|||
import com.habitrpg.android.habitica.models.notifications.LoginIncentiveData
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
|
||||
import com.habitrpg.android.habitica.ui.views.dialogs.WonChallengeDialog
|
||||
import io.reactivex.rxjava3.core.BackpressureStrategy
|
||||
import io.reactivex.rxjava3.core.Completable
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import io.reactivex.rxjava3.subjects.BehaviorSubject
|
||||
import io.reactivex.rxjava3.subjects.PublishSubject
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class NotificationsManager {
|
||||
private val displayNotificationSubject = PublishSubject.create<Notification>()
|
||||
|
||||
class NotificationsManager(private val context: Context) {
|
||||
private val seenNotifications: MutableMap<String, Boolean>
|
||||
private var apiClient: ApiClient? = null
|
||||
|
||||
lateinit var apiClient: WeakReference<ApiClient>
|
||||
private val notifications: BehaviorSubject<List<Notification>>
|
||||
|
||||
private var lastNotificationHandling: Date? = null
|
||||
|
||||
val displayNotificationEvents: Flowable<Notification>
|
||||
get() {
|
||||
return displayNotificationSubject.toFlowable(BackpressureStrategy.DROP)
|
||||
}
|
||||
|
||||
init {
|
||||
this.seenNotifications = HashMap()
|
||||
this.notifications = BehaviorSubject.create()
|
||||
|
|
@ -48,11 +62,7 @@ class NotificationsManager(private val context: Context) {
|
|||
return this.notifications.value?.find { it.id == id }
|
||||
}
|
||||
|
||||
fun setApiClient(apiClient: ApiClient?) {
|
||||
this.apiClient = apiClient
|
||||
}
|
||||
|
||||
private fun handlePopupNotifications(notifications: List<Notification>): Boolean? {
|
||||
private fun handlePopupNotifications(notifications: List<Notification>): Boolean {
|
||||
val now = Date()
|
||||
if (now.time - (lastNotificationHandling?.time ?: 0) < 300) {
|
||||
return true
|
||||
|
|
@ -62,116 +72,56 @@ class NotificationsManager(private val context: Context) {
|
|||
.filter { !this.seenNotifications.containsKey(it.id) }
|
||||
.map {
|
||||
val notificationDisplayed = when (it.type) {
|
||||
Notification.Type.LOGIN_INCENTIVE.type -> displayLoginIncentiveNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_PARTY_UP.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_PARTY_ON.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_BEAST_MASTER.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_MOUNT_MASTER.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_TRIAD_BINGO.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_GUILD_JOINED.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_CHALLENGE_JOINED.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_INVITED_FRIEND.type -> displayAchievementNotification(it)
|
||||
Notification.Type.WON_CHALLENGE.type -> displayWonChallengeNotificaiton(it)
|
||||
Notification.Type.ACHIEVEMENT_PARTY_UP.type -> true
|
||||
Notification.Type.ACHIEVEMENT_PARTY_ON.type -> true
|
||||
Notification.Type.ACHIEVEMENT_BEAST_MASTER.type -> true
|
||||
Notification.Type.ACHIEVEMENT_MOUNT_MASTER.type -> true
|
||||
Notification.Type.ACHIEVEMENT_TRIAD_BINGO.type -> true
|
||||
Notification.Type.ACHIEVEMENT_GUILD_JOINED.type -> true
|
||||
Notification.Type.ACHIEVEMENT_CHALLENGE_JOINED.type -> true
|
||||
Notification.Type.ACHIEVEMENT_INVITED_FRIEND.type -> true
|
||||
|
||||
Notification.Type.ACHIEVEMENT_ALL_YOUR_BASE.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_BACK_TO_BASICS.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_JUST_ADD_WATER.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_LOST_MASTERCLASSER.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_MIND_OVER_MATTER.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_DUST_DEVIL.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_ARID_AUTHORITY.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_MONSTER_MAGUS.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_UNDEAD_UNDERTAKER.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_PRIMED_FOR_PAINTING.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_PEARLY_PRO.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_TICKLED_PINK.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_ROSY_OUTLOOK.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_BUG_BONANZA.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_BARE_NECESSITIES.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_FRESHWATER_FRIENDS.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_GOOD_AS_GOLD.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_ALL_THAT_GLITTERS.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_GOOD_AS_GOLD.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_BONE_COLLECTOR.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_SKELETON_CREW.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_SEEING_RED.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_RED_LETTER_DAY.type -> displayAchievementNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_ALL_YOUR_BASE.type -> true
|
||||
Notification.Type.ACHIEVEMENT_BACK_TO_BASICS.type -> true
|
||||
Notification.Type.ACHIEVEMENT_JUST_ADD_WATER.type -> true
|
||||
Notification.Type.ACHIEVEMENT_LOST_MASTERCLASSER.type -> true
|
||||
Notification.Type.ACHIEVEMENT_MIND_OVER_MATTER.type -> true
|
||||
Notification.Type.ACHIEVEMENT_DUST_DEVIL.type -> true
|
||||
Notification.Type.ACHIEVEMENT_ARID_AUTHORITY.type -> true
|
||||
Notification.Type.ACHIEVEMENT_MONSTER_MAGUS.type -> true
|
||||
Notification.Type.ACHIEVEMENT_UNDEAD_UNDERTAKER.type -> true
|
||||
Notification.Type.ACHIEVEMENT_PRIMED_FOR_PAINTING.type -> true
|
||||
Notification.Type.ACHIEVEMENT_PEARLY_PRO.type -> true
|
||||
Notification.Type.ACHIEVEMENT_TICKLED_PINK.type -> true
|
||||
Notification.Type.ACHIEVEMENT_ROSY_OUTLOOK.type -> true
|
||||
Notification.Type.ACHIEVEMENT_BUG_BONANZA.type -> true
|
||||
Notification.Type.ACHIEVEMENT_BARE_NECESSITIES.type -> true
|
||||
Notification.Type.ACHIEVEMENT_FRESHWATER_FRIENDS.type -> true
|
||||
Notification.Type.ACHIEVEMENT_GOOD_AS_GOLD.type -> true
|
||||
Notification.Type.ACHIEVEMENT_ALL_THAT_GLITTERS.type -> true
|
||||
Notification.Type.ACHIEVEMENT_GOOD_AS_GOLD.type -> true
|
||||
Notification.Type.ACHIEVEMENT_BONE_COLLECTOR.type -> true
|
||||
Notification.Type.ACHIEVEMENT_SKELETON_CREW.type -> true
|
||||
Notification.Type.ACHIEVEMENT_SEEING_RED.type -> true
|
||||
Notification.Type.ACHIEVEMENT_RED_LETTER_DAY.type -> true
|
||||
|
||||
Notification.Type.ACHIEVEMENT_GENERIC.type -> displayAchievementNotification(
|
||||
it,
|
||||
notifications.find { notif ->
|
||||
notif.type == Notification.Type.ACHIEVEMENT_ONBOARDING_COMPLETE.type
|
||||
} != null
|
||||
)
|
||||
Notification.Type.ACHIEVEMENT_ONBOARDING_COMPLETE.type -> displayAchievementNotification(it)
|
||||
Notification.Type.FIRST_DROP.type -> displayFirstDropNotification(it)
|
||||
Notification.Type.ACHIEVEMENT_GENERIC.type -> true
|
||||
Notification.Type.ACHIEVEMENT_ONBOARDING_COMPLETE.type -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
if (notificationDisplayed == true) {
|
||||
if (notificationDisplayed) {
|
||||
displayNotificationSubject.onNext(it)
|
||||
this.seenNotifications[it.id] = true
|
||||
readNotification(it)
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun displayWonChallengeNotificaiton(notification: Notification): Boolean {
|
||||
EventBus.getDefault().post(ShowWonChallengeDialog(notification.id, notification.data as? ChallengeWonData))
|
||||
return true
|
||||
}
|
||||
|
||||
private fun displayFirstDropNotification(notification: Notification): Boolean {
|
||||
val data = (notification.data as? FirstDropData)
|
||||
EventBus.getDefault().post(ShowFirstDropDialog(data?.egg ?: "", data?.hatchingPotion ?: "", notification.id))
|
||||
return true
|
||||
}
|
||||
|
||||
private fun displayLoginIncentiveNotification(notification: Notification): Boolean? {
|
||||
val notificationData = notification.data as? LoginIncentiveData
|
||||
val nextUnlockText = context.getString(R.string.nextPrizeUnlocks, notificationData?.nextRewardAt)
|
||||
if (notificationData?.rewardKey != null) {
|
||||
val event = ShowCheckinDialog(notification, nextUnlockText, notificationData.nextRewardAt ?: 0)
|
||||
EventBus.getDefault().post(event)
|
||||
} else {
|
||||
val event = ShowSnackbarEvent()
|
||||
event.title = notificationData?.message
|
||||
event.text = nextUnlockText
|
||||
event.type = HabiticaSnackbar.SnackbarDisplayType.BLUE
|
||||
EventBus.getDefault().post(event)
|
||||
if (apiClient != null) {
|
||||
apiClient?.readNotification(notification.id)
|
||||
?.subscribe({}, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun displayAchievementNotification(notification: Notification, isLastOnboardingAchievement: Boolean = false): Boolean {
|
||||
val data = (notification.data as? AchievementData)
|
||||
val achievement = data?.achievement ?: notification.type ?: ""
|
||||
val delay: Long = if (achievement == "createdTask" || achievement == Notification.Type.ACHIEVEMENT_ONBOARDING_COMPLETE.type) {
|
||||
1000
|
||||
} else {
|
||||
200
|
||||
}
|
||||
val sub = Completable.complete()
|
||||
.delay(delay, TimeUnit.MILLISECONDS)
|
||||
.subscribe(
|
||||
{
|
||||
EventBus.getDefault().post(ShowAchievementDialog(achievement, notification.id, data?.message, data?.modalText, isLastOnboardingAchievement))
|
||||
},
|
||||
RxErrorHandler.handleEmptyError()
|
||||
)
|
||||
logOnboardingEvents(achievement)
|
||||
return true
|
||||
}
|
||||
|
||||
private fun logOnboardingEvents(type: String) {
|
||||
if (User.ONBOARDING_ACHIEVEMENT_KEYS.contains(type)) {
|
||||
FirebaseAnalytics.getInstance(context).logEvent(type, null)
|
||||
} else if (type == Notification.Type.ACHIEVEMENT_ONBOARDING_COMPLETE.type) {
|
||||
FirebaseAnalytics.getInstance(context).logEvent(type, null)
|
||||
}
|
||||
private fun readNotification(notification: Notification) {
|
||||
apiClient.get()?.readNotification(notification.id)
|
||||
?.subscribe({ }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,7 +156,6 @@ open class PurchaseHandler(activity: Activity, val analyticsManager: AnalyticsMa
|
|||
purchase.token,
|
||||
object : RequestListener<Any> {
|
||||
override fun onSuccess(o: Any) {
|
||||
// EventBus.getDefault().post(new BoughtGemsEvent(GEMS_TO_ADD));
|
||||
}
|
||||
|
||||
override fun onError(i: Int, e: Exception) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,169 @@
|
|||
package com.habitrpg.android.habitica.interactors
|
||||
|
||||
import android.app.Activity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.lifecycle.LifecycleCoroutineScope
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.google.firebase.analytics.FirebaseAnalytics
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.events.*
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.models.Notification
|
||||
import com.habitrpg.android.habitica.models.notifications.AchievementData
|
||||
import com.habitrpg.android.habitica.models.notifications.ChallengeWonData
|
||||
import com.habitrpg.android.habitica.models.notifications.FirstDropData
|
||||
import com.habitrpg.android.habitica.models.notifications.LoginIncentiveData
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
|
||||
import com.habitrpg.android.habitica.ui.views.dialogs.AchievementDialog
|
||||
import com.habitrpg.android.habitica.ui.views.dialogs.FirstDropDialog
|
||||
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
|
||||
import com.habitrpg.android.habitica.ui.views.dialogs.WonChallengeDialog
|
||||
import io.reactivex.rxjava3.core.Completable
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class ShowNotificationInteractor(private val activity: Activity, private val lifecycleScope: LifecycleCoroutineScope) {
|
||||
|
||||
fun handleNotification(notification: Notification) {
|
||||
when (notification.type) {
|
||||
Notification.Type.LOGIN_INCENTIVE.type -> showCheckinDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_PARTY_UP.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_PARTY_ON.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_BEAST_MASTER.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_MOUNT_MASTER.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_TRIAD_BINGO.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_GUILD_JOINED.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_CHALLENGE_JOINED.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_INVITED_FRIEND.type -> showAchievementDialog(notification)
|
||||
Notification.Type.WON_CHALLENGE.type -> showWonChallengeDialog(notification)
|
||||
|
||||
Notification.Type.ACHIEVEMENT_ALL_YOUR_BASE.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_BACK_TO_BASICS.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_JUST_ADD_WATER.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_LOST_MASTERCLASSER.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_MIND_OVER_MATTER.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_DUST_DEVIL.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_ARID_AUTHORITY.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_MONSTER_MAGUS.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_UNDEAD_UNDERTAKER.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_PRIMED_FOR_PAINTING.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_PEARLY_PRO.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_TICKLED_PINK.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_ROSY_OUTLOOK.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_BUG_BONANZA.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_BARE_NECESSITIES.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_FRESHWATER_FRIENDS.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_GOOD_AS_GOLD.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_ALL_THAT_GLITTERS.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_GOOD_AS_GOLD.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_BONE_COLLECTOR.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_SKELETON_CREW.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_SEEING_RED.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_RED_LETTER_DAY.type -> showAchievementDialog(notification)
|
||||
|
||||
Notification.Type.ACHIEVEMENT_GENERIC.type -> showAchievementDialog(notification)
|
||||
Notification.Type.ACHIEVEMENT_ONBOARDING_COMPLETE.type -> showAchievementDialog(notification)
|
||||
Notification.Type.FIRST_DROP.type -> showFirstDropDialog(notification)
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun showCheckinDialog(notification: Notification) {
|
||||
val notificationData = notification.data as? LoginIncentiveData
|
||||
val nextUnlockText = activity.getString(R.string.nextPrizeUnlocks, notificationData?.nextRewardAt)
|
||||
if (notificationData?.rewardKey != null) {
|
||||
val title = notificationData.message
|
||||
|
||||
val factory = LayoutInflater.from(activity)
|
||||
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)
|
||||
if (imageKey?.contains("armor") == true) {
|
||||
imageKey = "slim_$imageKey"
|
||||
}
|
||||
DataBindingUtils.loadImage(imageView, imageKey)
|
||||
|
||||
val youEarnedMessage = activity.getString(R.string.checkInRewardEarned, notificationData?.rewardText)
|
||||
val youEarnedTexView = view.findViewById(R.id.you_earned_message) as? TextView
|
||||
youEarnedTexView?.text = youEarnedMessage
|
||||
|
||||
val nextUnlockTextView = view.findViewById(R.id.next_unlock_message) as? TextView
|
||||
if ((notificationData.nextRewardAt ?: 0) > 0) {
|
||||
nextUnlockTextView?.text = nextUnlockText
|
||||
} else {
|
||||
nextUnlockTextView?.visibility = View.GONE
|
||||
}
|
||||
|
||||
lifecycleScope.launch(context = Dispatchers.Main) {
|
||||
val alert = HabiticaAlertDialog(activity)
|
||||
alert.setAdditionalContentView(view)
|
||||
alert.setTitle(title)
|
||||
alert.addButton(R.string.see_you_tomorrow, true)
|
||||
alert.show()
|
||||
}
|
||||
} else {
|
||||
val event = ShowSnackbarEvent()
|
||||
event.title = notificationData?.message
|
||||
event.text = nextUnlockText
|
||||
event.type = HabiticaSnackbar.SnackbarDisplayType.BLUE
|
||||
EventBus.getDefault().post(event)
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun showAchievementDialog(notification: Notification) {
|
||||
val data = (notification.data as? AchievementData) ?: return
|
||||
val achievement = data.achievement ?: notification.type ?: ""
|
||||
val delayTime: Long = if (achievement == "createdTask" || achievement == Notification.Type.ACHIEVEMENT_ONBOARDING_COMPLETE.type) {
|
||||
1000
|
||||
} else {
|
||||
200
|
||||
}
|
||||
lifecycleScope.launch() {
|
||||
delay(delayTime)
|
||||
lifecycleScope.launch(context = Dispatchers.Main) {
|
||||
val dialog = AchievementDialog(activity)
|
||||
dialog.isLastOnboardingAchievement = data.isLastOnboardingAchievement
|
||||
dialog.setType(data.achievement ?: "", data.message, data.modalText)
|
||||
dialog.enqueue()
|
||||
}
|
||||
}
|
||||
logOnboardingEvents(achievement)
|
||||
}
|
||||
|
||||
private fun showFirstDropDialog(notification: Notification) {
|
||||
val data = notification.data as? FirstDropData ?: return
|
||||
lifecycleScope.launch(context = Dispatchers.Main) {
|
||||
val dialog = FirstDropDialog(activity)
|
||||
dialog.configure(data.egg ?: "", data.hatchingPotion ?: "")
|
||||
dialog.enqueue()
|
||||
}
|
||||
}
|
||||
|
||||
private fun showWonChallengeDialog(notification: Notification) {
|
||||
lifecycleScope.launch(context = Dispatchers.Main) {
|
||||
val dialog = WonChallengeDialog(activity)
|
||||
dialog.configure(notification.data as? ChallengeWonData)
|
||||
dialog.enqueue()
|
||||
}
|
||||
}
|
||||
|
||||
private fun logOnboardingEvents(type: String) {
|
||||
if (User.ONBOARDING_ACHIEVEMENT_KEYS.contains(type)) {
|
||||
FirebaseAnalytics.getInstance(activity).logEvent(type, null)
|
||||
} else if (type == Notification.Type.ACHIEVEMENT_ONBOARDING_COMPLETE.type) {
|
||||
FirebaseAnalytics.getInstance(activity).logEvent(type, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package com.habitrpg.android.habitica.models.notifications
|
|||
|
||||
open class AchievementData : NotificationData {
|
||||
|
||||
val isLastOnboardingAchievement: Boolean = false
|
||||
var achievement: String? = null
|
||||
var message: String? = null
|
||||
var modalText: String? = null
|
||||
|
|
|
|||
|
|
@ -1,58 +0,0 @@
|
|||
package com.habitrpg.android.habitica.modules;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import com.habitrpg.android.habitica.api.HostConfig;
|
||||
import com.habitrpg.android.habitica.api.MaintenanceApiService;
|
||||
import com.habitrpg.android.habitica.data.ApiClient;
|
||||
import com.habitrpg.android.habitica.data.implementation.ApiClientImpl;
|
||||
import com.habitrpg.android.habitica.helpers.NotificationsManager;
|
||||
import com.habitrpg.android.habitica.helpers.KeyHelper;
|
||||
import com.habitrpg.android.habitica.proxy.AnalyticsManager;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory;
|
||||
import retrofit2.converter.gson.GsonConverterFactory;
|
||||
|
||||
@Module
|
||||
public class ApiModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public HostConfig providesHostConfig(SharedPreferences sharedPreferences, @Nullable KeyHelper keyHelper, Context context) {
|
||||
return new HostConfig(sharedPreferences, keyHelper, context);
|
||||
}
|
||||
|
||||
@Provides
|
||||
public GsonConverterFactory providesGsonConverterFactory() {
|
||||
return ApiClientImpl.Companion.createGsonFactory();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public NotificationsManager providesPopupNotificationsManager(Context context) {
|
||||
return new NotificationsManager(context);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public ApiClient providesApiHelper(GsonConverterFactory gsonConverter, HostConfig hostConfig, AnalyticsManager analyticsManager, NotificationsManager notificationsManager, Context context) {
|
||||
return new ApiClientImpl(gsonConverter, hostConfig, analyticsManager, notificationsManager, context);
|
||||
}
|
||||
|
||||
@Provides
|
||||
public MaintenanceApiService providesMaintenanceApiService(GsonConverterFactory gsonConverter) {
|
||||
Retrofit adapter = new Retrofit.Builder()
|
||||
.baseUrl("https://habitica-assets.s3.amazonaws.com/mobileApp/endpoint/")
|
||||
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
|
||||
.addConverterFactory(gsonConverter)
|
||||
.build();
|
||||
return adapter.create(MaintenanceApiService.class);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
package com.habitrpg.android.habitica.modules
|
||||
|
||||
import android.content.Context
|
||||
import com.habitrpg.android.habitica.data.implementation.ApiClientImpl.Companion.createGsonFactory
|
||||
import android.content.SharedPreferences
|
||||
import com.habitrpg.android.habitica.helpers.KeyHelper
|
||||
import com.habitrpg.android.habitica.api.HostConfig
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
import com.habitrpg.android.habitica.data.implementation.ApiClientImpl
|
||||
import com.habitrpg.android.habitica.helpers.NotificationsManager
|
||||
import com.habitrpg.android.habitica.proxy.AnalyticsManager
|
||||
import com.habitrpg.android.habitica.data.ApiClient
|
||||
import com.habitrpg.android.habitica.api.MaintenanceApiService
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory
|
||||
import java.lang.ref.WeakReference
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
open class ApiModule {
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesHostConfig(
|
||||
sharedPreferences: SharedPreferences,
|
||||
keyHelper: KeyHelper?,
|
||||
context: Context
|
||||
): HostConfig {
|
||||
return HostConfig(sharedPreferences, keyHelper, context)
|
||||
}
|
||||
|
||||
@Provides
|
||||
fun providesGsonConverterFactory(): GsonConverterFactory {
|
||||
return createGsonFactory()
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesPopupNotificationsManager(): NotificationsManager {
|
||||
return NotificationsManager()
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providesApiHelper(
|
||||
gsonConverter: GsonConverterFactory,
|
||||
hostConfig: HostConfig,
|
||||
analyticsManager: AnalyticsManager,
|
||||
notificationsManager: NotificationsManager,
|
||||
context: Context
|
||||
): ApiClient {
|
||||
val apiClient = ApiClientImpl(
|
||||
gsonConverter,
|
||||
hostConfig,
|
||||
analyticsManager,
|
||||
notificationsManager,
|
||||
context
|
||||
)
|
||||
notificationsManager.apiClient = WeakReference(apiClient)
|
||||
return apiClient
|
||||
}
|
||||
|
||||
@Provides
|
||||
fun providesMaintenanceApiService(gsonConverter: GsonConverterFactory): MaintenanceApiService {
|
||||
val adapter = Retrofit.Builder()
|
||||
.baseUrl("https://habitica-assets.s3.amazonaws.com/mobileApp/endpoint/")
|
||||
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
|
||||
.addConverterFactory(gsonConverter)
|
||||
.build()
|
||||
return adapter.create(MaintenanceApiService::class.java)
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,6 @@ import androidx.core.os.bundleOf
|
|||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.data.UserRepository
|
||||
import com.habitrpg.android.habitica.databinding.AvatarWithBarsBinding
|
||||
import com.habitrpg.android.habitica.events.BoughtGemsEvent
|
||||
import com.habitrpg.android.habitica.helpers.HealthFormatter
|
||||
import com.habitrpg.android.habitica.helpers.MainNavigationController
|
||||
import com.habitrpg.android.habitica.models.Avatar
|
||||
|
|
@ -17,7 +16,6 @@ import com.habitrpg.android.habitica.models.user.Stats
|
|||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
|
||||
import io.reactivex.rxjava3.disposables.Disposable
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import java.util.*
|
||||
import kotlin.math.floor
|
||||
|
||||
|
|
@ -111,13 +109,6 @@ class AvatarWithBarsViewModel(private val context: Context, private val binding:
|
|||
binding.mpBar.set(floor(value.toDouble()), cachedMaxMana.toDouble())
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun onEvent(gemsEvent: BoughtGemsEvent) {
|
||||
var gems = userObject?.gemCount ?: 0
|
||||
gems += gemsEvent.NewGemsToAdd
|
||||
binding.currencyView.gems = gems.toDouble()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private fun setUserLevel(context: Context, textView: TextView, level: Int?) {
|
||||
textView.text = context.getString(R.string.user_level, level)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import androidx.appcompat.app.AppCompatActivity
|
|||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.habitrpg.android.habitica.HabiticaApplication
|
||||
import com.habitrpg.android.habitica.HabiticaBaseApplication
|
||||
|
|
@ -24,14 +25,21 @@ import com.habitrpg.android.habitica.extensions.getThemeColor
|
|||
import com.habitrpg.android.habitica.extensions.isUsingNightModeResources
|
||||
import com.habitrpg.android.habitica.extensions.updateStatusBarColor
|
||||
import com.habitrpg.android.habitica.helpers.LanguageHelper
|
||||
import com.habitrpg.android.habitica.helpers.NotificationsManager
|
||||
import com.habitrpg.android.habitica.helpers.RxErrorHandler
|
||||
import com.habitrpg.android.habitica.interactors.ShowNotificationInteractor
|
||||
import com.habitrpg.android.habitica.ui.helpers.ToolbarColorHelper
|
||||
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
abstract class BaseActivity : AppCompatActivity() {
|
||||
@Inject
|
||||
lateinit var notificationsManager: NotificationsManager
|
||||
|
||||
private var currentTheme: String? = null
|
||||
private var isNightMode: Boolean = false
|
||||
internal var forcedTheme: String? = null
|
||||
|
|
@ -76,6 +84,12 @@ abstract class BaseActivity : AppCompatActivity() {
|
|||
injectActivity(HabiticaBaseApplication.userComponent)
|
||||
setContentView(getContentView())
|
||||
compositeSubscription = CompositeDisposable()
|
||||
compositeSubscription.add(notificationsManager.displayNotificationEvents.subscribe(
|
||||
{
|
||||
ShowNotificationInteractor(this, lifecycleScope).handleNotification(it)
|
||||
},
|
||||
RxErrorHandler.handleEmptyError()
|
||||
))
|
||||
}
|
||||
|
||||
override fun onRestart() {
|
||||
|
|
|
|||
|
|
@ -103,7 +103,6 @@ class GemPurchaseActivity : BaseActivity() {
|
|||
fun onConsumablePurchased(event: ConsumablePurchasedEvent) {
|
||||
if (isActivityVisible) {
|
||||
purchaseHandler?.consumePurchase(event.purchase)
|
||||
compositeSubscription.add(userRepository.retrieveUser(false).subscribe({}, RxErrorHandler.handleEmptyError()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -783,81 +783,6 @@ open class MainActivity : BaseActivity(), TutorialView.OnTutorialReaction {
|
|||
HabiticaSnackbar.showSnackbar(snackbarContainer, event.leftImage, event.title, event.text, event.specialView, event.rightIcon, event.rightTextColor, event.rightText, event.type)
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun showCheckinDialog(event: ShowCheckinDialog) {
|
||||
val notificationData = event.notification.data as? LoginIncentiveData
|
||||
val title = notificationData?.message
|
||||
|
||||
val factory = LayoutInflater.from(this)
|
||||
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)
|
||||
if (imageKey?.contains("armor") == true) {
|
||||
imageKey = "slim_$imageKey"
|
||||
}
|
||||
DataBindingUtils.loadImage(imageView, imageKey)
|
||||
|
||||
val youEarnedMessage = this.getString(R.string.checkInRewardEarned, notificationData?.rewardText)
|
||||
val youEarnedTexView = view.findViewById(R.id.you_earned_message) as? TextView
|
||||
youEarnedTexView?.text = youEarnedMessage
|
||||
|
||||
val nextUnlockTextView = view.findViewById(R.id.next_unlock_message) as? TextView
|
||||
if (event.nextUnlockCount > 0) {
|
||||
nextUnlockTextView?.text = event.nextUnlockText
|
||||
} else {
|
||||
nextUnlockTextView?.visibility = View.GONE
|
||||
}
|
||||
|
||||
lifecycleScope.launch(context = Dispatchers.Main) {
|
||||
val alert = HabiticaAlertDialog(this@MainActivity)
|
||||
alert.setAdditionalContentView(view)
|
||||
alert.setTitle(title)
|
||||
alert.addButton(R.string.see_you_tomorrow, true) { _, _ ->
|
||||
apiClient.readNotification(event.notification.id)
|
||||
.subscribe({ }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
alert.show()
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun showAchievementDialog(event: ShowAchievementDialog) {
|
||||
retrieveUser(true)
|
||||
lifecycleScope.launch(context = Dispatchers.Main) {
|
||||
val dialog = AchievementDialog(this@MainActivity)
|
||||
dialog.isLastOnboardingAchievement = event.isLastOnboardingAchievement
|
||||
dialog.setType(event.type, event.message, event.text)
|
||||
dialog.enqueue()
|
||||
apiClient.readNotification(event.id)
|
||||
.subscribe({ }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun showFirstDropDialog(event: ShowFirstDropDialog) {
|
||||
retrieveUser(true)
|
||||
lifecycleScope.launch(context = Dispatchers.Main) {
|
||||
val dialog = FirstDropDialog(this@MainActivity)
|
||||
dialog.configure(event.egg, event.hatchingPotion)
|
||||
dialog.enqueue()
|
||||
apiClient.readNotification(event.id)
|
||||
.subscribe({ }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
fun showWonChallengeDialog(event: ShowWonChallengeDialog) {
|
||||
retrieveUser(true)
|
||||
lifecycleScope.launch(context = Dispatchers.Main) {
|
||||
val dialog = WonChallengeDialog(this@MainActivity)
|
||||
dialog.configure(event.data)
|
||||
dialog.enqueue()
|
||||
apiClient.readNotification(event.id)
|
||||
.subscribe({ }, RxErrorHandler.handleEmptyError())
|
||||
}
|
||||
}
|
||||
|
||||
override fun onEvent(event: ShowConnectionProblemEvent) {
|
||||
if (event.title != null) {
|
||||
super.onEvent(event)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import android.content.SharedPreferences
|
|||
import android.os.Build
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.core.content.edit
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import com.facebook.AccessToken
|
||||
import com.facebook.CallbackManager
|
||||
|
|
@ -92,6 +91,9 @@ class AuthenticationViewModel() {
|
|||
response.newUser = result.newUser
|
||||
onSuccess(response)
|
||||
}
|
||||
else -> {
|
||||
|
||||
}
|
||||
}
|
||||
}.show()
|
||||
}
|
||||
|
|
@ -101,7 +103,7 @@ class AuthenticationViewModel() {
|
|||
loginManager.registerCallback(
|
||||
callbackManager,
|
||||
object : FacebookCallback<LoginResult> {
|
||||
override fun onSuccess(loginResult: LoginResult) {
|
||||
override fun onSuccess(result: LoginResult) {
|
||||
val accessToken = AccessToken.getCurrentAccessToken()
|
||||
compositeSubscription.add(
|
||||
apiClient.connectSocial("facebook", accessToken?.userId ?: "", accessToken?.token ?: "")
|
||||
|
|
@ -113,8 +115,8 @@ class AuthenticationViewModel() {
|
|||
|
||||
override fun onCancel() { /* no-on */ }
|
||||
|
||||
override fun onError(exception: FacebookException) {
|
||||
RxErrorHandler.reportError(exception)
|
||||
override fun onError(error: FacebookException) {
|
||||
RxErrorHandler.reportError(error)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
@ -124,10 +126,6 @@ class AuthenticationViewModel() {
|
|||
loginManager.logInWithReadPermissions(activity, listOf("user_friends"))
|
||||
}
|
||||
|
||||
fun handleFacebookLogin(fragment: Fragment) {
|
||||
loginManager.logInWithReadPermissions(fragment, listOf("user_friends"))
|
||||
}
|
||||
|
||||
fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?, onSuccess: (UserAuthResponse) -> Unit) {
|
||||
callbackManager.onActivityResult(requestCode, resultCode, data)
|
||||
|
||||
|
|
@ -180,7 +178,7 @@ class AuthenticationViewModel() {
|
|||
Flowable.defer {
|
||||
try {
|
||||
@Suppress("Deprecation")
|
||||
return@defer Flowable.just(GoogleAuthUtil.getToken(activity, googleEmail, scopes))
|
||||
return@defer Flowable.just(GoogleAuthUtil.getToken(activity, googleEmail ?: "", scopes))
|
||||
} catch (e: IOException) {
|
||||
throw Exceptions.propagate(e)
|
||||
} catch (e: GoogleAuthException) {
|
||||
|
|
@ -225,7 +223,7 @@ class AuthenticationViewModel() {
|
|||
e.connectionStatusCode,
|
||||
activity,
|
||||
null,
|
||||
AuthenticationViewModel.REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR
|
||||
REQUEST_CODE_RECOVER_FROM_PLAY_SERVICES_ERROR
|
||||
) {
|
||||
}
|
||||
return
|
||||
|
|
@ -247,8 +245,8 @@ class AuthenticationViewModel() {
|
|||
if (result != ConnectionResult.SUCCESS) {
|
||||
if (googleAPI.isUserResolvableError(result)) {
|
||||
googleAPI.getErrorDialog(activity, result,
|
||||
AuthenticationViewModel.PLAY_SERVICES_RESOLUTION_REQUEST
|
||||
).show()
|
||||
PLAY_SERVICES_RESOLUTION_REQUEST
|
||||
)?.show()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.6.0'
|
||||
ext.kotlin_version = '1.6.10'
|
||||
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
maven { url "https://plugins.gradle.org/m2/" }
|
||||
}
|
||||
dependencies {
|
||||
|
|
@ -15,7 +14,7 @@ buildscript {
|
|||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.1'
|
||||
classpath "io.realm:realm-gradle-plugin:10.8.1"
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.18.1"
|
||||
classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.19.0"
|
||||
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.3.5"
|
||||
classpath 'com.google.firebase:perf-plugin:1.4.0'
|
||||
}
|
||||
|
|
|
|||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
|
@ -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-7.0.2-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ apply plugin: 'kotlin-multiplatform'
|
|||
apply plugin: 'kotlin-kapt'
|
||||
|
||||
android {
|
||||
compileSdkVersion 31
|
||||
compileSdkVersion 32
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 31
|
||||
targetSdkVersion 32
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
|
|
|
|||
Loading…
Reference in a new issue