From a78897cda79da14058f16e53fef8e6a75408ee6e Mon Sep 17 00:00:00 2001 From: Carl Vuorinen Date: Sun, 28 Apr 2019 22:07:25 +0300 Subject: [PATCH] Revert saving notifications to Realm through User, use PopupNotificationsManager instead Combine Notification & GlobalNotification models since they model the same thing --- .../habitica/api/GSonFactoryCreator.java | 4 +- .../data/implementation/ApiClientImpl.kt | 10 +-- .../helpers/PopupNotificationsManager.java | 24 ++++- .../android/habitica/models/Notification.java | 88 ------------------- .../android/habitica/models/Notification.kt | 30 +++++++ .../notifications/GlobalNotification.kt | 65 -------------- .../notifications/GlobalNotificationData.kt | 5 -- .../notifications/LoginIncentiveData.kt | 11 +++ .../notifications/NewChatMessageData.kt | 4 +- .../models/notifications/NewStuffData.kt | 4 +- .../notifications/NotificationData.java | 18 ---- .../models/notifications/NotificationData.kt | 3 + .../models/notifications/NotificationGroup.kt | 4 +- .../notifications/UnallocatedPointsData.kt | 4 +- .../android/habitica/models/user/User.kt | 3 - .../habitica/ui/activities/MainActivity.kt | 8 +- .../ui/activities/NotificationsActivity.kt | 31 +++---- .../ui/viewmodels/NotificationsViewModel.kt | 68 ++++++++------ .../utils/NotificationDeserializer.kt | 12 ++- .../habitica/utils/UserDeserializer.kt | 6 -- 20 files changed, 145 insertions(+), 257 deletions(-) delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/models/Notification.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/models/Notification.kt delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/GlobalNotification.kt delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/GlobalNotificationData.kt create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/LoginIncentiveData.kt delete mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/NotificationData.java create mode 100644 Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/NotificationData.kt diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/api/GSonFactoryCreator.java b/Habitica/src/main/java/com/habitrpg/android/habitica/api/GSonFactoryCreator.java index 3a7fd0536..0499fc277 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/api/GSonFactoryCreator.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/api/GSonFactoryCreator.java @@ -5,6 +5,7 @@ import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; import com.habitrpg.android.habitica.models.ContentResult; import com.habitrpg.android.habitica.models.FAQArticle; +import com.habitrpg.android.habitica.models.Notification; import com.habitrpg.android.habitica.models.Skill; import com.habitrpg.android.habitica.models.Tag; import com.habitrpg.android.habitica.models.TutorialStep; @@ -17,7 +18,6 @@ import com.habitrpg.android.habitica.models.inventory.Quest; import com.habitrpg.android.habitica.models.inventory.QuestCollect; import com.habitrpg.android.habitica.models.inventory.QuestDropItem; import com.habitrpg.android.habitica.models.members.Member; -import com.habitrpg.android.habitica.models.notifications.GlobalNotification; import com.habitrpg.android.habitica.models.responses.FeedResponse; import com.habitrpg.android.habitica.models.social.Challenge; import com.habitrpg.android.habitica.models.social.ChatMessage; @@ -119,7 +119,7 @@ public class GSonFactoryCreator { .registerTypeAdapter(Member.class, new MemberSerialization()) .registerTypeAdapter(WorldState.class, new WorldStateSerialization()) .registerTypeAdapter(FindUsernameResult.class, new FindUsernameResultDeserializer()) - .registerTypeAdapter(GlobalNotification.class, new NotificationDeserializer()) + .registerTypeAdapter(Notification.class, new NotificationDeserializer()) .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") .create(); return GsonConverterFactory.create(gson); diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt index 74669d750..90ee1125f 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.kt @@ -73,11 +73,11 @@ class ApiClientImpl//private OnHabitsAPIResult mResultListener; observable .filter { it.data != null } .map { habitResponse -> - if (habitResponse.notifications != null) { - popupNotificationsManager.showNotificationDialog(habitResponse.notifications) - } - habitResponse.data - } + if (habitResponse.notifications != null) { + popupNotificationsManager.setNotifications(habitResponse.notifications) + } + habitResponse.data + } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .doOnError(this) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/PopupNotificationsManager.java b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/PopupNotificationsManager.java index f82bc9e2e..3c2096174 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/PopupNotificationsManager.java +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/helpers/PopupNotificationsManager.java @@ -2,12 +2,16 @@ package com.habitrpg.android.habitica.helpers; import android.content.Context; import androidx.annotation.Nullable; +import io.reactivex.BackpressureStrategy; +import io.reactivex.Flowable; +import io.reactivex.subjects.BehaviorSubject; import com.habitrpg.android.habitica.R; import com.habitrpg.android.habitica.data.ApiClient; import com.habitrpg.android.habitica.events.ShowCheckinDialog; import com.habitrpg.android.habitica.events.ShowSnackbarEvent; import com.habitrpg.android.habitica.models.Notification; +import com.habitrpg.android.habitica.models.notifications.LoginIncentiveData; import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar; import org.greenrobot.eventbus.EventBus; @@ -26,11 +30,24 @@ public class PopupNotificationsManager { private ApiClient apiClient; private Context context; + private BehaviorSubject> notifications; + // @TODO: A queue for displaying alert dialogues public PopupNotificationsManager(Context context) { this.seenNotifications = new HashMap<>(); this.context = context; + this.notifications = BehaviorSubject.create(); + } + + public void setNotifications(List current) { + this.notifications.onNext(current); + + this.showNotificationDialog(current); + } + + public Flowable> getNotifications() { + return this.notifications.toFlowable(BackpressureStrategy.LATEST); } public void setApiClient(@Nullable ApiClient apiClient) { @@ -38,15 +55,16 @@ public class PopupNotificationsManager { } Boolean displayNotification(Notification notification) { - String nextUnlockText = context.getString(R.string.nextPrizeUnlocks, notification.data.nextRewardAt); - if (notification.data.rewardKey != null) { + LoginIncentiveData notificationData = (LoginIncentiveData)notification.getData(); + String nextUnlockText = context.getString(R.string.nextPrizeUnlocks, notificationData.getNextRewardAt()); + if (notificationData.getRewardKey() != null) { ShowCheckinDialog event = new ShowCheckinDialog(); event.notification = notification; event.nextUnlockText = nextUnlockText; EventBus.getDefault().post(event); } else { ShowSnackbarEvent event = new ShowSnackbarEvent(); - event.title = notification.data.message; + event.title = notificationData.getMessage(); event.text = nextUnlockText; event.type = HabiticaSnackbar.SnackbarDisplayType.BLUE; EventBus.getDefault().post(event); diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/Notification.java b/Habitica/src/main/java/com/habitrpg/android/habitica/models/Notification.java deleted file mode 100644 index e3f995c74..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/Notification.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.habitrpg.android.habitica.models; - -/** - * Created by krh12 on 11/28/2016. - */ - -import com.habitrpg.android.habitica.models.notifications.NotificationData; - -import java.util.HashMap; -import java.util.Map; - -public class Notification { - - public NotificationData data; - private String type; - private String createdAt; - private String id; - private Map additionalProperties = new HashMap(); - - /** - * @return The type - */ - public String getType() { - return type; - } - - /** - * @param type The type - */ - public void setType(String type) { - this.type = type; - } - - /** - * @return The createdAt - */ - public String getCreatedAt() { - return createdAt; - } - - /** - * @param createdAt The createdAt - */ - public void setCreatedAt(String createdAt) { - this.createdAt = createdAt; - } - - /** - * - * @return - * The data - */ -// public T getData() { -// return data; -// } - - /** - * - * @param data - * The data - */ -// public void setData(T data) { -// this.data = data; -// } - - /** - * @return The id - */ - public String getId() { - return id; - } - - /** - * @param id The id - */ - public void setId(String id) { - this.id = id; - } - - public Map getAdditionalProperties() { - return this.additionalProperties; - } - - public void setAdditionalProperty(String name, Object value) { - this.additionalProperties.put(name, value); - } - -} \ No newline at end of file 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 new file mode 100644 index 000000000..afd6a0a25 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/Notification.kt @@ -0,0 +1,30 @@ +package com.habitrpg.android.habitica.models + +import com.habitrpg.android.habitica.models.notifications.* + +class Notification { + enum class Type(val type: String) { + LOGIN_INCENTIVE("LOGIN_INCENTIVE"), + NEW_STUFF("NEW_STUFF"), + NEW_CHAT_MESSAGE("NEW_CHAT_MESSAGE"), + NEW_MYSTERY_ITEMS("NEW_MYSTERY_ITEMS"), + UNALLOCATED_STATS_POINTS("UNALLOCATED_STATS_POINTS"); + } + + var id: String = "" + + var type: String? = null + var seen: Boolean? = null + + var data: NotificationData? = null + + fun getDataType(): java.lang.reflect.Type? { + return when (type) { + Type.LOGIN_INCENTIVE.type -> LoginIncentiveData::class.java + Type.NEW_STUFF.type -> NewStuffData::class.java + Type.NEW_CHAT_MESSAGE.type -> NewChatMessageData::class.java + Type.UNALLOCATED_STATS_POINTS.type -> UnallocatedPointsData::class.java + else -> null + } + } +} \ No newline at end of file diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/GlobalNotification.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/GlobalNotification.kt deleted file mode 100644 index 912fd867b..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/GlobalNotification.kt +++ /dev/null @@ -1,65 +0,0 @@ -package com.habitrpg.android.habitica.models.notifications - -import io.realm.RealmObject -import io.realm.annotations.PrimaryKey -import java.lang.reflect.Type - -enum class NotificationType(val type: String) { - NEW_STUFF("NEW_STUFF"), - NEW_CHAT_MESSAGE("NEW_CHAT_MESSAGE"), - NEW_MYSTERY_ITEMS("NEW_MYSTERY_ITEMS"), - UNALLOCATED_STATS_POINTS("UNALLOCATED_STATS_POINTS"); - - companion object { - fun contains(type: String?): Boolean { - return NotificationType.values().map { it.type }.contains(type) - } - } -} - -/** - * Represents Habitica "Global notifications", i.e. the notifications about chat messages - * (in Guilds and Party), Party & Quest invitations, unallocated stat points etc. - * - * These are different from other kind of notifications, such as Push notifications and - * Popup notifications. - */ -open class GlobalNotification : RealmObject() { - - @PrimaryKey - var id: String = "" - - var type: String? = null - var seen: Boolean? = null - - var newStuffData: NewStuffData? = null - var newChatMessageData: NewChatMessageData? = null - var unallocatedPointsData: UnallocatedPointsData? = null - - // Workaround for Realms lack of polymorphism - fun getData(): GlobalNotificationData? { - return when (type) { - NotificationType.NEW_STUFF.type -> newStuffData - NotificationType.NEW_CHAT_MESSAGE.type -> newChatMessageData - NotificationType.UNALLOCATED_STATS_POINTS.type -> unallocatedPointsData - else -> null - } - } - - fun setData(data: GlobalNotificationData?) { - when (type) { - NotificationType.NEW_STUFF.type -> newStuffData = data as NewStuffData? - NotificationType.NEW_CHAT_MESSAGE.type -> newChatMessageData = data as NewChatMessageData? - NotificationType.UNALLOCATED_STATS_POINTS.type -> unallocatedPointsData = data as UnallocatedPointsData? - } - } - - fun getDataType(): Type? { - return when (type) { - NotificationType.NEW_STUFF.type -> NewStuffData::class.java - NotificationType.NEW_CHAT_MESSAGE.type -> NewChatMessageData::class.java - NotificationType.UNALLOCATED_STATS_POINTS.type -> UnallocatedPointsData::class.java - else -> null - } - } -} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/GlobalNotificationData.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/GlobalNotificationData.kt deleted file mode 100644 index 25d7c44a2..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/GlobalNotificationData.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.habitrpg.android.habitica.models.notifications - -import io.realm.RealmModel - -interface GlobalNotificationData : RealmModel diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/LoginIncentiveData.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/LoginIncentiveData.kt new file mode 100644 index 000000000..7125e4a38 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/LoginIncentiveData.kt @@ -0,0 +1,11 @@ +package com.habitrpg.android.habitica.models.notifications + +open class LoginIncentiveData : NotificationData { + + var message: String? = null + var nextRewardAt: Int? = null + var rewardText: String? = null + var rewardKey: List? = null + var reward: List? = null + +} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/NewChatMessageData.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/NewChatMessageData.kt index f55fffc9d..64484968a 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/NewChatMessageData.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/NewChatMessageData.kt @@ -1,7 +1,5 @@ package com.habitrpg.android.habitica.models.notifications -import io.realm.RealmObject - -open class NewChatMessageData : RealmObject(), GlobalNotificationData { +open class NewChatMessageData : NotificationData { var group: NotificationGroup? = null } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/NewStuffData.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/NewStuffData.kt index 5cf278b26..6329490e6 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/NewStuffData.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/NewStuffData.kt @@ -1,7 +1,5 @@ package com.habitrpg.android.habitica.models.notifications -import io.realm.RealmObject - -open class NewStuffData : RealmObject(), GlobalNotificationData { +open class NewStuffData : NotificationData { var title: String? = null } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/NotificationData.java b/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/NotificationData.java deleted file mode 100644 index 235816ad5..000000000 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/NotificationData.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.habitrpg.android.habitica.models.notifications; - -import java.util.List; - -/** - * Created by krh12 on 11/30/2016. - */ - -public class NotificationData { - - public String groupId; - public String message; - public Integer nextRewardAt; - public String rewardText; - public List rewardKey; - public List reward; - -} diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/NotificationData.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/NotificationData.kt new file mode 100644 index 000000000..32524d056 --- /dev/null +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/NotificationData.kt @@ -0,0 +1,3 @@ +package com.habitrpg.android.habitica.models.notifications + +interface NotificationData diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/NotificationGroup.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/NotificationGroup.kt index aba9d2324..7c3728139 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/NotificationGroup.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/NotificationGroup.kt @@ -1,8 +1,6 @@ package com.habitrpg.android.habitica.models.notifications -import io.realm.RealmObject - -open class NotificationGroup : RealmObject() { +open class NotificationGroup { var id: String = "" var name: String? = null diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/UnallocatedPointsData.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/UnallocatedPointsData.kt index b8221df8e..8521766dd 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/UnallocatedPointsData.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/notifications/UnallocatedPointsData.kt @@ -1,7 +1,5 @@ package com.habitrpg.android.habitica.models.notifications -import io.realm.RealmObject - -open class UnallocatedPointsData : RealmObject(), GlobalNotificationData { +open class UnallocatedPointsData : NotificationData { var points: Int? = null } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/user/User.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/models/user/User.kt index 6707784c7..bf9ab3912 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/user/User.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/user/User.kt @@ -5,7 +5,6 @@ import com.habitrpg.android.habitica.models.Avatar import com.habitrpg.android.habitica.models.PushDevice import com.habitrpg.android.habitica.models.Tag import com.habitrpg.android.habitica.models.invitations.Invitations -import com.habitrpg.android.habitica.models.notifications.GlobalNotification import com.habitrpg.android.habitica.models.social.ChallengeMembership import com.habitrpg.android.habitica.models.social.UserParty import com.habitrpg.android.habitica.models.tasks.TaskList @@ -123,8 +122,6 @@ open class User : RealmObject(), Avatar { @Ignore var pushDevices: List? = null - var notifications = RealmList() - var purchased: Purchases? = null set(purchased) { field = purchased 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 a54106500..47017ca63 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 @@ -46,6 +46,7 @@ import com.habitrpg.android.habitica.helpers.* import com.habitrpg.android.habitica.helpers.notifications.PushNotificationManager import com.habitrpg.android.habitica.interactors.* import com.habitrpg.android.habitica.models.TutorialStep +import com.habitrpg.android.habitica.models.notifications.LoginIncentiveData import com.habitrpg.android.habitica.models.responses.MaintenanceResponse import com.habitrpg.android.habitica.models.responses.TaskScoringResult import com.habitrpg.android.habitica.models.tasks.Task @@ -827,19 +828,20 @@ open class MainActivity : BaseActivity(), TutorialView.OnTutorialReaction { @Subscribe fun showCheckinDialog(event: ShowCheckinDialog) { - val title = event.notification.data.message + 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? SimpleDraweeView - var imageKey = event.notification.data.rewardKey[0] + var imageKey = notificationData.rewardKey!!.get(0) if (imageKey.contains("armor")) { imageKey = "slim_$imageKey" } DataBindingUtils.loadImage(imageView, imageKey) - val youEarnedMessage = this.getString(R.string.checkInRewardEarned, event.notification.data.rewardText) + val youEarnedMessage = this.getString(R.string.checkInRewardEarned, notificationData.rewardText) val titleTextView = TextView(this) titleTextView.setBackgroundResource(R.color.blue_100) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/NotificationsActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/NotificationsActivity.kt index 9cb2d236e..41dc7e0f2 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/NotificationsActivity.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/NotificationsActivity.kt @@ -12,6 +12,7 @@ import androidx.lifecycle.ViewModelProviders import com.habitrpg.android.habitica.R import com.habitrpg.android.habitica.components.AppComponent import com.habitrpg.android.habitica.helpers.RxErrorHandler +import com.habitrpg.android.habitica.models.Notification import com.habitrpg.android.habitica.models.notifications.* import com.habitrpg.android.habitica.ui.viewmodels.NotificationsViewModel import io.reactivex.functions.Consumer @@ -25,7 +26,7 @@ class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget override fun getLayoutResId(): Int = R.layout.activity_notifications - private var notifications: List = emptyList() + private var notifications: List = emptyList() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -65,7 +66,7 @@ class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget }, RxErrorHandler.handleEmptyError())) } - private fun setNotifications(notifications: List) { + private fun setNotifications(notifications: List) { this.notifications = notifications if (notification_items == null) { @@ -86,17 +87,17 @@ class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget ) } - private fun displayNotificationsListView(notifications: List) { + private fun displayNotificationsListView(notifications: List) { notification_items.addView( createNotificationsHeaderView(notifications.count()) ) notifications.map { val item: View? = when (it.type) { - NotificationType.NEW_CHAT_MESSAGE.type -> createNewChatMessageNotification(it) - NotificationType.NEW_STUFF.type -> createNewStuffNotification(it) - NotificationType.UNALLOCATED_STATS_POINTS.type -> createUnallocatedStatsNotification(it) - NotificationType.NEW_MYSTERY_ITEMS.type -> createMysteryItemsNotification(it) + Notification.Type.NEW_CHAT_MESSAGE.type -> createNewChatMessageNotification(it) + Notification.Type.NEW_STUFF.type -> createNewStuffNotification(it) + Notification.Type.UNALLOCATED_STATS_POINTS.type -> createUnallocatedStatsNotification(it) + Notification.Type.NEW_MYSTERY_ITEMS.type -> createMysteryItemsNotification(it) //TODO rest of the notification types else -> null } @@ -117,8 +118,8 @@ class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget return header } - private fun createNewChatMessageNotification(notification: GlobalNotification): View? { - val data = notification.getData() as? NewChatMessageData + private fun createNewChatMessageNotification(notification: Notification): View? { + val data = notification.data as? NewChatMessageData val stringId = if (viewModel.isPartyMessage(data)) R.string.new_msg_party else R.string.new_msg_guild return createNotificationItem( @@ -127,8 +128,8 @@ class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget ) } - private fun createNewStuffNotification(notification: GlobalNotification): View? { - val data = notification.getData() as? NewStuffData + private fun createNewStuffNotification(notification: Notification): View? { + val data = notification.data as? NewStuffData val text = fromHtml("" + getString(R.string.new_bailey_update) + "
" + data?.title) return createNotificationItem( @@ -138,8 +139,8 @@ class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget ) } - private fun createUnallocatedStatsNotification(notification: GlobalNotification): View? { - val data = notification.getData() as? UnallocatedPointsData + private fun createUnallocatedStatsNotification(notification: Notification): View? { + val data = notification.data as? UnallocatedPointsData return createNotificationItem( notification, @@ -148,7 +149,7 @@ class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget ) } - private fun createMysteryItemsNotification(notification: GlobalNotification): View? { + private fun createMysteryItemsNotification(notification: Notification): View? { return createNotificationItem( notification, fromHtml(getString(R.string.new_subscriber_item)), @@ -156,7 +157,7 @@ class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget ) } - private fun createNotificationItem(notification: GlobalNotification, messageText: CharSequence, imageResourceId: Int? = null): View? { + private fun createNotificationItem(notification: Notification, messageText: CharSequence, imageResourceId: Int? = null): View? { val item = inflater.inflate(R.layout.notification_item, notification_items, false) val dismissButton = item?.findViewById(R.id.dismiss_button) as? ImageView diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/NotificationsViewModel.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/NotificationsViewModel.kt index 81ff69290..f65747dee 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/NotificationsViewModel.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewmodels/NotificationsViewModel.kt @@ -1,28 +1,53 @@ package com.habitrpg.android.habitica.ui.viewmodels import com.habitrpg.android.habitica.components.AppComponent +import com.habitrpg.android.habitica.helpers.PopupNotificationsManager import com.habitrpg.android.habitica.helpers.RxErrorHandler -import com.habitrpg.android.habitica.models.notifications.GlobalNotification +import com.habitrpg.android.habitica.models.Notification import com.habitrpg.android.habitica.models.notifications.NewChatMessageData -import com.habitrpg.android.habitica.models.notifications.NotificationType import com.habitrpg.android.habitica.models.social.UserParty import io.reactivex.Flowable import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.functions.Consumer -import io.realm.RealmList import java.util.HashMap +import javax.inject.Inject open class NotificationsViewModel : BaseViewModel() { - var party: UserParty? = null + @Inject + lateinit var notificationsManager: PopupNotificationsManager + + /** + * A list of notification types handled by this component. + * NOTE: Those not listed here won't be shown in the notification panel + */ + private val supportedNotificationTypes = listOf( + Notification.Type.NEW_STUFF.type, + Notification.Type.NEW_CHAT_MESSAGE.type, + Notification.Type.NEW_MYSTERY_ITEMS.type, + Notification.Type.UNALLOCATED_STATS_POINTS.type + ) + + /** + * Keep track of users party so we can determine which chat notifications are party chat + * instead of guild chat notifications. + */ + private var party: UserParty? = null override fun inject(component: AppComponent) { component.inject(this) } - fun getNotifications(): Flowable> { - return userRepository.getUser() - .doOnEach { party = it.value?.party } - .map { filterSupportedTypes(it.notifications) } + init { + disposable.add(userRepository.getUser() + .subscribe(Consumer { + party = it.party + }, RxErrorHandler.handleEmptyError())) + } + + + fun getNotifications(): Flowable> { + return notificationsManager.notifications + .map { filterSupportedTypes(it) } .observeOn(AndroidSchedulers.mainThread()) } @@ -38,12 +63,12 @@ open class NotificationsViewModel : BaseViewModel() { .distinctUntilChanged() } - fun refreshNotifications(): Flowable> { - return userRepository.retrieveUser(withTasks = false, forced = true).map { it.notifications } + fun refreshNotifications(): Flowable<*> { + return userRepository.retrieveUser(withTasks = false, forced = true) } - private fun filterSupportedTypes(notifications: List): List { - return notifications.filter { NotificationType.contains(it.type) } + private fun filterSupportedTypes(notifications: List): List { + return notifications.filter { supportedNotificationTypes.contains(it.type) } } fun isPartyMessage(data: NewChatMessageData?): Boolean { @@ -54,15 +79,12 @@ open class NotificationsViewModel : BaseViewModel() { return party?.id == data.group?.id } - fun dismissNotification(notification: GlobalNotification) { + fun dismissNotification(notification: Notification) { disposable.add(userRepository.readNotification(notification.id) - .subscribe(Consumer { - // TODO better way to handle updates than reload whole user ?? - refreshNotifications() - }, RxErrorHandler.handleEmptyError())) + .subscribe(Consumer {}, RxErrorHandler.handleEmptyError())) } - fun dismissAllNotifications(notifications: List) { + fun dismissAllNotifications(notifications: List) { if (notifications.isEmpty()) { return } @@ -71,12 +93,10 @@ open class NotificationsViewModel : BaseViewModel() { notificationIds["notificationIds"] = notifications.map { notification -> notification.id } disposable.add(userRepository.readNotifications(notificationIds) - .subscribe(Consumer { - refreshNotifications() - }, RxErrorHandler.handleEmptyError())) + .subscribe(Consumer {}, RxErrorHandler.handleEmptyError())) } - fun markNotificationsAsSeen(notifications: List) { + fun markNotificationsAsSeen(notifications: List) { val unseenIds = notifications.filter { notification -> notification.seen != true } .map { notification -> notification.id } @@ -88,9 +108,7 @@ open class NotificationsViewModel : BaseViewModel() { notificationIds["notificationIds"] = unseenIds disposable.add(userRepository.seeNotifications(notificationIds) - .subscribe(Consumer { - refreshNotifications() - }, RxErrorHandler.handleEmptyError())) + .subscribe(Consumer {}, RxErrorHandler.handleEmptyError())) } } diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/utils/NotificationDeserializer.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/utils/NotificationDeserializer.kt index c19a98928..cb6944b10 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/utils/NotificationDeserializer.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/utils/NotificationDeserializer.kt @@ -4,13 +4,13 @@ import com.google.gson.JsonDeserializationContext import com.google.gson.JsonDeserializer import com.google.gson.JsonElement import com.google.gson.JsonParseException -import com.habitrpg.android.habitica.models.notifications.* +import com.habitrpg.android.habitica.models.Notification import java.lang.reflect.Type -class NotificationDeserializer : JsonDeserializer { +class NotificationDeserializer : JsonDeserializer { @Throws(JsonParseException::class) - override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): GlobalNotification { - val notification = GlobalNotification() + override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Notification { + val notification = Notification() val obj = json.asJsonObject if (obj.has("id")) { @@ -27,9 +27,7 @@ class NotificationDeserializer : JsonDeserializer { val dataType = notification.getDataType() if (obj.has("data") && dataType != null) { - notification.setData( - context.deserialize(obj.getAsJsonObject("data"), dataType) - ) + notification.data = context.deserialize(obj.getAsJsonObject("data"), dataType) } return notification diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/utils/UserDeserializer.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/utils/UserDeserializer.kt index 052766700..689724bc6 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/utils/UserDeserializer.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/utils/UserDeserializer.kt @@ -11,7 +11,6 @@ import com.habitrpg.android.habitica.models.PushDevice import com.habitrpg.android.habitica.models.Tag import com.habitrpg.android.habitica.models.inventory.Quest import com.habitrpg.android.habitica.models.invitations.Invitations -import com.habitrpg.android.habitica.models.notifications.GlobalNotification import com.habitrpg.android.habitica.models.social.ChallengeMembership import com.habitrpg.android.habitica.models.social.UserParty import com.habitrpg.android.habitica.models.tasks.TasksOrder @@ -110,11 +109,6 @@ class UserDeserializer : JsonDeserializer { .forEach { (user.pushDevices as? ArrayList)?.add(it) } } - if (obj.has("notifications")) { - user.notifications = context.deserialize(obj.get("notifications"), object: TypeToken>() { - }.type) - } - if (obj.has("lastCron")) { user.lastCron = context.deserialize(obj.get("lastCron"), Date::class.java) }