diff --git a/Habitica/build.gradle b/Habitica/build.gradle index 90d0bc88d..6f0f98807 100644 --- a/Habitica/build.gradle +++ b/Habitica/build.gradle @@ -152,7 +152,7 @@ android { buildConfigField "String", "TESTING_LEVEL", "\"production\"" multiDexEnabled true - versionCode 2211 + versionCode 2219 versionName "2.1" } diff --git a/Habitica/res/layout/dialog_habitica_base.xml b/Habitica/res/layout/dialog_habitica_base.xml index 121d68f3c..245fb5396 100644 --- a/Habitica/res/layout/dialog_habitica_base.xml +++ b/Habitica/res/layout/dialog_habitica_base.xml @@ -26,7 +26,6 @@ android:layout_height="wrap_content" android:gravity="center_horizontal" android:paddingBottom="@dimen/spacing_large" - style="@style/Headline6" tools:text="This is the title" android:visibility="gone" tools:visibility="visible" @@ -41,8 +40,6 @@ android:gravity="center_horizontal" android:visibility="gone" tools:visibility="visible" - android:textColor="?textColorSecondary" - style="@style/Body2" tools:text="This is the message" android:paddingBottom="@dimen/spacing_medium" android:paddingStart="@dimen/alert_side_padding" @@ -99,7 +96,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/close" - android:textColor="?colorAccent" android:background="@drawable/alert_dialog_background" android:layout_marginTop="@dimen/spacing_large" android:visibility="gone" diff --git a/Habitica/res/values/strings.xml b/Habitica/res/values/strings.xml index 5d6242b71..c27c01c44 100644 --- a/Habitica/res/values/strings.xml +++ b/Habitica/res/values/strings.xml @@ -815,4 +815,22 @@ %s was removed from the group You open the box and receive a %s See what\'s new + View Achievements + You got an Achievement! + Party Up + You teamed up with a party member! + Party On + Your party grew to 4 members! + Beast Master + You have earned the \\\"Beast Master\\\" Achievement for collecting all the pets! + Mount Master + You have earned the \\\"Mount Master\\\" achievement for taming all the mounts! + Triad Bingo + You have earned the \\\"Triad Bingo\\\" achievement for finding all the pets, taming all the mounts, and finding all the pets again! + Joined a Guild + Ventured into the social side of Habitica by joining a Guild! + Joined a Challenge + You put themselves to the test by joining a Challenge! + Invited a Friend + invitedinvited a friend (or friends) who joined you on your adventure! diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/events/ShowAchievementDialog.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/events/ShowAchievementDialog.kt new file mode 100644 index 000000000..26c8bce5c --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/events/ShowAchievementDialog.kt @@ -0,0 +1,3 @@ +package com.habitrpg.android.habitica.events + +class ShowAchievementDialog(var type: String) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/NotificationsManager.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/NotificationsManager.kt index 863e86f94..996494a24 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/NotificationsManager.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/NotificationsManager.kt @@ -3,6 +3,7 @@ package com.habitrpg.android.habitica.helpers import android.content.Context import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.data.ApiClient +import com.habitrpg.android.habitica.events.ShowAchievementDialog import com.habitrpg.android.habitica.events.ShowCheckinDialog import com.habitrpg.android.habitica.events.ShowSnackbarEvent import com.habitrpg.android.habitica.models.Notification @@ -10,18 +11,13 @@ import com.habitrpg.android.habitica.models.notifications.LoginIncentiveData import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar import io.reactivex.BackpressureStrategy import io.reactivex.Flowable -import io.reactivex.functions.Consumer +import io.reactivex.disposables.CompositeDisposable import io.reactivex.subjects.BehaviorSubject import org.greenrobot.eventbus.EventBus import java.util.* -/** - * Created by krh12 on 12/9/2016. - */ - class NotificationsManager (private val context: Context) { - // @TODO: A queue for displaying alert dialogues - + private var compositeSubscription = CompositeDisposable() private val seenNotifications: MutableMap private var apiClient: ApiClient? = null @@ -58,12 +54,25 @@ class NotificationsManager (private val context: Context) { .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) else -> false } if (notificationDisplayed == true) { this.seenNotifications[it.id] = true + /*if (apiClient != null) { + apiClient?.readNotification(it.id) + ?.subscribe(Consumer {}, RxErrorHandler.handleEmptyError()) + }*/ } + } return true @@ -83,12 +92,13 @@ class NotificationsManager (private val context: Context) { event.text = nextUnlockText event.type = HabiticaSnackbar.SnackbarDisplayType.BLUE EventBus.getDefault().post(event) - if (apiClient != null) { - // @TODO: This should be handled somewhere else? MAybe we notifiy via event - apiClient?.readNotification(notification.id) - ?.subscribe(Consumer {}, RxErrorHandler.handleEmptyError()) - } + } return true } + + private fun displayAchievementNotification(notification: Notification): Boolean { + EventBus.getDefault().post(ShowAchievementDialog(notification.type ?: "")) + return true + } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/LevelUpUseCase.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/LevelUpUseCase.kt index ed002e14e..7d1bcd007 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/LevelUpUseCase.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/interactors/LevelUpUseCase.kt @@ -50,7 +50,7 @@ constructor(private val soundManager: SoundManager, threadExecutor: ThreadExecut alert.addButton(R.string.not_now, false) if (!requestValues.activity.isFinishing) { - alert.show() + alert.enqueue() } } else { val customView = requestValues.activity.layoutInflater.inflate(R.layout.dialog_levelup, null) @@ -76,7 +76,7 @@ constructor(private val soundManager: SoundManager, threadExecutor: ThreadExecut } if (!requestValues.activity.isFinishing) { - alert.show() + alert.enqueue() } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/Notification.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/models/Notification.kt index b594e26a0..b4c16138f 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/Notification.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/Notification.kt @@ -14,10 +14,20 @@ class Notification { GROUP_TASK_REQUIRES_APPROVAL("GROUP_TASK_REQUIRES_APPROVAL"), UNALLOCATED_STATS_POINTS("UNALLOCATED_STATS_POINTS"), + //Achievements + ACHIEVEMENT_PARTY_UP("ACHIEVEMENT_PARTY_UP"), + ACHIEVEMENT_PARTY_ON("ACHIEVEMENT_PARTY_ON"), + ACHIEVEMENT_BEAST_MASTER("ACHIEVEMENT_BEAST_MASTER"), + ACHIEVEMENT_MOUNT_MASTER("ACHIEVEMENT_MOUNT_MASTER"), + ACHIEVEMENT_TRIAD_BINGO("ACHIEVEMENT_TRIAD_BINGO"), + ACHIEVEMENT_GUILD_JOINED("GUILD_JOINED_ACHIEVEMENT"), + ACHIEVEMENT_CHALLENGE_JOINED("CHALLENGE_JOINED_ACHIEVEMENT"), + ACHIEVEMENT_INVITED_FRIEND("INVITED_FRIEND_ACHIEVEMENT"), + // Custom notification types (created by this app) GUILD_INVITATION("GUILD_INVITATION"), PARTY_INVITATION("PARTY_INVITATION"), - QUEST_INVITATION("QUEST_INVITATION"); + QUEST_INVITATION("QUEST_INVITATION"), } var id: String = "" diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/BaseActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/BaseActivity.kt index 9ac6af5b6..8133d8f76 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/BaseActivity.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/BaseActivity.kt @@ -3,10 +3,10 @@ package com.habitrpg.android.habitica.ui.activities import android.content.SharedPreferences import android.content.res.Configuration import android.os.Bundle -import androidx.preference.PreferenceManager import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.widget.Toolbar +import androidx.preference.PreferenceManager import com.habitrpg.android.habitica.HabiticaApplication import com.habitrpg.android.habitica.HabiticaBaseApplication import com.habitrpg.android.habitica.R @@ -139,7 +139,7 @@ abstract class BaseActivity : AppCompatActivity() { alert.setTitle(event.title) alert.setMessage(event.message) alert.addButton(android.R.string.ok, isPrimary = true, isDestructive = false, function = null) - alert.show() + alert.enqueue() } fun reload() { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ChallengeFormActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ChallengeFormActivity.kt index 47fef591e..67c7de59a 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ChallengeFormActivity.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ChallengeFormActivity.kt @@ -197,7 +197,7 @@ class ChallengeFormActivity : BaseActivity() { if (errorMessages.count() > 0) { val alert = HabiticaAlertDialog(this) alert.setMessage(errorMessages.joinToString("\n")) - alert.show() + alert.enqueue() } return errorMessages.size == 0 } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ClassSelectionActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ClassSelectionActivity.kt index d94fcca3f..3544a903f 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ClassSelectionActivity.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/ClassSelectionActivity.kt @@ -20,8 +20,8 @@ import com.habitrpg.android.habitica.helpers.RxErrorHandler import com.habitrpg.android.habitica.models.user.* import com.habitrpg.android.habitica.ui.AvatarView import com.habitrpg.android.habitica.ui.helpers.bindView -import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper +import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog import io.reactivex.functions.Consumer import javax.inject.Inject @@ -264,7 +264,7 @@ class ClassSelectionActivity : BaseActivity(), Consumer { alert.setTitle(getString(R.string.class_changed, className)) alert.setMessage(getString(R.string.class_changed_description)) alert.addButton(getString(R.string.complete_tutorial), true) - alert.show() + alert.enqueue() } private fun optOutOfClasses() { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/GiftIAPActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/GiftIAPActivity.kt index 1cfb87485..17a641765 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/GiftIAPActivity.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/GiftIAPActivity.kt @@ -273,7 +273,7 @@ class GiftIAPActivity: BaseActivity() { dialog.dismiss() finish() } - alert.show() + alert.enqueue() } private fun consumePurchase(purchase: Purchase) { diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.kt index 29fd8a46c..bb86087c2 100755 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.kt @@ -11,7 +11,6 @@ import android.graphics.Bitmap import android.graphics.Canvas import android.os.Bundle import android.os.Handler -import androidx.preference.PreferenceManager import android.util.Log import android.view.* import android.widget.FrameLayout @@ -35,10 +34,7 @@ import com.habitrpg.android.habitica.api.HostConfig import com.habitrpg.android.habitica.api.MaintenanceApiService import com.habitrpg.android.habitica.components.UserComponent import com.habitrpg.android.habitica.data.* -import com.habitrpg.android.habitica.events.ShareEvent -import com.habitrpg.android.habitica.events.ShowCheckinDialog -import com.habitrpg.android.habitica.events.ShowConnectionProblemEvent -import com.habitrpg.android.habitica.events.ShowSnackbarEvent +import com.habitrpg.android.habitica.events.* import com.habitrpg.android.habitica.events.commands.FeedCommand import com.habitrpg.android.habitica.extensions.DateUtils import com.habitrpg.android.habitica.extensions.subscribeWithErrorHandler @@ -67,6 +63,7 @@ import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar.SnackbarDisplayType import com.habitrpg.android.habitica.ui.views.ValueBar +import com.habitrpg.android.habitica.ui.views.dialogs.AchievementDialog import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog import com.habitrpg.android.habitica.ui.views.navigation.HabiticaBottomNavigationView import com.habitrpg.android.habitica.ui.views.yesterdailies.YesterdailyDialog @@ -423,7 +420,7 @@ open class MainActivity : BaseActivity(), TutorialView.OnTutorialReaction { EventBus.getDefault().post(event1) hatchingDialog.dismiss() } - dialog.show() + dialog.enqueue() } }, RxErrorHandler.handleEmptyError())) } @@ -470,7 +467,7 @@ open class MainActivity : BaseActivity(), TutorialView.OnTutorialReaction { } } soundManager.loadAndPlayAudio(SoundManager.SoundDeath) - this.faintDialog?.show() + this.faintDialog?.enqueue() } } @@ -655,6 +652,18 @@ open class MainActivity : BaseActivity(), TutorialView.OnTutorialReaction { }, RxErrorHandler.handleEmptyError())) } + @Subscribe + fun showAchievementDialog(event: ShowAchievementDialog) { + compositeSubscription.add(Completable.complete() + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(Action { + val dialog = AchievementDialog(this) + dialog.setType(event.type) + dialog.enqueue() + }, RxErrorHandler.handleEmptyError())) + + } + override fun onEvent(event: ShowConnectionProblemEvent) { if (event.title != null) { super.onEvent(event) @@ -694,7 +703,7 @@ open class MainActivity : BaseActivity(), TutorialView.OnTutorialReaction { EventBus.getDefault().post(event1) hatchingDialog.dismiss() } - dialog.show() + dialog.enqueue() }.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())) } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/dialogs/AchievementDialog.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/dialogs/AchievementDialog.kt new file mode 100644 index 000000000..8e82606ec --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/dialogs/AchievementDialog.kt @@ -0,0 +1,33 @@ +package com.habitrpg.android.habitica.ui.views.dialogs + +import android.content.Context +import com.habitrpg.android.habitica.R +import com.habitrpg.android.habitica.helpers.MainNavigationController +import com.habitrpg.android.habitica.models.Notification + +class AchievementDialog(context: Context) : HabiticaAlertDialog(context) { + + fun setType(type: String) { + when (type) { + Notification.Type.ACHIEVEMENT_PARTY_UP.type -> configure(R.string.partyUpTitle, R.string.partyUpDescription, "partyUp") + Notification.Type.ACHIEVEMENT_PARTY_ON.type -> configure(R.string.partyOnTitle, R.string.partyOnDescription, "partyOn") + Notification.Type.ACHIEVEMENT_BEAST_MASTER.type -> configure(R.string.beastMasterTitle, R.string.beastMasterDescription, "rat") + Notification.Type.ACHIEVEMENT_MOUNT_MASTER.type -> configure(R.string.mountMasterTitle, R.string.mountMasterDescription, "wolf") + Notification.Type.ACHIEVEMENT_TRIAD_BINGO.type -> configure(R.string.triadBingoTitle, R.string.triadBingoDescription, "triadbingo") + Notification.Type.ACHIEVEMENT_GUILD_JOINED.type -> configure(R.string.joinedGuildTitle, R.string.joinedGuildDescription, "guild") + Notification.Type.ACHIEVEMENT_CHALLENGE_JOINED.type -> configure(R.string.joinedChallengeTitle, R.string.joinedChallengeDescription, "challenge") + Notification.Type.ACHIEVEMENT_INVITED_FRIEND.type -> configure(R.string.inviteFriendTitle, R.string.inviteFriendDescription, "friends") + } + } + + private fun configure(titleID: Int, descriptionID: Int, iconName: String) { + setTitle(R.string.achievement_title) + + + addButton(R.string.onwards, true) + addButton(R.string.view_achievements, isPrimary = false, isDestructive = false) { _, _ -> + MainNavigationController.navigate(R.id.achievementsFragment) + } + } + +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/dialogs/HabiticaAlertDialog.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/dialogs/HabiticaAlertDialog.kt index 9224d3daa..daf202710 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/dialogs/HabiticaAlertDialog.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/dialogs/HabiticaAlertDialog.kt @@ -152,17 +152,17 @@ open class HabiticaAlertDialog(context: Context) : AlertDialog(context, R.style. fun addButton(string: String, isPrimary: Boolean, isDestructive: Boolean = false, function: ((HabiticaAlertDialog, Int) -> Unit)? = null): Button { val button: Button = if (isPrimary) { if (isDestructive) { - buttonsWrapper.inflate(R.layout.dialog_habitica_primary_destructive_button) as Button + buttonsWrapper.inflate(R.layout.dialog_habitica_primary_destructive_button) as? Button } else { - buttonsWrapper.inflate(R.layout.dialog_habitica_primary_button) as Button + buttonsWrapper.inflate(R.layout.dialog_habitica_primary_button) as? Button } } else { - val button = buttonsWrapper.inflate(R.layout.dialog_habitica_secondary_button) as Button + val button = buttonsWrapper.inflate(R.layout.dialog_habitica_secondary_button) as? Button if (isDestructive) { - button.setTextColor(ContextCompat.getColor(context, R.color.red_100)) + button?.setTextColor(ContextCompat.getColor(context, R.color.red_100)) } button - } + } ?: Button(context) button.text = string button.minWidth = 147.dpToPx(context) button.setScaledPadding(context, 20, 0, 20, 0) @@ -197,4 +197,33 @@ open class HabiticaAlertDialog(context: Context) : AlertDialog(context, R.style. buttonView.layoutParams = layoutParams buttonView.elevation = 10f } + + fun enqueue() { + addToQueue(this) + } + + override fun dismiss() { + showNextInQueue(this) + super.dismiss() + } + + companion object { + private var dialogQueue = mutableListOf() + + private fun showNextInQueue(currentDialog: HabiticaAlertDialog) { + if (dialogQueue.first() == currentDialog) { + dialogQueue.removeAt(0) + } + if (dialogQueue.size > 0) { + dialogQueue[0].show() + } + } + + private fun addToQueue(dialog: HabiticaAlertDialog) { + if (dialogQueue.isEmpty()) { + dialog.show() + } + dialogQueue.add(dialog) + } + } } \ No newline at end of file diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/yesterdailies/YesterdailyDialog.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/yesterdailies/YesterdailyDialog.kt index dbcb5dac0..736d1e280 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/yesterdailies/YesterdailyDialog.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/yesterdailies/YesterdailyDialog.kt @@ -191,7 +191,7 @@ class YesterdailyDialog private constructor(context: Context, private val userRe dialog.setCancelable(false) dialog.setCanceledOnTouchOutside(false) if (!activity.isFinishing) { - dialog.show() + dialog.enqueue() } } }