Global Notification support - pt2 (#1171)

* Create custom notifications for Guild, Party & Quest invitations

Merge custom notifications with the ones coming from server.
Skip marking custom notifications as seen or dismissing them.

* Create actionable notification item views

Set result code based on accept/reject button click

* Handle accept & reject results from actionable notifications

Accept / reject quests & group invites based on notification type
Reload user after accept/reject to refresh notifications

* Create observable from custom notifications also & combine with server notifications

* Better styles for small buttons

* Handle displaying quest data for quest invitation notification

* Add translations related to notifications
This commit is contained in:
Carl Vuorinen 2019-06-12 19:00:08 +03:00 committed by Phillip Thelen
parent 56fab73305
commit 8eed9cb197
29 changed files with 703 additions and 44 deletions

View file

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/notification_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:orientation="vertical"
android:paddingLeft="20dp"
android:paddingTop="10dp"
android:paddingRight="20dp"
android:paddingBottom="10dp">
<TextView
android:id="@+id/message_text"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_marginTop="6dp"
android:layout_marginBottom="6dp"
android:layout_weight="1"
android:lineSpacingExtra="5dp"
android:text="Message" />
<TableLayout
android:id="@+id/quest_detail_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:shrinkColumns="1"
android:stretchColumns="1"
android:visibility="gone"
tools:visibility="visible">
<TableRow
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<TextView
android:id="@+id/quest_objective_label"
style="@style/Caption3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="4dp"
android:textStyle="bold"
tools:text="Collect:" />
<TextView
android:id="@+id/quest_objective_text"
style="@style/Caption3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="List of items" />
</TableRow>
<TableRow
android:id="@+id/difficulty_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<TextView
android:id="@+id/difficulty_label"
style="@style/Caption3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="4dp"
android:textStyle="bold"
tools:text="Difficulty:" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<RatingBar
android:id="@+id/quest_difficulty"
style="@style/QuestRatingBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:isIndicator="true"
android:numStars="4"
android:stepSize="0.5"
tools:rating="2.5" />
</LinearLayout>
</TableRow>
</TableLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:layout_marginBottom="6dp"
android:orientation="horizontal">
<Button
android:id="@+id/reject_button"
style="@style/HabiticaButton.Red.Small"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginRight="16dp"
android:layout_weight="1"
android:text="@string/quest.reject" />
<Button
android:id="@+id/accept_button"
style="@style/HabiticaButton.Green.Small"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/quest.accept" />
</LinearLayout>
</LinearLayout>

View file

@ -822,4 +822,17 @@
<string name="gift_confirmation_text">Подареният от Вас абонамент беше изпратен, и Вие също получихте абонамент.</string>
<string name="discover">Откриване</string>
<string name="damage_paused">Щетите са спрени</string>
<string name="notifications">Известия</string>
<string name="no_notifications_title">Няма непрочетени известия!</string>
<string name="no_notifications_text">Феите на известията Ви ръкопляскат бурно! Добра работа!</string>
<string name="dismiss_all">Премахване на всички</string>
<string name="new_bailey_update">Ново обновление от Бейли!</string>
<string name="new_msg_guild"><![CDATA[Има нови публикации в <b>%1$s</b>]]></string>
<string name="new_msg_party"><![CDATA[Има нови публикации в групата Ви — <b>%1$s</b>]]></string>
<string name="unallocated_stats_points"><![CDATA[Имате <b>%1$s неразпределени показателни точки</b>]]></string>
<string name="new_subscriber_item"><![CDATA[Имате нов <b>тайнствен предмет</b>]]></string>
<string name="invited_to_party_notification"><![CDATA[Получихте покана за присъединяване към групата <b>%1$s</b>]]></string>
<string name="invited_to_private_guild"><![CDATA[Получихте покана за присъединяване към частната гилдия <b>%1$s</b>]]></string>
<string name="invited_to_public_guild"><![CDATA[Получихте покана за присъединяване към гилдията <b>%1$s</b>]]></string>
<string name="invited_to_quest"><![CDATA[Получихте покана за присъединяване в мисията <b>%1$s</b>]]></string>
</resources>

View file

@ -790,15 +790,27 @@ Die Quest-Schriftrolle wird an den Quest-Besitzer zurückgegeben.</string>
<string name="setup_task_reward_notes">Schau Fernsehen, spiel ein Spiel, iss etwas Süßes, es liegt ganz an Dir!</string>
<string name="visit_website">Internetseite besuchen</string>
<string name="gift_title">Wen würdest Du gerne beschenken?</string>
<string name="expand_notes">Mehr lesen</string>
<string name="collapse_notes">Weniger anzeigen</string>
<string name="last_login">Letzte Anmeldung</string>
<string name="total_checkins">Gesamtanmeldungen</string>
<string name="two_handed">Zweihändig</string>
<string name="confirmUsername">Benutzernamen bestätigen</string>
<string name="username_level">\@%s ・Lvl %d</string>
<string name="verification_pet">Eines dieser Veteranen-Haustiere wartet auf Dich wenn Du die Bestätigung abgeschlossen hast!</string>
<string name="gift_subscription">Abonnement verschenken</string>
<string name="create_party">Gruppe erstellen</string>
<string name="expand_notes">Mehr lesen</string>
<string name="collapse_notes">Weniger anzeigen</string>
<string name="last_login">Letzte Anmeldung</string>
<string name="total_checkins">Gesamtanmeldungen</string>
<string name="two_handed">Zweihändig</string>
<string name="confirmUsername">Benutzernamen bestätigen</string>
<string name="username_level">\@%s ・Lvl %d</string>
<string name="verification_pet">Eines dieser Veteranen-Haustiere wartet auf Dich wenn Du die Bestätigung abgeschlossen hast!</string>
<string name="gift_subscription">Abonnement verschenken</string>
<string name="create_party">Gruppe erstellen</string>
<string name="notifications">Mitteilungen</string>
<string name="no_notifications_title">Du bist auf dem Laufenden!</string>
<string name="no_notifications_text">Die Mitteilungsfeen geben dir eine heftige Runde Applaus! Gut gemacht!</string>
<string name="dismiss_all">Alle entfernen</string>
<string name="new_bailey_update">Neues Update von Bailey!</string>
<string name="new_msg_guild"><![CDATA[<b>%1$s</b> hat neue Beiträge]]></string>
<string name="new_msg_party"><![CDATA[Deine Gruppe, <b>%1$s</b>, hat neue Beiträge]]></string>
<string name="unallocated_stats_points"><![CDATA[Du kannst <b>%1$s Attributpunkt(e)</b> verteilen]]></string>
<string name="new_subscriber_item"><![CDATA[Du hast einen neuen <b>Überraschungsgegenstand</b>]]></string>
<string name="invited_to_party_notification"><![CDATA[Du wurdest zu der Gruppe <b>%1$s</b> eingeladen]]></string>
<string name="invited_to_private_guild"><![CDATA[Du wurdest eingeladen, der privaten Gilde <b>%1$s</b> beizutreten.]]></string>
<string name="invited_to_public_guild"><![CDATA[Du wurdest eingeladen, der Gilde <b>%1$s</b> beizutreten.]]></string>
<string name="invited_to_quest"><![CDATA[Du wurdest zur Quest <b>%1$s</b> eingeladen]]></string>
</resources>

View file

@ -574,4 +574,17 @@
<string name="nevermind">Never mind</string>
<string name="resetting_account">Resetting Account</string>
<string name="deleting_account">Deleting Account</string>
<string name="notifications">Notifications</string>
<string name="no_notifications_title">Youre all caught up!</string>
<string name="no_notifications_text">The notification fairies give you a raucous round of applause! Well done!</string>
<string name="dismiss_all">Dismiss All</string>
<string name="new_bailey_update">New Bailey Update!</string>
<string name="new_msg_guild"><![CDATA[<b>%1$s</b> has new posts]]></string>
<string name="new_msg_party"><![CDATA[Your Party, <b>%1$s</b>, has new posts]]></string>
<string name="unallocated_stats_points"><![CDATA[You have <b>%1$s unallocated Stat Points</b>]]></string>
<string name="new_subscriber_item"><![CDATA[You have new <b>Mystery Items</b>]]></string>
<string name="invited_to_party_notification"><![CDATA[You were invited to join the Party <b>%1$s</b>]]></string>
<string name="invited_to_private_guild"><![CDATA[You were invited to join the private Guild <b>%1$s</b>]]></string>
<string name="invited_to_public_guild"><![CDATA[You were invited to join the Guild <b>%1$s</b>]]></string>
<string name="invited_to_quest"><![CDATA[You were invited to the Quest <b>%1$s</b>]]></string>
</resources>

View file

@ -823,4 +823,17 @@
<string name="gift_confirmation_text">Tu suscripción regalo ha sido enviada y tu suscripción ha sido aplicada a tu cuenta.</string>
<string name="discover">Descubre</string>
<string name="damage_paused">Daño pausado</string>
<string name="notifications">Notificaciones</string>
<string name="no_notifications_title">¡Estás al día!</string>
<string name="no_notifications_text">Las hadas de las notificaciones te aplauden atronadoramente. ¡Bien hecho!</string>
<string name="dismiss_all">Ignorar todas</string>
<string name="new_bailey_update">¡Nueva Actualización de Bailey!</string>
<string name="new_msg_guild"><![CDATA[<b>%1$s</b> tiene nuevos mensajes]]></string>
<string name="new_msg_party"><![CDATA[Tu Equipo, <b>%1$s</b>, tiene nuevos mensajes]]></string>
<string name="unallocated_stats_points"><![CDATA[Tienes <b>%1$s Puntos de Estadísticas sin asignar</b>]]></string>
<string name="new_subscriber_item"><![CDATA[Tienes <b>Objetos Misteriosos</b> nuevos]]></string>
<string name="invited_to_party_notification"><![CDATA[Has sido invitado a unirte al Equipo <b>%1$s</b>]]></string>
<string name="invited_to_private_guild"><![CDATA[Has sido invitado a unirte al Gremio privado <b>%1$s</b>]]></string>
<string name="invited_to_public_guild"><![CDATA[Has sido invitado a unirte al Gremio <b>%1$s</b>]]></string>
<string name="invited_to_quest"><![CDATA[Has sido invitado a la misión <b>%1$s</b>]]></string>
</resources>

View file

@ -820,4 +820,17 @@
<string name="gift_confirmation_title">Votre cadeau a été envoyé !</string>
<string name="gift_confirmation_text_g1g1">Votre abonnement offert a été envoyé, et votre abonnement a été rattaché à votre compte.</string>
<string name="gift_confirmation_text">Votre abonnement offert a été envoyé, et votre abonnement a été rattaché à votre compte.</string>
<string name="notifications">Notifications</string>
<string name="no_notifications_title">Vous êtes à jour !</string>
<string name="no_notifications_text">Les fées de la notification vous font un tonnerre d\'applaudissements ! Bien joué !</string>
<string name="dismiss_all">Tout effacer</string>
<string name="new_bailey_update">Nouvelles informations de Bailey !</string>
<string name="new_msg_guild"><![CDATA[<b>%1$s</b> a de nouveaux messages]]></string>
<string name="new_msg_party"><![CDATA[Votre équipe, <b>%1$s</b>, a de nouveaux messages]]></string>
<string name="unallocated_stats_points"><![CDATA[Vous avez <b>%1$s points d\'attribut non alloués</b>]]></string>
<string name="new_subscriber_item"><![CDATA[Vous avez de nouveaux <b>objets mystère</b>]]></string>
<string name="invited_to_party_notification"><![CDATA[Vous avez reçu une invitation à rejoindre l\'équipe <b>%1$s</b>]]></string>
<string name="invited_to_private_guild"><![CDATA[Vous avez reçu une invitation à rejoindre la guilde privée <b>%1$s</b>]]></string>
<string name="invited_to_public_guild"><![CDATA[Vous avez reçu une invitation à rejoindre la guilde <b>%1$s</b>]]></string>
<string name="invited_to_quest"><![CDATA[On vous invite à rejoindre la quête <b>%1$s</b>]]></string>
</resources>

View file

@ -823,4 +823,17 @@ Le Dailies mancate e le cattive Abitudini non li danneggiano molto, e hanno semp
<string name="gift_confirmation_text">L\'abbonamento regalato è stato ricevuto e l\'abbonamento corrispondente applicato al tuo profilo.</string>
<string name="discover">Scopri</string>
<string name="damage_paused">Danni sospesi</string>
<string name="notifications">Notifiche</string>
<string name="no_notifications_title">Sei in pari!</string>
<string name="no_notifications_text">Le fate delle notifche ti danno un rauco turno di applausi! Ben fatto!</string>
<string name="dismiss_all">Nascondi tutto</string>
<string name="new_bailey_update">Nuovo aggiornamento da Bailey!</string>
<string name="new_msg_guild"><![CDATA[<b>%1$s</b> ha nuovi messaggi]]></string>
<string name="new_msg_party"><![CDATA[La tua squadra, <b>%1$s</b>, ha nuovi messaggi]]></string>
<string name="unallocated_stats_points"><![CDATA[Hai <b>%1$s Punti Statistica non allocati</b>]]></string>
<string name="new_subscriber_item"><![CDATA[Hai dei nuovi <b>Oggetti Misteriosi</b>]]></string>
<string name="invited_to_party_notification"><![CDATA[Hai ricevuto un invito per unirti alla Squadra <b>%1$s</b>]]></string>
<string name="invited_to_private_guild"><![CDATA[Hai ricevuto un invito per unirti alla Gilda privata <b>%1$s</b>]]></string>
<string name="invited_to_public_guild"><![CDATA[Hai ricevuto un invito per unirti alla Gilda <b>%1$s</b>]]></string>
<string name="invited_to_quest"><![CDATA[Hai ricevuto un invito per la missione <b>%1$s</b>]]></string>
</resources>

View file

@ -822,4 +822,17 @@
<string name="server">サーバー</string>
<string name="gift_confirmation_title">プレゼントを贈りました!</string>
<string name="discover">探す</string>
<string name="notifications">通知</string>
<string name="no_notifications_title">全ての通知をチェックしました!</string>
<string name="no_notifications_text">通知の妖精はパチパチとあなたに拍手を送っています! えらい!</string>
<string name="dismiss_all">すべて閉じる</string>
<string name="new_bailey_update">Baileyから新しいお知らせがあります</string>
<string name="new_msg_guild"><![CDATA[<b>%1$s</b> に新しい投稿があります]]></string>
<string name="new_msg_party"><![CDATA[あなたのパーティー、<b>%1$s</b> に新しい投稿があります]]></string>
<string name="unallocated_stats_points"><![CDATA[<b>%1$sポイントが割り当てできます。</b>]]></string>
<string name="new_subscriber_item"><![CDATA[新しい<b>ミステリー アイテム</b>]]></string>
<string name="invited_to_party_notification"><![CDATA[パーティー「<b>%1$s</b>」に招待されました。]]></string>
<string name="invited_to_private_guild"><![CDATA[<b>%1$s</b> プライベートギルドに招待されました。]]></string>
<string name="invited_to_public_guild"><![CDATA[<b>%1$s</b> ギルドに招待されました。]]></string>
<string name="invited_to_quest"><![CDATA[<b>%1$s</b> クエストに招待されました。]]></string>
</resources>

View file

@ -804,4 +804,17 @@
<string name="send_gift">Verzend geschenk</string>
<string name="server">server</string>
<string name="gift_confirmation_title">Je geschenk is verzonden!</string>
<string name="notifications">Meldingen</string>
<string name="no_notifications_title">Je bent volledig klaar</string>
<string name="no_notifications_text">De meldingsfeeën geven je een staande ovatie! Goed gedaan!</string>
<string name="dismiss_all">Allen afwijzen</string>
<string name="new_bailey_update">Nieuwe update van Bailey</string>
<string name="new_msg_guild"><![CDATA[<b>%1$s</b> heeft nieuwe berichten]]></string>
<string name="new_msg_party"><![CDATA[Je Gezelschap, <b>%1$s</b>, heeft nieuwe berichten]]></string>
<string name="unallocated_stats_points"><![CDATA[Je hebt <b>%1$s niet toegekende statuspunten</b>]]></string>
<string name="new_subscriber_item"><![CDATA[Je hebt nieuwe <b>Mysterieuze items</b>]]></string>
<string name="invited_to_party_notification"><![CDATA[Je werd uitgenodigd om je aan te sluiten bij de Groep <b>%1$s</b>]]></string>
<string name="invited_to_private_guild"><![CDATA[Je werd uitgenodigd om je aan te sluiten bij het Gilde <b>%1$s</b>]]></string>
<string name="invited_to_public_guild"><![CDATA[Je werd uitgenodigd om je aan te sluiten bij de Gilde <b>%1$s</b>]]></string>
<string name="invited_to_quest"><![CDATA[Je bent uitgenodigd voor de Queeste <b>%1$s</b>]]></string>
</resources>

View file

@ -676,4 +676,17 @@
<string name="questShop_owner_long">Ian Przewodnik Misji</string>
<string name="seasonalShop_owner_long">Sezonowa Czarodziejka</string>
<string name="rage_attack">Atak szału:</string>
<string name="notifications">Powiadomienia</string>
<string name="no_notifications_title">Teraz jesteś na bieżąco!</string>
<string name="no_notifications_text">Wróżki powiadomień składają ci gromkie brawa. Dobra robota!</string>
<string name="dismiss_all">Odrzuć wszystko</string>
<string name="new_bailey_update">Nowości od Bailey</string>
<string name="new_msg_guild"><![CDATA[<b>%1$s</b> ma nowe posty]]></string>
<string name="new_msg_party"><![CDATA[Twoja drużyna <b>%1$s</b> ma nowe posty]]></string>
<string name="unallocated_stats_points"><![CDATA[Masz <b>nieprzydzielone Punkty Atrybutów: %1$s</b>]]></string>
<string name="new_subscriber_item"><![CDATA[Masz nowy <b>Tajemniczy Przedmiot</b>]]></string>
<string name="invited_to_party_notification"><![CDATA[Zostałeś/aś zaproszony/a do Dryżyny <b>%1$s</b>]]></string>
<string name="invited_to_private_guild"><![CDATA[Zostałeś/aś zaproszony/a do prywatnej Gildii <b>%1$s</b>]]></string>
<string name="invited_to_public_guild"><![CDATA[Zostałeś/aś zaproszony/a do Gildii <b>%1$s</b>]]></string>
<string name="invited_to_quest"><![CDATA[Zostałeś/aś zaproszony/a do Misji <b>%1$s</b>]]></string>
</resources>

View file

@ -821,4 +821,17 @@
<string name="gift_confirmation_title">Seu presente foi enviado!</string>
<string name="gift_confirmation_text_g1g1">Sua assinatura de presente foi enviada e uma outra assinatura foi aplicada à sua conta.</string>
<string name="gift_confirmation_text">Sua assinatura de presente foi enviada e uma outra assinatura foi aplicada à sua conta.</string>
<string name="notifications">Notificações</string>
<string name="no_notifications_title">Você está com tudo em dia!</string>
<string name="no_notifications_text">As fadas da notificação lhe deram uma rodada de aplausos barulhentos! Muito bem!</string>
<string name="dismiss_all">Dispensar Tudo</string>
<string name="new_bailey_update">Nova atualização da Bailey!</string>
<string name="new_msg_guild"><![CDATA[<b>%1$s</b> tem novas publicações]]></string>
<string name="new_msg_party"><![CDATA[Seu grupo, <b>%1$s</b>, tem novas publicações]]></string>
<string name="unallocated_stats_points"><![CDATA[Você tem <b>%1$s</b> Pontos de Atributos não distribuidos]]></string>
<string name="new_subscriber_item"><![CDATA[Você possui novos <b>Itens Surpresa</b>]]></string>
<string name="invited_to_party_notification"><![CDATA[Você foi convidado para entrar em um Grupo <b>%1$s</b>]]></string>
<string name="invited_to_private_guild"><![CDATA[Você foi convidado para entrar em uma Guilda privada <b>%1$s</b>]]></string>
<string name="invited_to_public_guild"><![CDATA[Você foi convidado para entrar em uma Guilda <b>%1$s</b>]]></string>
<string name="invited_to_quest"><![CDATA[Você foi convidado para a Missão <b>%1$s</b>]]></string>
</resources>

View file

@ -494,4 +494,17 @@
<string name="collection_quest">Recolha de Missão</string>
<string name="quest_owner_rewards">Recompensas do Dono de Missão</string>
<string name="tavern_description">Bem-vindo à Pousada! Puxe uma cadeira para conversar, ou efetue uma pausa das suas tarefas.</string>
<string name="notifications">Notificações</string>
<string name="no_notifications_title">Já sabes tudo o que se passa!</string>
<string name="no_notifications_text">As fadas das notificações dão-te uma ruidosa salva de palmas! Bom trabalho!</string>
<string name="dismiss_all">Dispensar Todos</string>
<string name="new_bailey_update">Nova atualização de Bailey!</string>
<string name="new_msg_guild"><![CDATA[<b>%1$s</b> tem novas mensagens]]></string>
<string name="new_msg_party"><![CDATA[A sua Equipa, <b>%1$s</b>, tem novas mensagens]]></string>
<string name="unallocated_stats_points"><![CDATA[Tens <b>%1$s Ponto(s) de Atributo por alocar</b>]]></string>
<string name="new_subscriber_item"><![CDATA[Você tem <b>Items Mistério</b> novos]]></string>
<string name="invited_to_party_notification"><![CDATA[Foi convidado a juntar-se à Equipa <b>%1$s</b>]]></string>
<string name="invited_to_private_guild"><![CDATA[Foi convidado a juntar-se à Guilda privada <b>%1$s</b>]]></string>
<string name="invited_to_public_guild"><![CDATA[Foi convidado a juntar-se à Guilda <b>%1$s</b>]]></string>
<string name="invited_to_quest"><![CDATA[Foste convidado para a Missão <b>%1$s</b>]]></string>
</resources>

View file

@ -798,4 +798,17 @@
<string name="equipment_con">ТЕЛ:</string>
<string name="equipment_int">ИНТ:</string>
<string name="equipment_per">ВОС:</string>
<string name="notifications">Уведомления</string>
<string name="no_notifications_title">Вы все вспомнили!</string>
<string name="no_notifications_text">Феи уведомлений вам тихо рукоплещут! Отлично сработано!</string>
<string name="dismiss_all">Сбросить все уведомления</string>
<string name="new_bailey_update">Обновление от Бэйли!</string>
<string name="new_msg_guild"><![CDATA[<b>%1$s</b>, есть новые сообщения]]></string>
<string name="new_msg_party"><![CDATA[В команде <b>%1$s</b> есть новые сообщения]]></string>
<string name="unallocated_stats_points"><![CDATA[Вы не распределили <b>%1$s очков</b>]]></string>
<string name="new_subscriber_item"><![CDATA[У вас новый <b>Таинственный предмет</b>]]></string>
<string name="invited_to_party_notification"><![CDATA[Вас пригласили в команду <b>%1$s</b>]]></string>
<string name="invited_to_private_guild"><![CDATA[Вас пригласили присоединиться к частной гильдии <b>%1$s</b>]]></string>
<string name="invited_to_public_guild"><![CDATA[Вас пригласили в гильдию <b>%1$s</b>]]></string>
<string name="invited_to_quest"><![CDATA[Вас пригласили на квест <b>%1$s</b>]]></string>
</resources>

View file

@ -808,4 +808,17 @@
<string name="visit_website">websiteyi ziyaret et</string>
<string name="gift_subscription">Abonelik Hediye Et</string>
<string name="send_gift">Hediye Gönder</string>
<string name="notifications">Bildirimler</string>
<string name="no_notifications_title">Bildirimleri temizledin!</string>
<string name="no_notifications_text">Bildirim perileri seni şevkle alkışlıyor! Bravo!</string>
<string name="dismiss_all">Okundu Olarak İşaretle</string>
<string name="new_bailey_update">Yeni Bailey Güncellemesi!</string>
<string name="new_msg_guild"><![CDATA[<b>%1$s</b> adlı Loncada yeni mesajlar var]]></string>
<string name="new_msg_party"><![CDATA[<b>%1$s</b> adlı Takımında yeni mesajlar var]]></string>
<string name="unallocated_stats_points"><![CDATA[<b>%1$s adet dağıtılmamış Nitelik Puanın var.</b>]]></string>
<string name="new_subscriber_item"><![CDATA[Yeni <b>Gizemli Eşyaların</b> var]]></string>
<string name="invited_to_party_notification"><![CDATA[<b>%1$s</b> Takımına davet edildin]]></string>
<string name="invited_to_private_guild"><![CDATA[<b>%1$s</b> adlı özel Loncaya davet edildin]]></string>
<string name="invited_to_public_guild"><![CDATA[<b>%1$s</b> adlı Loncaya davet edildin]]></string>
<string name="invited_to_quest"><![CDATA[<b>%1$s</b> Görevine davet edildin]]></string>
</resources>

View file

@ -739,4 +739,17 @@
<string name="short_name">簡短的名稱</string>
<string name="unlock_attribute_points">分配屬性點在10等時解鎖</string>
<string name="moderator">管理員</string>
<string name="notifications">通知</string>
<string name="no_notifications_title">已查看所有新訊息!</string>
<string name="no_notifications_text">通知仙女給您一陣熱烈的掌聲!做得好!</string>
<string name="dismiss_all">清除全部</string>
<string name="new_bailey_update">Bailey的新信息</string>
<string name="new_msg_guild"><![CDATA[<b>%1$s</b>有新的貼文]]></string>
<string name="new_msg_party"><![CDATA[您的隊伍<b>%1$s</b>有新的貼文]]></string>
<string name="unallocated_stats_points"><![CDATA[你有<b>%1$s點未分配屬性點</b>]]></string>
<string name="new_subscriber_item"><![CDATA[您有新的<b>神秘裝備</b>]]></string>
<string name="invited_to_party_notification"><![CDATA[您受邀加入<b>%1$s</b>隊伍]]></string>
<string name="invited_to_private_guild"><![CDATA[您受邀加入<b>%1$s</b>私人公會]]></string>
<string name="invited_to_public_guild"><![CDATA[您受邀加入<b>%1$s</b>您受邀加入]]></string>
<string name="invited_to_quest"><![CDATA[您受邀加入<b>%1$s</b>副本]]></string>
</resources>

View file

@ -729,4 +729,17 @@
<string name="next_day_reminder_title">今天完成任务了么?</string>
<string name="next_day_reminder_text">升级后有许多可解锁和发现的,所以继续你的任务。祝玩得愉快!</string>
<string name="two_handed">双手握持</string>
<string name="notifications">通知</string>
<string name="no_notifications_title">您全部都完成了!</string>
<string name="no_notifications_text">小信使仙女们围着你欢快得鼓起了热烈的掌声!恭喜,做得太棒了!</string>
<string name="dismiss_all">关闭全部</string>
<string name="new_bailey_update">新的贝利更新!</string>
<string name="new_msg_guild"><![CDATA[<b>%1$s</b> 有新消息]]></string>
<string name="new_msg_party"><![CDATA[您的队伍 <b>%1$s</b> 有新消息]]></string>
<string name="unallocated_stats_points"><![CDATA[你有<b>%1$s没分配的属性点</b>]]></string>
<string name="new_subscriber_item"><![CDATA[你有新的<b>神秘物品</b>]]></string>
<string name="invited_to_party_notification"><![CDATA[你被邀请加入队伍<b>%1$s</b>]]></string>
<string name="invited_to_private_guild"><![CDATA[你被邀请加入一个私人工会<b>%1$s</b>]]></string>
<string name="invited_to_public_guild"><![CDATA[你被邀请加入一个工会<b>%1$s</b>]]></string>
<string name="invited_to_quest"><![CDATA[你被邀请加入任务<b>%1$s</b>]]></string>
</resources>

View file

@ -139,6 +139,7 @@
<dimen name="bb_default_elevation">8dp</dimen>
<dimen name="bb_fake_shadow_height">4dp</dimen>
<dimen name="button_height">38dp</dimen>
<dimen name="button_height_small">24dp</dimen>
<dimen name="button_text_size">16sp</dimen>
<dimen name="alert_side_padding">26dp</dimen>
<dimen name="downwards_drop_shadow_height">16dp</dimen>

View file

@ -867,6 +867,11 @@
<string name="new_msg_party"><![CDATA[Your Party, <b>%1$s</b>, has new posts]]></string>
<string name="unallocated_stats_points"><![CDATA[You have <b>%1$s unallocated Stat Points</b>]]></string>
<string name="new_subscriber_item"><![CDATA[You have new <b>Mystery Items</b>]]></string>
<string name="invited_to_party_notification"><![CDATA[You were invited to join the Party <b>%1$s</b>]]></string>
<string name="invited_to_private_guild"><![CDATA[You were invited to join the private Guild <b>%1$s</b>]]></string>
<string name="invited_to_public_guild"><![CDATA[You were invited to join the Guild <b>%1$s</b>]]></string>
<string name="invited_to_quest"><![CDATA[You were invited to the Quest <b>%1$s</b>]]></string>
<string name="defeat">Defeat</string>
<string name="create">Create</string>
<string name="only_leader_create_challenge">Only leader can create Challenges</string>
<string name="create_party">Create Party</string>

View file

@ -464,6 +464,14 @@
<item name="android:text">?textColorPrimaryDark</item>
</style>
<style name="HabiticaButton.Small" parent="HabiticaButton">
<item name="android:paddingTop">@dimen/button_padding_vertical_small</item>
<item name="android:paddingBottom">@dimen/button_padding_vertical_small</item>
<item name="android:textSize">12sp</item>
<item name="android:minHeight">@dimen/button_height_small</item>
<item name="android:layout_height">@dimen/button_height_small</item>
</style>
<style name="HabiticaButton.Gray" parent="HabiticaButton">
<item name="android:background">@drawable/layout_rounded_bg_gray_700</item>
<item name="android:textColor">@color/brand_400</item>
@ -482,6 +490,10 @@
<item name="android:background">@drawable/layout_rounded_bg_blue</item>
</style>
<style name="HabiticaButton.Red.Small" parent="HabiticaButton.Small">
<item name="android:background">@drawable/layout_rounded_bg_red</item>
</style>
<style name="SegmentTitle" parent="Headline">
<item name="android:layout_marginBottom">@dimen/spacing_medium</item>
</style>
@ -490,6 +502,10 @@
<item name="android:background">@drawable/layout_rounded_bg_green</item>
</style>
<style name="HabiticaButton.Green.Small" parent="HabiticaButton.Small">
<item name="android:background">@drawable/layout_rounded_bg_green</item>
</style>
<style name="HabiticaButton.Yellow" parent="HabiticaButton">
<item name="android:background">@drawable/layout_rounded_bg_yellow</item>
</style>

View file

@ -39,7 +39,9 @@ class NotificationsManager (private val context: Context) {
}
fun getNotifications(): Flowable<List<Notification>> {
return this.notifications.toFlowable(BackpressureStrategy.LATEST)
return this.notifications
.startWith(emptyList<Notification>())
.toFlowable(BackpressureStrategy.LATEST)
}
fun getNotification(id: String): Notification? {

View file

@ -4,13 +4,19 @@ import com.habitrpg.android.habitica.models.notifications.*
class Notification {
enum class Type(val type: String) {
// Notification types coming from the server
LOGIN_INCENTIVE("LOGIN_INCENTIVE"),
NEW_STUFF("NEW_STUFF"),
NEW_CHAT_MESSAGE("NEW_CHAT_MESSAGE"),
NEW_MYSTERY_ITEMS("NEW_MYSTERY_ITEMS"),
GROUP_TASK_NEEDS_WORK("GROUP_TASK_NEEDS_WORK"),
GROUP_TASK_APPROVED("GROUP_TASK_APPROVED"),
UNALLOCATED_STATS_POINTS("UNALLOCATED_STATS_POINTS");
UNALLOCATED_STATS_POINTS("UNALLOCATED_STATS_POINTS"),
// Custom notification types (created by this app)
GUILD_INVITATION("GUILD_INVITATION"),
PARTY_INVITATION("PARTY_INVITATION"),
QUEST_INVITATION("QUEST_INVITATION");
}
var id: String = ""
@ -28,6 +34,9 @@ class Notification {
Type.GROUP_TASK_NEEDS_WORK.type -> GroupTaskNeedsWorkData::class.java
Type.GROUP_TASK_APPROVED.type -> GroupTaskApprovedData::class.java
Type.UNALLOCATED_STATS_POINTS.type -> UnallocatedPointsData::class.java
Type.GUILD_INVITATION.type -> GuildInvitationData::class.java
Type.PARTY_INVITATION.type -> PartyInvitationData::class.java
Type.QUEST_INVITATION.type -> QuestInvitationData::class.java
else -> null
}
}

View file

@ -11,6 +11,8 @@ public class GuildInvite extends RealmObject {
@PrimaryKey
private String id;
private Boolean publicGuild;
/**
* @return The inviter
*/
@ -52,4 +54,12 @@ public class GuildInvite extends RealmObject {
public void setId(String id) {
this.id = id;
}
public Boolean getPublicGuild() {
return publicGuild;
}
public void setPublicGuild(Boolean publicGuild) {
this.publicGuild = publicGuild;
}
}

View file

@ -12,13 +12,9 @@ open class Invitations : RealmObject() {
var userId: String? = null
internal var user: User? = null
/**
* @return The party invite
*/
/**
* @param party The party
*/
var party: PartyInvite? = null
var parties: RealmList<PartyInvite>? = null
private var guilds: RealmList<GuildInvite>? = null
/**
@ -38,10 +34,14 @@ open class Invitations : RealmObject() {
fun removeInvitation(groupID: String) {
if (party?.id == groupID) {
party = null
} else {
guilds?.removeAll {
it.id == groupID
}
}
guilds?.removeAll {
it.id == groupID
}
parties?.removeAll {
it.id == groupID
}
}
}

View file

@ -0,0 +1,9 @@
package com.habitrpg.android.habitica.models.notifications
import com.habitrpg.android.habitica.models.invitations.GuildInvite
open class GuildInvitationData : NotificationData {
var invitation: GuildInvite? = null
}

View file

@ -0,0 +1,9 @@
package com.habitrpg.android.habitica.models.notifications
import com.habitrpg.android.habitica.models.invitations.PartyInvite
open class PartyInvitationData : NotificationData {
var invitation: PartyInvite? = null
}

View file

@ -0,0 +1,7 @@
package com.habitrpg.android.habitica.models.notifications
open class QuestInvitationData : NotificationData {
var questKey: String? = null
}

View file

@ -399,6 +399,18 @@ open class MainActivity : BaseActivity(), TutorialView.OnTutorialReaction {
MainNavigationController
)
}
if (resultCode == NOTIFICATION_ACCEPT && data?.hasExtra("notificationId") == true) {
notificationsViewModel?.accept(
data.getStringExtra("notificationId")
)
}
if (resultCode == NOTIFICATION_REJECT && data?.hasExtra("notificationId") == true) {
notificationsViewModel?.reject(
data.getStringExtra("notificationId")
)
}
}
// region Events
@ -747,5 +759,7 @@ open class MainActivity : BaseActivity(), TutorialView.OnTutorialReaction {
const val SELECT_CLASS_RESULT = 11
const val GEM_PURCHASE_REQUEST = 111
const val NOTIFICATION_CLICK = 222
const val NOTIFICATION_ACCEPT = 223
const val NOTIFICATION_REJECT = 224
}
}

View file

@ -4,26 +4,32 @@ import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.text.Html
import android.text.TextUtils
import android.view.LayoutInflater
import android.view.View
import android.widget.Button
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import android.widget.*
import androidx.core.content.ContextCompat
import androidx.lifecycle.ViewModelProviders
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.components.UserComponent
import com.habitrpg.android.habitica.data.InventoryRepository
import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.models.Notification
import com.habitrpg.android.habitica.models.inventory.QuestContent
import com.habitrpg.android.habitica.models.notifications.*
import com.habitrpg.android.habitica.ui.activities.MainActivity.Companion.NOTIFICATION_ACCEPT
import com.habitrpg.android.habitica.ui.activities.MainActivity.Companion.NOTIFICATION_CLICK
import com.habitrpg.android.habitica.ui.activities.MainActivity.Companion.NOTIFICATION_REJECT
import com.habitrpg.android.habitica.ui.viewmodels.NotificationsViewModel
import io.reactivex.functions.Consumer
import kotlinx.android.synthetic.main.activity_notifications.*
import javax.inject.Inject
class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener {
@Inject
lateinit var inventoryRepository: InventoryRepository
lateinit var viewModel: NotificationsViewModel
lateinit var inflater: LayoutInflater
@ -108,11 +114,15 @@ class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget
Notification.Type.NEW_MYSTERY_ITEMS.type -> createMysteryItemsNotification(it)
Notification.Type.GROUP_TASK_NEEDS_WORK.type -> createGroupTaskNeedsWorkNotification(it)
Notification.Type.GROUP_TASK_APPROVED.type -> createGroupTaskApprovedNotification(it)
//TODO rest of the notification types
Notification.Type.PARTY_INVITATION.type -> createPartyInvitationNotification(it)
Notification.Type.GUILD_INVITATION.type -> createGuildInvitationNotification(it)
Notification.Type.QUEST_INVITATION.type -> createQuestInvitationNotification(it)
else -> null
}
notification_items.addView(item)
if (item != null) {
notification_items.addView(item)
}
}
}
@ -132,7 +142,7 @@ class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget
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(
return createDismissableNotificationItem(
notification,
fromHtml(getString(stringId, data?.group?.name))
)
@ -142,7 +152,7 @@ class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget
val data = notification.data as? NewStuffData
val text = fromHtml("<b>" + getString(R.string.new_bailey_update) + "</b><br>" + data?.title)
return createNotificationItem(
return createDismissableNotificationItem(
notification,
text,
R.drawable.notifications_bailey
@ -152,7 +162,7 @@ class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget
private fun createUnallocatedStatsNotification(notification: Notification): View? {
val data = notification.data as? UnallocatedPointsData
return createNotificationItem(
return createDismissableNotificationItem(
notification,
fromHtml(getString(R.string.unallocated_stats_points, data?.points.toString())),
R.drawable.notification_stat_sparkles
@ -160,7 +170,7 @@ class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget
}
private fun createMysteryItemsNotification(notification: Notification): View? {
return createNotificationItem(
return createDismissableNotificationItem(
notification,
fromHtml(getString(R.string.new_subscriber_item)),
R.drawable.notification_mystery_item
@ -171,7 +181,7 @@ class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget
val data = notification.data as? GroupTaskNeedsWorkData
val message = convertGroupMessageHtml(data?.message ?: "")
return createNotificationItem(
return createDismissableNotificationItem(
notification,
fromHtml(message),
null,
@ -183,7 +193,7 @@ class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget
val data = notification.data as? GroupTaskApprovedData
val message = convertGroupMessageHtml(data?.message ?: "")
return createNotificationItem(
return createDismissableNotificationItem(
notification,
fromHtml(message),
null,
@ -204,7 +214,7 @@ class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget
return message.replace(pattern, "strong")
}
private fun createNotificationItem(
private fun createDismissableNotificationItem(
notification: Notification,
messageText: CharSequence,
imageResourceId: Int? = null,
@ -239,6 +249,100 @@ class NotificationsActivity : BaseActivity(), androidx.swiperefreshlayout.widget
return item
}
private fun createPartyInvitationNotification(notification: Notification): View? {
val data = notification.data as? PartyInvitationData
return createActionableNotificationItem(
notification,
fromHtml(getString(R.string.invited_to_party_notification, data?.invitation?.name))
)
}
private fun createGuildInvitationNotification(notification: Notification): View? {
val data = notification.data as? GuildInvitationData
val stringId = if (data?.invitation?.publicGuild == false) R.string.invited_to_private_guild else R.string.invited_to_public_guild
return createActionableNotificationItem(
notification,
fromHtml(getString(stringId, data?.invitation?.name))
)
}
private fun createQuestInvitationNotification(notification: Notification): View? {
val data = notification.data as? QuestInvitationData
val view = createActionableNotificationItem(notification, "")
// hide view until we have loaded quest data and populated the values
view.visibility = View.GONE
compositeSubscription.add(inventoryRepository.getQuestContent(data?.questKey ?: "")
.firstElement()
.subscribe(Consumer {
updateQuestInvitationView(view, it)
}, RxErrorHandler.handleEmptyError()))
return view
}
private fun updateQuestInvitationView(view: View, questContent: QuestContent) {
val messageTextView = view.findViewById(R.id.message_text) as? TextView
messageTextView?.text = fromHtml(getString(R.string.invited_to_quest, questContent.text))
val questObjectiveLabelView = view.findViewById(R.id.quest_objective_label) as? TextView
val questObjectiveTextView = view.findViewById(R.id.quest_objective_text) as? TextView
val questDifficultyLabelView = view.findViewById(R.id.difficulty_label) as? TextView
questDifficultyLabelView?.text = getText(R.string.difficulty)
questDifficultyLabelView?.append(":")
val questDifficultyView = view.findViewById(R.id.quest_difficulty) as? RatingBar
if (questContent.isBossQuest) {
questObjectiveLabelView?.text = getString(R.string.defeat)
questObjectiveTextView?.text = questContent.boss?.name
questDifficultyView?.rating = questContent.boss?.str ?: 1f
} else {
questObjectiveLabelView?.text = getString(R.string.collect)
val collectionList = questContent.collect?.map { it.count.toString() + " " + it.text }
questObjectiveTextView?.text = TextUtils.join(", ", collectionList)
questDifficultyView?.rating = 1f
}
questObjectiveLabelView?.append(":")
val questDetailView = view.findViewById(R.id.quest_detail_view) as? View
questDetailView?.visibility = View.VISIBLE
view.visibility = View.VISIBLE
}
private fun createActionableNotificationItem(
notification: Notification,
messageText: CharSequence
): View {
val item = inflater.inflate(R.layout.notification_item_actionable, notification_items, false)
val acceptButton = item.findViewById(R.id.accept_button) as? Button
acceptButton?.setOnClickListener {
val resultIntent = Intent()
resultIntent.putExtra("notificationId", notification.id)
setResult(NOTIFICATION_ACCEPT, resultIntent)
finish()
}
val rejectButton = item.findViewById(R.id.reject_button) as? Button
rejectButton?.setOnClickListener {
val resultIntent = Intent()
resultIntent.putExtra("notificationId", notification.id)
setResult(NOTIFICATION_REJECT, resultIntent)
finish()
}
val messageTextView = item.findViewById(R.id.message_text) as? TextView
messageTextView?.text = messageText
return item
}
private fun fromHtml(text: String): CharSequence {
return if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
Html.fromHtml(text, Html.FROM_HTML_MODE_LEGACY)

View file

@ -3,15 +3,24 @@ package com.habitrpg.android.habitica.ui.viewmodels
import android.os.Bundle
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.components.UserComponent
import com.habitrpg.android.habitica.data.SocialRepository
import com.habitrpg.android.habitica.extensions.notNull
import com.habitrpg.android.habitica.helpers.MainNavigationController
import com.habitrpg.android.habitica.helpers.NotificationsManager
import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.models.Notification
import com.habitrpg.android.habitica.models.notifications.GuildInvitationData
import com.habitrpg.android.habitica.models.notifications.NewChatMessageData
import com.habitrpg.android.habitica.models.notifications.PartyInvitationData
import com.habitrpg.android.habitica.models.notifications.QuestInvitationData
import com.habitrpg.android.habitica.models.social.UserParty
import com.habitrpg.android.habitica.models.user.User
import io.reactivex.BackpressureStrategy
import io.reactivex.Flowable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.functions.BiFunction
import io.reactivex.functions.Consumer
import io.reactivex.subjects.BehaviorSubject
import java.util.*
import javax.inject.Inject
@ -19,9 +28,12 @@ open class NotificationsViewModel : BaseViewModel() {
@Inject
lateinit var notificationsManager: NotificationsManager
@Inject
lateinit var socialRepository: SocialRepository
/**
* A list of notification types handled by this component.
* NOTE: Those not listed here won't be shown in the notification panel
* NOTE: Those not listed here won't be shown in the notification panel (except the custom ones)
*/
private val supportedNotificationTypes = listOf(
Notification.Type.NEW_STUFF.type,
@ -32,28 +44,54 @@ open class NotificationsViewModel : BaseViewModel() {
Notification.Type.UNALLOCATED_STATS_POINTS.type
)
/**
* A list of notification types that are "actionable" (ones that have accept/reject buttons).
*/
private val actionableNotificationTypes = listOf(
Notification.Type.GUILD_INVITATION.type,
Notification.Type.PARTY_INVITATION.type,
Notification.Type.QUEST_INVITATION.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
/**
* Custom notification types created by this class (from user data).
* Will be combined with the notifications coming from server.
*/
private val customNotifications: BehaviorSubject<List<Notification>>
override fun inject(component: UserComponent) {
component.inject(this)
}
init {
customNotifications = BehaviorSubject.create()
customNotifications.onNext(emptyList())
disposable.add(userRepository.getUser()
.subscribe(Consumer {
party = it.party
customNotifications.onNext(convertInvitationsToNotifications(it))
}, RxErrorHandler.handleEmptyError()))
}
fun getNotifications(): Flowable<List<Notification>> {
return notificationsManager.getNotifications()
val serverNotifications = notificationsManager.getNotifications()
.map { filterSupportedTypes(it) }
.observeOn(AndroidSchedulers.mainThread())
return Flowable.combineLatest(
serverNotifications,
customNotifications.toFlowable(BackpressureStrategy.LATEST),
BiFunction<List<Notification>, List<Notification>, List<Notification>> {
serverNotificationsList, customNotificationsList -> serverNotificationsList + customNotificationsList
}
).observeOn(AndroidSchedulers.mainThread())
}
fun getNotificationCount(): Flowable<Int> {
@ -64,7 +102,7 @@ open class NotificationsViewModel : BaseViewModel() {
fun allNotificationsSeen(): Flowable<Boolean> {
return getNotifications()
.map { it.all { notification -> notification.seen == true } }
.map { it.all { notification -> notification.seen != false } }
.distinctUntilChanged()
}
@ -87,6 +125,44 @@ open class NotificationsViewModel : BaseViewModel() {
return notifications.filter { supportedNotificationTypes.contains(it.type) }
}
private fun convertInvitationsToNotifications(user: User): List<Notification> {
val notifications = arrayListOf<Notification>()
notifications.addAll(user.invitations?.parties?.map {
val notification = Notification()
notification.id = "custom-party-invitation-" + it.id
notification.type = Notification.Type.PARTY_INVITATION.type
val data = PartyInvitationData()
data.invitation = it
notification.data = data
notification
} ?: emptyList())
notifications.addAll(user.invitations?.getGuilds()?.map {
val notification = Notification()
notification.id = "custom-guild-invitation-" + it.id
notification.type = Notification.Type.GUILD_INVITATION.type
val data = GuildInvitationData()
data.invitation = it
notification.data = data
notification
} ?: emptyList())
val quest = user.party?.quest
if (quest != null && quest.RSVPNeeded) {
val notification = Notification()
notification.id = "custom-quest-invitation-" + user.party?.id
notification.type = Notification.Type.QUEST_INVITATION.type
val data = QuestInvitationData()
data.questKey = quest.key
notification.data = data
notifications.add(notification)
}
return notifications
}
fun isPartyMessage(data: NewChatMessageData?): Boolean {
if (party == null || data?.group?.id == null) {
return false
@ -95,26 +171,45 @@ open class NotificationsViewModel : BaseViewModel() {
return party?.id == data.group?.id
}
/**
* Is the given notification an "artificial" custom notification (created by this class)
* instead of one of the ones coming from server.
*/
private fun isCustomNotification(notification: Notification): Boolean {
return notification.id.startsWith("custom-")
}
fun dismissNotification(notification: Notification) {
if (isCustomNotification(notification)) {
return
}
disposable.add(userRepository.readNotification(notification.id)
.subscribe(Consumer {}, RxErrorHandler.handleEmptyError()))
}
fun dismissAllNotifications(notifications: List<Notification>) {
if (notifications.isEmpty()) {
val dismissableIds = notifications
.filter { !isCustomNotification(it) }
.filter { !actionableNotificationTypes.contains(it.type) }
.map { it.id }
if (dismissableIds.isEmpty()) {
return
}
val notificationIds = HashMap<String, List<String>>()
notificationIds["notificationIds"] = notifications.map { notification -> notification.id }
notificationIds["notificationIds"] = dismissableIds
disposable.add(userRepository.readNotifications(notificationIds)
.subscribe(Consumer {}, RxErrorHandler.handleEmptyError()))
}
fun markNotificationsAsSeen(notifications: List<Notification>) {
val unseenIds = notifications.filter { notification -> notification.seen != true }
.map { notification -> notification.id }
val unseenIds = notifications
.filter { !isCustomNotification(it) }
.filter { it.seen == false }
.map { it.id }
if (unseenIds.isEmpty()) {
return
@ -155,4 +250,71 @@ open class NotificationsViewModel : BaseViewModel() {
}
}
fun accept(notificationId: String) {
val notification = customNotifications.value?.find { it.id == notificationId } ?: return
when (notification.type) {
Notification.Type.GUILD_INVITATION.type -> {
val data = notification.data as GuildInvitationData
acceptGroupInvitation(data.invitation?.id)
}
Notification.Type.PARTY_INVITATION.type -> {
val data = notification.data as PartyInvitationData
acceptGroupInvitation(data.invitation?.id)
}
Notification.Type.QUEST_INVITATION.type -> acceptQuestInvitation()
}
}
fun reject(notificationId: String) {
val notification = customNotifications.value?.find { it.id == notificationId } ?: return
when (notification.type) {
Notification.Type.GUILD_INVITATION.type -> {
val data = notification.data as GuildInvitationData
rejectGroupInvite(data.invitation?.id)
}
Notification.Type.PARTY_INVITATION.type -> {
val data = notification.data as PartyInvitationData
rejectGroupInvite(data.invitation?.id)
}
Notification.Type.QUEST_INVITATION.type -> rejectQuestInvitation()
}
}
fun acceptGroupInvitation(groupId: String?) {
groupId.notNull {
disposable.add(socialRepository.joinGroup(it)
.subscribe(Consumer {
refreshNotifications()
}, RxErrorHandler.handleEmptyError()))
}
}
fun rejectGroupInvite(groupId: String?) {
groupId.notNull {
disposable.add(socialRepository.rejectGroupInvite(it)
.subscribe(Consumer {
refreshNotifications()
}, RxErrorHandler.handleEmptyError()))
}
}
private fun acceptQuestInvitation() {
party?.id.notNull {
disposable.add(socialRepository.acceptQuest(null, it)
.subscribe(Consumer {
refreshNotifications()
}, RxErrorHandler.handleEmptyError()))
}
}
private fun rejectQuestInvitation() {
party?.id.notNull {
disposable.add(socialRepository.rejectQuest(null, it)
.subscribe(Consumer {
refreshNotifications()
}, RxErrorHandler.handleEmptyError()))
}
}
}