Improve deserialization speeds

This commit is contained in:
Phillip Thelen 2019-04-05 09:36:32 +02:00
parent 6ba76db5d0
commit 16888dd3ed
53 changed files with 554 additions and 485 deletions

View file

@ -25,7 +25,11 @@
android:label="@string/app_name"
android:theme="@style/AppTheme"
tools:replace="android:name"
android:fullBackupContent="@xml/backup_descriptor">
android:fullBackupContent="@xml/backup_descriptor"
android:networkSecurityConfig="@xml/network_security_config">
<meta-data
android:name="firebase_performance_logcat_enabled"
android:value="true" />
<activity
android:name=".ui.activities.MainActivity"
android:label="@string/app_name"

View file

@ -151,7 +151,7 @@ android {
multiDexEnabled true
versionCode 2081
versionName "1.8.1"
versionName "1.9"
}
lintOptions {

View file

@ -296,15 +296,15 @@
<string name="feed_to_pet">Даване на любимец</string>
<string name="hatch_egg">Излюпване с яйце</string>
<string name="invite_party">Поканване на групата</string>
<string name="dialog_feeding">Хранене на %1$s %2$s с:</string>
<string name="dialog_feeding">Хранене на %s с:</string>
<string name="use_animal">Използване</string>
<string name="feed">Хранене</string>
<string name="hatch_with">Излюпване на любимец с %s</string>
<string name="hatched_pet_title">Вие излюпихте %1$s %2$s!</string>
<string name="evolved_pet_title">Вие опитомихте %1$s %2$s. Да се качваме!</string>
<string name="hatched_pet_title">Вие излюпихте %s!</string>
<string name="evolved_pet_title">Вие опитомихте %s. Да се качваме!</string>
<string name="close">Затваряне</string>
<string name="share">Споделяне</string>
<string name="notification_pet_fed">Вие нахранихте своя(та/то) %1$s %2$s!</string>
<string name="notification_pet_fed">Вие нахранихте своя(та/то) %s!</string>
<string name="notification_purchase">Вие закупихте %s</string>
<string name="notification_purchase_reward">Вие закупихте награда</string>
<string name="sectionpets">Обикновени</string>

View file

@ -296,15 +296,15 @@
<string name="feed_to_pet">An Haustier verfüttern</string>
<string name="hatch_egg">Mit Ei ausbrüten</string>
<string name="invite_party">Party einladen</string>
<string name="dialog_feeding">Füttere %1$s %2$s mit:</string>
<string name="dialog_feeding">Füttere %s mit:</string>
<string name="use_animal">Nutzen</string>
<string name="feed">Füttern</string>
<string name="hatch_with">Haustier mit %s ausbrüten</string>
<string name="hatched_pet_title">Du hast ein %1$s %2$s ausgebrütet!</string>
<string name="evolved_pet_title">Du hast %1$s%2$s gezähmt, auf geht\'s!</string>
<string name="hatched_pet_title">Du hast ein %s ausgebrütet!</string>
<string name="evolved_pet_title">Du hast %s gezähmt, auf geht\'s!</string>
<string name="close">Schließen</string>
<string name="share">Teilen</string>
<string name="notification_pet_fed">Du hast Dein/e/n %1$s %2$s gefüttert!</string>
<string name="notification_pet_fed">Du hast Dein/e/n %s gefüttert!</string>
<string name="notification_purchase">Du hast %s gekauft</string>
<string name="notification_purchase_reward">Du hast eine Belohnung gekauft</string>
<string name="sectionpets">Standard</string>

View file

@ -285,14 +285,14 @@
<string name="feed_to_pet">Feed to pet</string>
<string name="hatch_egg">Hatch with egg</string>
<string name="invite_party">Invite party</string>
<string name="dialog_feeding">Feed %1$s %2$s with:</string>
<string name="dialog_feeding">Feed %s with:</string>
<string name="use_animal">Use</string>
<string name="feed">Feed</string>
<string name="hatch_with">Hatch pet with %s</string>
<string name="hatched_pet_title">You hatched a %1$s %2$s!</string>
<string name="hatched_pet_title">You hatched a %s!</string>
<string name="close">Close</string>
<string name="share">Share</string>
<string name="notification_pet_fed">You fed your %1$s %2$s!</string>
<string name="notification_pet_fed">You fed your %s!</string>
<string name="world_quest">World Quest</string>
<string name="empty_items">You don\'t have any %s</string>
<string name="user_level">Lvl %d</string>

View file

@ -296,15 +296,15 @@
<string name="feed_to_pet">Alimentar a mascota</string>
<string name="hatch_egg">Mezclar con huevo</string>
<string name="invite_party">Invitar al grupo</string>
<string name="dialog_feeding">Dar de comer a %2$s %1$s:</string>
<string name="dialog_feeding">Dar de comer a %s:</string>
<string name="use_animal">Usar</string>
<string name="feed">Alimentar</string>
<string name="hatch_with">Criar mascota con %s</string>
<string name="hatched_pet_title">¡Ha nacido un/a %2$s %1$s!</string>
<string name="evolved_pet_title">Has domado %1$s %2$s, ¡vamos a dar un paseo!</string>
<string name="hatched_pet_title">¡Ha nacido un/a %s!</string>
<string name="evolved_pet_title">Has domado %s, ¡vamos a dar un paseo!</string>
<string name="close">Cerrar</string>
<string name="share">Compartir</string>
<string name="notification_pet_fed">¡Tu %2$s %1$s ha comido!</string>
<string name="notification_pet_fed">¡Tu %s ha comido!</string>
<string name="notification_purchase">Has comprado %s</string>
<string name="notification_purchase_reward">Has obtenido una recompensa.</string>
<string name="sectionpets">Estandar</string>

View file

@ -296,15 +296,15 @@
<string name="feed_to_pet">Donner au familier</string>
<string name="hatch_egg">Faire éclore avec l\'œuf</string>
<string name="invite_party">Inviter l\'équipe</string>
<string name="dialog_feeding">Nourrissez votre %1$s %2$s avec :</string>
<string name="dialog_feeding">Nourrissez votre %s avec :</string>
<string name="use_animal">Utiliser</string>
<string name="feed">Nourrir</string>
<string name="hatch_with">Faire éclore le familier avec %s</string>
<string name="hatched_pet_title">Votre %1$s %2$s a éclos !</string>
<string name="evolved_pet_title">Vous avez dompté %2$s%1$s, partez en promenade ensemble !</string>
<string name="hatched_pet_title">Votre %s a éclos !</string>
<string name="evolved_pet_title">Vous avez dompté %s, partez en promenade ensemble !</string>
<string name="close">Fermer</string>
<string name="share">Partager</string>
<string name="notification_pet_fed">Vous avez nourri votre %1$s %2$s !</string>
<string name="notification_pet_fed">Vous avez nourri votre %s !</string>
<string name="notification_purchase">Vous avez acheté %s</string>
<string name="notification_purchase_reward">Vous avez acheté une récompense</string>
<string name="sectionpets">Standard</string>

View file

@ -298,15 +298,15 @@
<string name="feed_to_pet">Nahrani ljubimca</string>
<string name="hatch_egg">Izlegni s jajetom</string>
<string name="invite_party">Pozovi družinu</string>
<string name="dialog_feeding">Nahrani %1$s %2$s s:</string>
<string name="dialog_feeding">Nahrani %s s:</string>
<string name="use_animal">Koristi</string>
<string name="feed">Nahrani</string>
<string name="hatch_with">Izlegni ljubimca s %s</string>
<string name="hatched_pet_title">%1$s %2$s se izlegao/la!</string>
<string name="evolved_pet_title">Pripitomio/la si %1$s %2$s, hajdemo jahati!</string>
<string name="hatched_pet_title">%s se izlegao/la!</string>
<string name="evolved_pet_title">Pripitomio/la si %s, hajdemo jahati!</string>
<string name="close">Zatvori</string>
<string name="share">Podijeli</string>
<string name="notification_pet_fed">Nahranio/la si svoju/ga %1$s %2$s!</string>
<string name="notification_pet_fed">Nahranio/la si svoju/ga %s!</string>
<string name="notification_purchase">Kupio/la si %s</string>
<string name="notification_purchase_reward">Kupio/la si nagradu</string>
<string name="sectionpets">Standardni</string>

View file

@ -286,14 +286,14 @@
<string name="feed_to_pet">Beri makan peliharaan</string>
<string name="hatch_egg">Tetaskan dengan telur</string>
<string name="invite_party">Undang party</string>
<string name="dialog_feeding">Beri makan %2$s %1$s dengan:</string>
<string name="dialog_feeding">Beri makan %s dengan:</string>
<string name="use_animal">Gunakan</string>
<string name="feed">Beri makan</string>
<string name="hatch_with">Tetaskan dengan %s</string>
<string name="hatched_pet_title">Kamu menetaskan seekor %2$s %1$s!</string>
<string name="hatched_pet_title">Kamu menetaskan seekor %s</string>
<string name="close">Tutup</string>
<string name="share">Bagikan</string>
<string name="notification_pet_fed">Kamu memberi makan %2$s %1$s!</string>
<string name="notification_pet_fed">Kamu memberi makan %s!</string>
<string name="notification_purchase">%s telah dibeli</string>
<string name="notification_purchase_reward">Kamu membeli sebuah hadiah</string>
<string name="sectionpets">Standard</string>

View file

@ -296,15 +296,15 @@
<string name="feed_to_pet">Dai ad animale</string>
<string name="hatch_egg">Schiudi con uovo</string>
<string name="invite_party">Invita squadra</string>
<string name="dialog_feeding">Dai da mangiare a %1$s %2$s:</string>
<string name="dialog_feeding">Dai da mangiare a %s:</string>
<string name="use_animal">Usa</string>
<string name="feed">Dai da mangiare</string>
<string name="hatch_with">Fai nascere un animale con %s</string>
<string name="hatched_pet_title">È nato un %2$s %1$s!</string>
<string name="evolved_pet_title">Hai domato %1$s%2$s, inizia a cavalcare!</string>
<string name="hatched_pet_title">È nato un %s!</string>
<string name="evolved_pet_title">Hai domato %s, inizia a cavalcare!</string>
<string name="close">Chiudi</string>
<string name="share">Condividi</string>
<string name="notification_pet_fed">Hai dato da mangiare al tuo %1$s %2$s!</string>
<string name="notification_pet_fed">Hai dato da mangiare al tuo %s!</string>
<string name="notification_purchase">Hai comprato %s</string>
<string name="notification_purchase_reward">Hai comprato una ricompensa</string>
<string name="sectionpets">Base</string>

View file

@ -244,14 +244,14 @@
<string name="feed_to_pet">האכילו חיית מחמד</string>
<string name="hatch_egg">הבקיעו עם ביצה</string>
<string name="invite_party">הזמינו חבורה</string>
<string name="dialog_feeding">האכלתם %1$s %2$s עם:</string>
<string name="dialog_feeding">האכלתם %s עם:</string>
<string name="use_animal">השתמשו</string>
<string name="feed">האכילו</string>
<string name="hatch_with">הבקיעו חיית מחמד עם %s</string>
<string name="hatched_pet_title">הבקעתם %1$s %2$s!</string>
<string name="hatched_pet_title">הבקעתם %1s!</string>
<string name="close">סיגרו</string>
<string name="share">שתפו</string>
<string name="notification_pet_fed">האכלתם את ה %1$s %2$s שלכם!</string>
<string name="notification_pet_fed">האכלתם את ה %s שלכם!</string>
<string name="world_quest">הרפתקאה עולמית</string>
<string name="empty_items">אין לכם כל %s</string>
<string name="user_level">דרגה %d</string>

View file

@ -297,15 +297,15 @@
<string name="feed_to_pet">ペットにえさをやる</string>
<string name="hatch_egg">たまごをかえす</string>
<string name="invite_party">パーティーに招待する</string>
<string name="dialog_feeding">%1$s%2$s にえさをやる :</string>
<string name="dialog_feeding">%s にえさをやる :</string>
<string name="use_animal">連れていく</string>
<string name="feed">えさをやる</string>
<string name="hatch_with">%s でペットをかえす</string>
<string name="hatched_pet_title">%1$s%2$sが生まれた!</string>
<string name="evolved_pet_title">%1$s%2$sを手なずけたさあ、乗ってみよう</string>
<string name="hatched_pet_title">%sが生まれた!</string>
<string name="evolved_pet_title">%sを手なずけたさあ、乗ってみよう</string>
<string name="close">閉じる</string>
<string name="share">共有する</string>
<string name="notification_pet_fed">%1$s%2$sにえさをやった!</string>
<string name="notification_pet_fed">%sにえさをやった!</string>
<string name="notification_purchase">%sを購入しました</string>
<string name="notification_purchase_reward">報酬をを購入しました</string>
<string name="sectionpets">ふつうの</string>

View file

@ -293,14 +293,14 @@
<string name="feed_to_pet">펫 먹이주기</string>
<string name="hatch_egg">알 부화</string>
<string name="invite_party">파티에 초대</string>
<string name="dialog_feeding">%1$s %2$s 에게 다음의 먹이 주기:</string>
<string name="dialog_feeding">%s 에게 다음의 먹이 주기:</string>
<string name="use_animal">사용</string>
<string name="feed">먹이주기</string>
<string name="hatch_with">%s 으로 펫 부화</string>
<string name="hatched_pet_title">당신은 %1$s %2$s 를 부화시켰습니다!</string>
<string name="hatched_pet_title">당신은 %s 를 부화시켰습니다!</string>
<string name="close">닫기</string>
<string name="share">나누기</string>
<string name="notification_pet_fed">%1$s %2$s 에게 먹이를 줬습니다!</string>
<string name="notification_pet_fed">%s 에게 먹이를 줬습니다!</string>
<string name="notification_purchase">%s 를 구매했습니다</string>
<string name="notification_purchase_reward">보상을 구매했습니다</string>
<string name="sectionpets">기본 펫</string>

View file

@ -251,14 +251,14 @@
<string name="feed_to_pet">Maitinti gyvūnui</string>
<string name="hatch_egg">Išperėti kiaušinį</string>
<string name="invite_party">Pakviesti grupę</string>
<string name="dialog_feeding">Pašerti %1$s %2$s su:</string>
<string name="dialog_feeding">Pašerti %s su:</string>
<string name="use_animal">Naudoti</string>
<string name="feed">Maitinti</string>
<string name="hatch_with">Užauginti gyvūną su %s</string>
<string name="hatched_pet_title">Užauginai %1$s %2$s!</string>
<string name="hatched_pet_title">Užauginai %s!</string>
<string name="close">Uždaryti</string>
<string name="share">Dalintis</string>
<string name="notification_pet_fed">Pašėrei savo %1$s %2$s!</string>
<string name="notification_pet_fed">Pašėrei savo %s!</string>
<string name="world_quest">Pasaulinė Misija</string>
<string name="empty_items">Nebeturi %s</string>
<string name="warrior">Karys</string>

View file

@ -296,15 +296,15 @@
<string name="feed_to_pet">Aan huisdier voederen</string>
<string name="hatch_egg">Laten uitkomen met ei</string>
<string name="invite_party">Nodig groep uit</string>
<string name="dialog_feeding">Voeder %1$s %2$s met:</string>
<string name="dialog_feeding">Voeder %s met:</string>
<string name="use_animal">Gebruik</string>
<string name="feed">Voeder</string>
<string name="hatch_with">Laat huisdier uitkomen met %s</string>
<string name="hatched_pet_title">Je hebt een %1$s %2$s laten uitkomen!</string>
<string name="evolved_pet_title">Je hebt %1$s%2$s afgericht, laten we een ridje maken!</string>
<string name="hatched_pet_title">Je hebt een %s laten uitkomen!</string>
<string name="evolved_pet_title">Je hebt %s afgericht, laten we een ridje maken!</string>
<string name="close">Sluiten</string>
<string name="share">Delen</string>
<string name="notification_pet_fed">Je hebt je %1$s %2$s gevoederd!</string>
<string name="notification_pet_fed">Je hebt je %s gevoederd!</string>
<string name="notification_purchase">Je hebt %s gekocht</string>
<string name="notification_purchase_reward">Je hebt een beloning gekocht</string>
<string name="sectionpets">Standaard</string>

View file

@ -288,14 +288,14 @@
<string name="feed_to_pet">Nakarm chowańca</string>
<string name="hatch_egg">Wykluj za pomocą jaja</string>
<string name="invite_party">Zaproś drużynę</string>
<string name="dialog_feeding">Nakarm %1$s %2$s</string>
<string name="dialog_feeding">Nakarm %s</string>
<string name="use_animal">Użyj</string>
<string name="feed">Nakarm</string>
<string name="hatch_with">Wykluj za pomocą %s</string>
<string name="hatched_pet_title">Wyklułeś/as %1$s %2$s!</string>
<string name="hatched_pet_title">Wyklułeś/as %s!</string>
<string name="close">Zamknij</string>
<string name="share">Podziel się</string>
<string name="notification_pet_fed">Nakarmiłeś/aś %1$s %2$s!</string>
<string name="notification_pet_fed">Nakarmiłeś/aś %s!</string>
<string name="notification_purchase">Kupiłeś %s</string>
<string name="notification_purchase_reward">Kupiłeś nagrodę</string>
<string name="sectionpets">Standardowe</string>

View file

@ -296,15 +296,15 @@
<string name="feed_to_pet">Alimentar mascote</string>
<string name="hatch_egg">Chocar com ovo</string>
<string name="invite_party">Convidar Grupo</string>
<string name="dialog_feeding">Alimentar %1$s %2$s com:</string>
<string name="dialog_feeding">Alimentar %s com:</string>
<string name="use_animal">Usar</string>
<string name="feed">Alimentar</string>
<string name="hatch_with">Chocar mascote com %s</string>
<string name="hatched_pet_title">Você chocou um %1$s %2$s!</string>
<string name="evolved_pet_title">Você domou %1$s %2$s, vamos dar um passeio !</string>
<string name="hatched_pet_title">Você chocou um %s!</string>
<string name="evolved_pet_title">Você domou %s, vamos dar um passeio !</string>
<string name="close">Fechar</string>
<string name="share">Compartilhar</string>
<string name="notification_pet_fed">Você alimentou seu %1$s %2$s!</string>
<string name="notification_pet_fed">Você alimentou seu %s!</string>
<string name="notification_purchase">Você comprou %s</string>
<string name="notification_purchase_reward">Você comprou uma recompensa</string>
<string name="sectionpets">Base</string>

View file

@ -279,14 +279,14 @@
<string name="feed_to_pet">Alimento para o animal</string>
<string name="hatch_egg">Nascimento com ovo</string>
<string name="invite_party">Convidar a equipa</string>
<string name="dialog_feeding">Alimente %1$s %2$s com:</string>
<string name="dialog_feeding">Alimente %s com:</string>
<string name="use_animal">Usar</string>
<string name="feed">Alimentar</string>
<string name="hatch_with">Nascimento do animal com %s</string>
<string name="hatched_pet_title">Chocou um %1$s %2$s!</string>
<string name="hatched_pet_title">Chocou um %s!</string>
<string name="close">Fechar</string>
<string name="share">Partilhar</string>
<string name="notification_pet_fed">Alimentou o seu %1$s %2$s!</string>
<string name="notification_pet_fed">Alimentou o seu %s!</string>
<string name="notification_purchase">Comprou %s</string>
<string name="notification_purchase_reward">Comprou uma recompensa</string>
<string name="sectionpets">Padrão</string>

View file

@ -294,15 +294,15 @@
<string name="feed_to_pet">Покормить питомца</string>
<string name="hatch_egg">Вывести питомца из яйца</string>
<string name="invite_party">Пригласить команду</string>
<string name="dialog_feeding">Покормить %1$s %2$s:</string>
<string name="dialog_feeding">Покормить %s:</string>
<string name="use_animal">Использовать</string>
<string name="feed">Покормить</string>
<string name="hatch_with">Вылупить питомца с помощью %s</string>
<string name="hatched_pet_title">У вас вылупился %1$s %2$s!</string>
<string name="evolved_pet_title">Вы приручили %1$s%2$s, пора покататься! </string>
<string name="hatched_pet_title">У вас вылупился %s!</string>
<string name="evolved_pet_title">"Вы приручили %s, пора покататься! "</string>
<string name="close">Закрыть</string>
<string name="share">Поделиться</string>
<string name="notification_pet_fed">Вы покормили вашего %1$s %2$s!</string>
<string name="notification_pet_fed">Вы покормили вашего %s!</string>
<string name="notification_purchase">Вы купили %s</string>
<string name="notification_purchase_reward">Вы купили награду</string>
<string name="sectionpets">Обычные</string>

View file

@ -296,15 +296,15 @@
<string name="feed_to_pet">Evcil hayvana besle</string>
<string name="hatch_egg">Yumurta ile üret</string>
<string name="invite_party">Takımı davet et</string>
<string name="dialog_feeding">%1$s %2$s besle:</string>
<string name="dialog_feeding">%s besle:</string>
<string name="use_animal">Kullan</string>
<string name="feed">Besle</string>
<string name="hatch_with">Evcil hayvanı %s ile üret</string>
<string name="hatched_pet_title">%1$s %2$s ürettin!</string>
<string name="evolved_pet_title">Bir %1$s %2$s ehlileştirdin.</string>
<string name="hatched_pet_title">%s ürettin!</string>
<string name="evolved_pet_title">Bir %s ehlileştirdin.</string>
<string name="close">Kapat</string>
<string name="share">Paylaş</string>
<string name="notification_pet_fed">%1$s %2$s besledin!</string>
<string name="notification_pet_fed">%s besledin!</string>
<string name="notification_purchase">%s satın aldın</string>
<string name="notification_purchase_reward">Bir ödül satın aldın</string>
<string name="sectionpets">Standart</string>

View file

@ -294,15 +294,15 @@
<string name="feed_to_pet">餵食寵物</string>
<string name="hatch_egg">孵化寵物蛋</string>
<string name="invite_party">隊伍邀請</string>
<string name="dialog_feeding">餵養%1$s %2$s用</string>
<string name="dialog_feeding">餵養%s用</string>
<string name="use_animal"></string>
<string name="feed"></string>
<string name="hatch_with">用 %s 孵化寵物</string>
<string name="hatched_pet_title">你孵化了一隻 %1$s %2$s</string>
<string name="evolved_pet_title">你馴服了%1$s%2$s讓我們騎上牠吧</string>
<string name="hatched_pet_title">你孵化了一隻 %s</string>
<string name="evolved_pet_title">你馴服了%s讓我們騎上牠吧</string>
<string name="close">關閉</string>
<string name="share">分享</string>
<string name="notification_pet_fed">你餵食了你的%1$s %2$s</string>
<string name="notification_pet_fed">你餵食了你的%s</string>
<string name="notification_purchase">你購買了%s</string>
<string name="notification_purchase_reward">你購買了一個獎勵</string>
<string name="sectionpets">基本寵物</string>

View file

@ -298,15 +298,15 @@
<string name="feed_to_pet">喂养宠物</string>
<string name="hatch_egg">孵化宠物蛋</string>
<string name="invite_party">邀请队伍</string>
<string name="dialog_feeding">喂养%1$s %2$s用</string>
<string name="dialog_feeding">喂养%s用</string>
<string name="use_animal">使用</string>
<string name="feed">喂食</string>
<string name="hatch_with">用%s孵化宠物</string>
<string name="hatched_pet_title">你孵化了一个 %1$s %2$s</string>
<string name="evolved_pet_title">您驯服了%1$s%2$s我们去骑一圈吧</string>
<string name="hatched_pet_title">你孵化了一个 %s</string>
<string name="evolved_pet_title">您驯服了%s我们去骑一圈吧</string>
<string name="close">关闭</string>
<string name="share">分享</string>
<string name="notification_pet_fed">你喂食了你的%1$s %2$s</string>
<string name="notification_pet_fed">你喂食了你的%s</string>
<string name="notification_purchase">你购买了%s</string>
<string name="notification_purchase_reward">你购买了一个奖励</string>
<string name="sectionpets">基本宠物</string>

View file

@ -326,15 +326,15 @@
<string name="feed_to_pet">Feed to pet</string>
<string name="hatch_egg">Hatch with egg</string>
<string name="invite_party">Invite party</string>
<string name="dialog_feeding">Feed %1$s %2$s with:</string>
<string name="dialog_feeding">Feed %s with:</string>
<string name="use_animal">Use</string>
<string name="feed">Feed</string>
<string name="hatch_with">Hatch pet with %s</string>
<string name="hatched_pet_title">You hatched a %1$s %2$s!</string>
<string name="evolved_pet_title">You have tamed %1$s %2$s, let\'s go for a ride!</string>
<string name="hatched_pet_title">You hatched a %s!</string>
<string name="evolved_pet_title">You have tamed %s, let\'s go for a ride!</string>
<string name="close">Close</string>
<string name="share">Share</string>
<string name="notification_pet_fed" >You fed your %1$s %2$s!</string>
<string name="notification_pet_fed" >You fed your %s!</string>
<string name="notification_purchase" >You purchased %s</string>
<string name="notification_purchase_reward" >You purchased a reward</string>
<string name="sectionpets">Standard</string>

View file

@ -0,0 +1,8 @@
<network-security-config>
<debug-overrides>
<trust-anchors>
<!-- Trust user added CAs while debuggable only -->
<certificates src="user" />
</trust-anchors>
</debug-overrides>
</network-security-config>

View file

@ -20,5 +20,9 @@
<key>enableUsernameAutocomplete</key>
<value>false</value>
</entry>
<entry>
<key>enableLocalChanges</key>
<value>true</value>
</entry>
</defaultsMap>
<!-- END xml_defaults -->

View file

@ -57,11 +57,10 @@ import com.habitrpg.android.habitica.utils.QuestDeserializer;
import com.habitrpg.android.habitica.utils.QuestDropItemsListSerialization;
import com.habitrpg.android.habitica.utils.QuestListDeserializer;
import com.habitrpg.android.habitica.utils.SkillDeserializer;
import com.habitrpg.android.habitica.utils.TaskDeserializer;
import com.habitrpg.android.habitica.utils.TaskListDeserializer;
import com.habitrpg.android.habitica.utils.TaskSerializer;
import com.habitrpg.android.habitica.utils.TaskTagDeserializer;
import com.habitrpg.android.habitica.utils.TutorialStepListDeserializer;
import com.habitrpg.android.habitica.utils.TaskTagDeserializer;
import com.habitrpg.android.habitica.utils.UserDeserializer;
import com.habitrpg.android.habitica.utils.WorldStateSerialization;
@ -76,8 +75,8 @@ import retrofit2.converter.gson.GsonConverterFactory;
public class GSonFactoryCreator {
public static GsonConverterFactory create() {
Type taskTagClassListType = new TypeToken<RealmList<Tag>>() {}.getType();
Type skillListType = new TypeToken<List<Skill>>() {}.getType();
Type taskTagClassListType = new TypeToken<RealmList<Tag>>() {}.getType();
Type customizationListType = new TypeToken<RealmList<Customization>>() {}.getType();
Type tutorialStepListType = new TypeToken<RealmList<TutorialStep>>() {}.getType();
Type faqArticleListType = new TypeToken<RealmList<FAQArticle>>() {}.getType();
@ -133,7 +132,6 @@ public class GSonFactoryCreator {
.registerTypeAdapter(Member.class, new MemberSerialization())
.registerTypeAdapter(WorldState.class, new WorldStateSerialization())
.registerTypeAdapter(FindUsernameResult.class, new FindUsernameResultDeserializer())
//.registerTypeAdapter(Task.class, new TaskDeserializer())
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
.create();
return GsonConverterFactory.create(gson);

View file

@ -69,4 +69,5 @@ interface UserRepository : BaseRepository {
fun allocatePoint(user: User?, stat: String): Flowable<Stats>
fun bulkAllocatePoints(user: User?, strength: Int, intelligence: Int, constitution: Int, perception: Int): Flowable<Stats>
fun useCustomization(user: User?, type: String, category: String?, identifier: String): Flowable<User>
}

View file

@ -19,7 +19,7 @@ abstract class ContentRepositoryImpl<T : ContentLocalRepository>(localRepository
override fun retrieveContent(forced: Boolean): Flowable<ContentResult> {
val now = Date().time
return if (forced || now - this.lastContentSync > 3600000) {
return if (forced || now - this.lastContentSync > 3) {
lastContentSync = now
apiClient.content.doOnNext { localRepository.saveContent(it) }
} else {

View file

@ -3,6 +3,7 @@ package com.habitrpg.android.habitica.data.implementation
import com.habitrpg.android.habitica.data.ApiClient
import com.habitrpg.android.habitica.data.InventoryRepository
import com.habitrpg.android.habitica.data.local.InventoryLocalRepository
import com.habitrpg.android.habitica.helpers.RemoteConfigManager
import com.habitrpg.android.habitica.models.inventory.*
import com.habitrpg.android.habitica.models.responses.BuyResponse
import com.habitrpg.android.habitica.models.responses.FeedResponse
@ -13,7 +14,7 @@ import com.habitrpg.android.habitica.models.user.User
import io.reactivex.Flowable
import io.realm.RealmResults
class InventoryRepositoryImpl(localRepository: InventoryLocalRepository, apiClient: ApiClient, userID: String) : ContentRepositoryImpl<InventoryLocalRepository>(localRepository, apiClient, userID), InventoryRepository {
class InventoryRepositoryImpl(localRepository: InventoryLocalRepository, apiClient: ApiClient, userID: String, var remoteConfigManager: RemoteConfigManager) : ContentRepositoryImpl<InventoryLocalRepository>(localRepository, apiClient, userID), InventoryRepository {
override fun getQuestContent(key: String): Flowable<QuestContent> {
return localRepository.getQuestContent(key)
@ -142,6 +143,30 @@ class InventoryRepositoryImpl(localRepository: InventoryLocalRepository, apiClie
}
override fun equip(user: User?, type: String, key: String): Flowable<Items> {
if (user != null && remoteConfigManager.enableLocalChanges()) {
localRepository.executeTransaction {
if (type == "mount") {
user.items?.currentMount = key
} else if (type == "pet") {
user.items?.currentPet = key
}
val outfit = if (type == "costume") {
user.items?.gear?.costume
} else {
user.items?.gear?.equipped
}
when (key.split("_").firstOrNull()) {
"weapon" -> outfit?.head = key
"armor" -> outfit?.armor = key
"shield" -> outfit?.shield = key
"eyewear" -> outfit?.eyeWear = key
"head" -> outfit?.head = key
"back" -> outfit?.back = key
"headAccessory" -> outfit?.headAccessory = key
"body" -> outfit?.body = key
}
}
}
return apiClient.equipItem(type, key)
.doOnNext { items ->
if (user == null) {

View file

@ -4,6 +4,7 @@ import com.habitrpg.android.habitica.data.ApiClient
import com.habitrpg.android.habitica.data.TaskRepository
import com.habitrpg.android.habitica.data.UserRepository
import com.habitrpg.android.habitica.data.local.UserLocalRepository
import com.habitrpg.android.habitica.helpers.RemoteConfigManager
import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.models.Skill
import com.habitrpg.android.habitica.models.inventory.Customization
@ -21,7 +22,7 @@ import io.realm.RealmResults
import java.util.*
import java.util.concurrent.TimeUnit
class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiClient, userID: String, private val taskRepository: TaskRepository) : BaseRepositoryImpl<UserLocalRepository>(localRepository, apiClient, userID), UserRepository {
class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiClient, userID: String, private val taskRepository: TaskRepository, var remoteConfigManager: RemoteConfigManager) : BaseRepositoryImpl<UserLocalRepository>(localRepository, apiClient, userID), UserRepository {
private var lastSync: Date? = null
@ -274,6 +275,34 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
}
override fun useCustomization(user: User?, type: String, category: String?, identifier: String): Flowable<User> {
if (user != null && remoteConfigManager.enableLocalChanges()) {
localRepository.executeTransaction {
when (type) {
"skin" -> user.preferences?.setSkin(identifier)
"shirt" -> user.preferences?.setShirt(identifier)
"hair" -> {
when (category) {
"color" -> user.preferences?.hair?.color = identifier
"flower" -> user.preferences?.hair?.flower = identifier.toInt()
"mustache" -> user.preferences?.hair?.mustache = identifier.toInt()
"beard" -> user.preferences?.hair?.beard = identifier.toInt()
"bangs" -> user.preferences?.hair?.bangs = identifier.toInt()
"base" -> user.preferences?.hair?.base = identifier.toInt()
}
}
"background" -> user.preferences?.setBackground(identifier)
"chair" -> user.preferences?.setChair(identifier)
}
}
}
var updatePath = "preferences.$type"
if (category != null) {
updatePath = "$updatePath.$category"
}
return updateUser(user, updatePath, identifier)
}
private fun mergeUser(oldUser: User?, newUser: User): User {
if (oldUser == null || !oldUser.isValid) {
return oldUser ?: newUser

View file

@ -19,10 +19,11 @@ import io.realm.Sort
class RealmInventoryLocalRepository(realm: Realm, private val context: Context) : RealmContentLocalRepository(realm), InventoryLocalRepository {
override fun getQuestContent(key: String): Flowable<QuestContent> {
return realm.where(QuestContent::class.java).equalTo("key", key).findFirstAsync()
.asFlowable<RealmObject>()
.filter { realmObject -> realmObject.isLoaded }
.cast(QuestContent::class.java)
return realm.where(QuestContent::class.java).equalTo("key", key)
.findAll()
.asFlowable()
.filter { content -> content.isLoaded && content.isValid && !content.isEmpty() }
.map { content -> content.first() }
}
override fun getEquipment(searchedKeys: List<String>): Flowable<RealmResults<Equipment>> {
@ -126,7 +127,7 @@ class RealmInventoryLocalRepository(realm: Realm, private val context: Context)
override fun getMounts(type: String, group: String): Flowable<RealmResults<Mount>> {
return realm.where(Mount::class.java)
.sort("color", Sort.ASCENDING)
.equalTo("animalGroup", group)
.equalTo("type", group)
.equalTo("animal", type)
.findAll()
.asFlowable()
@ -136,16 +137,15 @@ class RealmInventoryLocalRepository(realm: Realm, private val context: Context)
override fun getOwnedMounts(): Flowable<RealmResults<Mount>> {
return realm.where(Mount::class.java)
.equalTo("owned", true)
.sort("animalGroup", Sort.ASCENDING, "animal", Sort.ASCENDING)
.sort("type", Sort.ASCENDING, "animal", Sort.ASCENDING)
.findAll()
.asFlowable()
.filter { it.isLoaded }
}
override fun getOwnedMounts(animalType: String, animalGroup: String): Flowable<RealmResults<Mount>> {
val thisAnimalGroup = animalGroup.replace("pets", "mounts").replace("Pets", "Mounts")
return realm.where(Mount::class.java)
.equalTo("animalGroup", thisAnimalGroup)
.equalTo("type", animalGroup)
.equalTo("animal", animalType)
.equalTo("owned", true)
.sort("animal")
@ -156,7 +156,7 @@ class RealmInventoryLocalRepository(realm: Realm, private val context: Context)
override fun getPets(): Flowable<RealmResults<Pet>> {
return realm.where(Pet::class.java)
.sort("animalGroup", Sort.ASCENDING, "animal", Sort.ASCENDING)
.sort("type", Sort.ASCENDING, "animal", Sort.ASCENDING)
.findAll()
.asFlowable()
.filter { it.isLoaded }
@ -165,7 +165,7 @@ class RealmInventoryLocalRepository(realm: Realm, private val context: Context)
override fun getPets(type: String, group: String): Flowable<RealmResults<Pet>> {
return realm.where(Pet::class.java)
.sort("color", Sort.ASCENDING)
.equalTo("animalGroup", group)
.equalTo("type", group)
.equalTo("animal", type)
.findAll()
.asFlowable()
@ -175,7 +175,7 @@ class RealmInventoryLocalRepository(realm: Realm, private val context: Context)
override fun getOwnedPets(): Flowable<RealmResults<Pet>> {
return realm.where(Pet::class.java)
.greaterThan("trained", 0)
.sort("animalGroup", Sort.ASCENDING, "animal", Sort.ASCENDING)
.sort("type", Sort.ASCENDING, "animal", Sort.ASCENDING)
.findAll()
.asFlowable()
.filter { it.isLoaded }
@ -183,7 +183,7 @@ class RealmInventoryLocalRepository(realm: Realm, private val context: Context)
override fun getOwnedPets(type: String, group: String): Flowable<RealmResults<Pet>> {
return realm.where(Pet::class.java)
.equalTo("animalGroup", group)
.equalTo("type", group)
.equalTo("animal", type)
.greaterThan("trained", 0)
.sort("animal")

View file

@ -0,0 +1,11 @@
package com.habitrpg.android.habitica.extensions
import com.google.gson.JsonObject
fun JsonObject?.getAsString(key: String): String {
if (this?.get(key)?.isJsonPrimitive == true) {
return this.get(key)?.asString ?: ""
}
return ""
}

View file

@ -1,18 +1,8 @@
package com.habitrpg.android.habitica.helpers
import android.content.Context
import android.os.AsyncTask
import androidx.preference.PreferenceManager
import com.google.firebase.remoteconfig.FirebaseRemoteConfig
import com.google.gson.Gson
import com.google.gson.JsonObject
import com.google.gson.reflect.TypeToken
import okhttp3.OkHttpClient
import okhttp3.Request
import org.json.JSONException
import org.json.JSONObject
import java.io.*
class RemoteConfigManager {
@ -50,4 +40,8 @@ class RemoteConfigManager {
fun enableUsernameAutocomplete(): Boolean {
return remoteConfig.getBoolean("enableUsernameAutocomplete")
}
fun enableLocalChanges(): Boolean {
return remoteConfig.getBoolean("enableLocalChanges")
}
}

View file

@ -1,11 +1,20 @@
package com.habitrpg.android.habitica.models.inventory;
public interface Animal {
public String getKey();
public void setKey(String key);
public String getText();
public void setText(String text);
public String getType();
public void setType(String type);
public String getAnimal();
public void setAnimal(String animal);
@ -18,22 +27,10 @@ public interface Animal {
public void setAnimalGroup(String group);
public String getAnimalText();
public void setAnimalText(String animalText);
public String getColorText();
public void setColorText(String colorText);
public boolean getPremium();
public void setPremium(boolean premium);
public boolean getLimited();
public void setLimited(boolean limited);
public Integer getNumberOwned();
public void setNumberOwned(Integer numberOwned);

View file

@ -28,6 +28,7 @@ public class Customization extends RealmObject {
this.id = id;
}
@Nullable
public String getIdentifier() {
return this.identifier;
}
@ -37,6 +38,7 @@ public class Customization extends RealmObject {
this.updateID();
}
@Nullable
public String getCategory() {
return this.category;
}
@ -46,6 +48,7 @@ public class Customization extends RealmObject {
this.updateID();
}
@Nullable
public String getType() {
return this.type;
}

View file

@ -11,8 +11,8 @@ public class Mount extends RealmObject implements Animal {
Boolean owned;
@PrimaryKey
String key;
String animal, color, animalGroup, animalText, colorText;
boolean premium, limited;
String animal, color, animalGroup, text, type;
boolean premium;
@Ignore
Integer numberOwned;
@ -25,6 +25,26 @@ public class Mount extends RealmObject implements Animal {
this.key = key;
}
@Override
public String getText() {
return text;
}
@Override
public void setText(String text) {
this.text = text;
}
@Override
public String getType() {
return type;
}
@Override
public void setType(String type) {
this.type = type;
}
public String getAnimal() {
if (animal == null) {
return key.split("-")[0];
@ -58,28 +78,6 @@ public class Mount extends RealmObject implements Animal {
this.animalGroup = group;
}
public String getAnimalText() {
if (animalText == null) {
return animal;
}
return animalText;
}
public void setAnimalText(String animalText) {
this.animalText = animalText;
}
public String getColorText() {
if (colorText == null) {
return color;
}
return colorText;
}
public void setColorText(String colorText) {
this.colorText = colorText;
}
public boolean getPremium() {
return premium;
}
@ -88,14 +86,6 @@ public class Mount extends RealmObject implements Animal {
this.premium = premium;
}
public boolean getLimited() {
return limited;
}
public void setLimited(boolean limited) {
this.limited = limited;
}
public Integer getNumberOwned() {
if (numberOwned == null) {
return 0;

View file

@ -10,8 +10,8 @@ public class Pet extends RealmObject implements Animal{
Integer trained;
@PrimaryKey
String key;
String animal, color, animalGroup, animalText, colorText;
boolean premium, limited;
String animal, color, animalGroup, text, type;
boolean premium;
@Ignore
private Integer numberOwned;
@ -24,6 +24,26 @@ public class Pet extends RealmObject implements Animal{
this.key = key;
}
@Override
public String getText() {
return text;
}
@Override
public void setText(String text) {
this.text = text;
}
@Override
public String getType() {
return type;
}
@Override
public void setType(String type) {
this.type = type;
}
public String getAnimal() {
if (animal == null) {
return getKey().split("-")[0];
@ -57,28 +77,6 @@ public class Pet extends RealmObject implements Animal{
this.animalGroup = group;
}
public String getAnimalText() {
if (animalText == null) {
return animal;
}
return animalText;
}
public void setAnimalText(String animalText) {
this.animalText = animalText;
}
public String getColorText() {
if (colorText == null) {
return color;
}
return colorText;
}
public void setColorText(String colorText) {
this.colorText = colorText;
}
public boolean getPremium() {
return premium;
}
@ -87,14 +85,6 @@ public class Pet extends RealmObject implements Animal{
this.premium = premium;
}
public boolean getLimited() {
return limited;
}
public void setLimited(boolean limited) {
this.limited = limited;
}
public Integer getNumberOwned() {
if (numberOwned == null) {
return 0;

View file

@ -42,6 +42,7 @@ import com.habitrpg.android.habitica.data.local.implementation.RealmTagLocalRepo
import com.habitrpg.android.habitica.data.local.implementation.RealmTaskLocalRepository;
import com.habitrpg.android.habitica.data.local.implementation.RealmTutorialLocalRepository;
import com.habitrpg.android.habitica.data.local.implementation.RealmUserLocalRepository;
import com.habitrpg.android.habitica.helpers.RemoteConfigManager;
import javax.inject.Named;
import javax.inject.Singleton;
@ -100,8 +101,8 @@ public class RepositoryModule {
}
@Provides
UserRepository providesUserRepository(UserLocalRepository localRepository, ApiClient apiClient, @Named(AppModule.NAMED_USER_ID) String userId, TaskRepository taskRepository) {
return new UserRepositoryImpl(localRepository, apiClient, userId, taskRepository);
UserRepository providesUserRepository(UserLocalRepository localRepository, ApiClient apiClient, @Named(AppModule.NAMED_USER_ID) String userId, TaskRepository taskRepository, RemoteConfigManager remoteConfigManager) {
return new UserRepositoryImpl(localRepository, apiClient, userId, taskRepository, remoteConfigManager);
}
@Provides
@ -120,11 +121,10 @@ public class RepositoryModule {
}
@Provides
InventoryRepository providesInventoryRepository(InventoryLocalRepository localRepository, ApiClient apiClient, @Named(AppModule.NAMED_USER_ID) String userId) {
return new InventoryRepositoryImpl(localRepository, apiClient, userId);
InventoryRepository providesInventoryRepository(InventoryLocalRepository localRepository, ApiClient apiClient, @Named(AppModule.NAMED_USER_ID) String userId, RemoteConfigManager remoteConfig) {
return new InventoryRepositoryImpl(localRepository, apiClient, userId, remoteConfig);
}
@Provides
FAQLocalRepository providesFAQLocalRepository(Realm realm) {
return new RealmFAQLocalRepository(realm);

View file

@ -187,15 +187,7 @@ open class MainActivity : BaseActivity(), TutorialView.OnTutorialReaction {
val languageHelper = LanguageHelper(sharedPreferences.getString("language", "en"))
Locale.setDefault(languageHelper.locale)
val configuration = Configuration()
if (SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) {
@Suppress("Deprecation")
configuration.locale = languageHelper.locale
} else {
configuration.setLocale(languageHelper.locale)
}
@Suppress("Deprecation")
resources.updateConfiguration(configuration,
resources.displayMetrics)
configuration.setLocale(languageHelper.locale)
super.onCreate(savedInstanceState)
if (!HabiticaBaseApplication.checkUserAuthentication(this, hostConfig)) {
@ -207,18 +199,16 @@ open class MainActivity : BaseActivity(), TutorialView.OnTutorialReaction {
avatarInHeader = AvatarWithBarsViewModel(this, avatarWithBars, userRepository)
sideAvatarView = AvatarView(this, true, false, false)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
val window = window
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.statusBarColor = ContextCompat.getColor(this, R.color.black_10_alpha)
}
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
toolbar.setPadding(0, statusBarHeight, 0, 0)
val px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16f, resources.displayMetrics)
avatarWithBars.setPadding(px.toInt(), statusBarHeight, px.toInt(), 0)
val window = window
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.statusBarColor = ContextCompat.getColor(this, R.color.black_10_alpha)
}
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
toolbar.setPadding(0, statusBarHeight, 0, 0)
val px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16f, resources.displayMetrics)
avatarWithBars.setPadding(px.toInt(), statusBarHeight, px.toInt(), 0)
compositeSubscription.add(userRepository.getUser(hostConfig.user ?: "")
compositeSubscription.add(userRepository.getUser(hostConfig.user)
.subscribe(Consumer { newUser ->
this@MainActivity.user = newUser
this@MainActivity.setUserData()
@ -566,21 +556,19 @@ open class MainActivity : BaseActivity(), TutorialView.OnTutorialReaction {
val pet = event.usingPet
this.inventoryRepository.feedPet(event.usingPet, event.usingFood)
.subscribe(Consumer { feedResponse ->
HabiticaSnackbar.showSnackbar(floatingMenuWrapper, getString(R.string.notification_pet_fed, pet.colorText, pet.animalText), SnackbarDisplayType.NORMAL)
HabiticaSnackbar.showSnackbar(floatingMenuWrapper, getString(R.string.notification_pet_fed, pet.text), SnackbarDisplayType.NORMAL)
if (feedResponse.value == -1) {
val mountWrapper = View.inflate(this, R.layout.pet_imageview, null) as FrameLayout
val mountImageView = mountWrapper.findViewById<View>(R.id.pet_imageview) as SimpleDraweeView
DataBindingUtils.loadImage(mountImageView, "Mount_Icon_" + event.usingPet.key)
val colorName = event.usingPet.colorText
val animalName = event.usingPet.animalText
val dialog = AlertDialog.Builder(this@MainActivity)
.setTitle(getString(R.string.evolved_pet_title, colorName, animalName))
.setTitle(getString(R.string.evolved_pet_title, pet.text))
.setView(mountWrapper)
.setPositiveButton(R.string.close) { hatchingDialog, _ -> hatchingDialog.dismiss() }
.setNeutralButton(R.string.share) { hatchingDialog, _ ->
val event1 = ShareEvent()
event1.sharedMessage = getString(R.string.share_raised, colorName, animalName) + " https://habitica.com/social/raise-pet"
event1.sharedMessage = getString(R.string.share_raised, pet.text) + " https://habitica.com/social/raise-pet"
val sharedImage = Bitmap.createBitmap(99, 99, Bitmap.Config.ARGB_8888)
val canvas = Canvas(sharedImage)
canvas.drawColor(ContextCompat.getColor(this, R.color.brand_300))
@ -661,7 +649,6 @@ open class MainActivity : BaseActivity(), TutorialView.OnTutorialReaction {
pushNotificationManager.setUser(user1)
pushNotificationManager.addPushDeviceUsingStoredToken()
}
.flatMap { socialRepository.retrieveInboxMessages() }
.flatMap { inventoryRepository.retrieveContent(false) }
.flatMap { inventoryRepository.retrieveWorldState() }
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())

View file

@ -54,7 +54,7 @@ class MountDetailRecyclerAdapter(data: OrderedRealmCollection<Mount>?, autoUpdat
fun bind(item: Mount) {
animal = item
titleView.text = item.colorText
titleView.text = item.color
ownedTextView.visibility = View.GONE
this.imageView.alpha = 1.0f
if (this.animal?.owned == true) {

View file

@ -77,7 +77,7 @@ class PetDetailRecyclerAdapter(data: OrderedRealmCollection<Pet>?, autoUpdate: B
fun bind(item: Pet) {
this.animal = item
this.titleView.text = item.colorText
this.titleView.text = item.color
this.trainedProgressbar.visibility = if (animal?.animalGroup == "specialPets") View.GONE else View.VISIBLE
this.imageView.alpha = 1.0f
if (this.animal?.trained ?: 0 > 0) {

View file

@ -74,7 +74,7 @@ class StableRecyclerAdapter : androidx.recyclerview.widget.RecyclerView.Adapter<
fun bind(item: Animal) {
this.animal = item
titleView.text = item.animalText
titleView.text = item.animal
ownedTextView.visibility = View.VISIBLE
this.imageView.alpha = 1.0f
if (item.numberOwned > 0) {

View file

@ -42,11 +42,7 @@ class AvatarCustomizationFragment : BaseMainFragment() {
compositeSubscription.add(adapter.getSelectCustomizationEvents()
.flatMap { customization ->
var updatePath = "preferences." + customization.type
if (customization.category != null) {
updatePath = updatePath + "." + customization.category
}
userRepository.updateUser(user, updatePath, customization.identifier)
userRepository.useCustomization(user, customization.type ?: "", customization.category, customization.identifier ?: "")
}
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(adapter.getUnlockCustomizationEvents()

View file

@ -123,7 +123,7 @@ class ItemRecyclerFragment : BaseFragment() {
}
this.isFeeding -> {
dialog?.requestWindowFeature(Window.FEATURE_NO_TITLE)
this.titleView?.text = getString(R.string.dialog_feeding, this.feedingPet?.colorText, this.feedingPet?.animalText)
this.titleView?.text = getString(R.string.dialog_feeding, this.feedingPet?.text)
this.titleView?.visibility = View.VISIBLE
this.footerView?.text = getString(R.string.feeding_market_info)
this.footerView?.visibility = View.VISIBLE

View file

@ -135,8 +135,7 @@ class StableRecyclerFragment : BaseFragment() {
var lastAnimal: Animal = unsortedAnimals[0]
for (animal in unsortedAnimals) {
if (animal.animal != lastAnimal.animal || animal === unsortedAnimals[unsortedAnimals.size - 1]) {
if (!((lastAnimal.animalGroup == "premiumPets" || lastAnimal.animalGroup == "specialPets"
|| lastAnimal.animalGroup == "specialMounts" || lastAnimal.animalGroup == "premiumMounts") && lastAnimal.numberOwned == 0)) {
if (!((lastAnimal.type == "premium" || lastAnimal.type == "special") && lastAnimal.numberOwned == 0)) {
items.add(lastAnimal)
}
lastAnimal = animal
@ -151,14 +150,14 @@ class StableRecyclerFragment : BaseFragment() {
if (user != null && user?.items != null) {
when (itemType) {
"pets" -> {
val pet = animal as Pet
if (pet.trained > 0) {
val pet = animal as? Pet
if (pet?.trained ?: 0 > 0) {
lastAnimal.numberOwned = lastAnimal.numberOwned + 1
}
}
"mounts" -> {
val mount = animal as Mount
if (mount.owned) {
val mount = animal as? Mount
if (mount?.owned == true) {
lastAnimal.numberOwned = lastAnimal.numberOwned + 1
}
}

View file

@ -60,21 +60,15 @@ class KeyboardUtil(activity: Activity, private val contentView: View) {
}
init {
if (Build.VERSION.SDK_INT >= 19) {
decorView.viewTreeObserver.addOnGlobalLayoutListener(onGlobalLayoutListener)
}
decorView.viewTreeObserver.addOnGlobalLayoutListener(onGlobalLayoutListener)
}
fun enable() {
if (Build.VERSION.SDK_INT >= 19) {
decorView.viewTreeObserver.addOnGlobalLayoutListener(onGlobalLayoutListener)
}
decorView.viewTreeObserver.addOnGlobalLayoutListener(onGlobalLayoutListener)
}
fun disable() {
if (Build.VERSION.SDK_INT >= 19) {
decorView.viewTreeObserver.removeOnGlobalLayoutListener(onGlobalLayoutListener)
}
decorView.viewTreeObserver.removeOnGlobalLayoutListener(onGlobalLayoutListener)
}
companion object {

View file

@ -1,154 +0,0 @@
package com.habitrpg.android.habitica.utils;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.reflect.TypeToken;
import com.habitrpg.android.habitica.data.CustomizationRepository;
import com.habitrpg.android.habitica.models.ContentGear;
import com.habitrpg.android.habitica.models.ContentResult;
import com.habitrpg.android.habitica.models.FAQArticle;
import com.habitrpg.android.habitica.models.Skill;
import com.habitrpg.android.habitica.models.inventory.Customization;
import com.habitrpg.android.habitica.models.inventory.Egg;
import com.habitrpg.android.habitica.models.inventory.Equipment;
import com.habitrpg.android.habitica.models.inventory.Food;
import com.habitrpg.android.habitica.models.inventory.HatchingPotion;
import com.habitrpg.android.habitica.models.inventory.Mount;
import com.habitrpg.android.habitica.models.inventory.Pet;
import com.habitrpg.android.habitica.models.inventory.QuestContent;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import io.realm.RealmList;
public class ContentDeserializer implements JsonDeserializer<ContentResult> {
@Inject
CustomizationRepository customizationRepository;
@Override
public ContentResult deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
ContentResult result = new ContentResult();
JsonObject object = json.getAsJsonObject();
result.potion = context.deserialize(object.get("potion"), Equipment.class);
//result.potion.imageName = "shop_potion";
//result.potion.currency = "gold";
result.armoire = context.deserialize(object.get("armoire"), Equipment.class);
//result.armoire.imageName = "shop_armoire";
//result.armoire.currency = "gold";
result.gear = context.deserialize(object.get("gear"), ContentGear.class);
result.quests = context.deserialize(object.get("quests"), new TypeToken<RealmList<QuestContent>>() {}.getType());
result.eggs = context.deserialize(object.get("eggs"), new TypeToken<RealmList<Egg>>() {}.getType());
result.food = context.deserialize(object.get("food"), new TypeToken<RealmList<Food>>() {}.getType());
result.hatchingPotions = context.deserialize(object.get("hatchingPotions"), new TypeToken<RealmList<HatchingPotion>>() {}.getType());
Map<String, Pet> pets = context.deserialize(object.get("pets"), new TypeToken<Map<String, Pet>>() {}.getType());
Map<String, Pet> specialPets = context.deserialize(object.get("specialPets"), new TypeToken<Map<String, Pet>>() {}.getType());
Map<String, Pet> premiumPets = context.deserialize(object.get("premiumPets"), new TypeToken<Map<String, Pet>>() {}.getType());
Map<String, Pet> questPets = context.deserialize(object.get("questPets"), new TypeToken<Map<String, Pet>>() {}.getType());
Map<String, Pet> whackyPets = context.deserialize(object.get("whackyPets"), new TypeToken<Map<String, Pet>>() {}.getType());
if (whackyPets == null) {
whackyPets = new HashMap<>();
}
Map<String, Mount> mounts = context.deserialize(object.get("mounts"), new TypeToken<Map<String, Mount>>() {}.getType());
Map<String, Mount> specialMounts = context.deserialize(object.get("specialMounts"), new TypeToken<Map<String, Mount>>() {}.getType());
Map<String, Mount> premiumMounts = context.deserialize(object.get("premiumMounts"), new TypeToken<Map<String, Mount>>() {}.getType());
Map<String, Mount> questMounts = context.deserialize(object.get("questMounts"), new TypeToken<Map<String, Mount>>() {}.getType());
Map<String, Mount> whackyMounts = context.deserialize(object.get("whackyMounts"), new TypeToken<Map<String, Mount>>() {}.getType());
if (whackyMounts == null) {
whackyMounts = new HashMap<>();
}
for (Egg egg : result.eggs) {
for (HatchingPotion potion : result.hatchingPotions) {
String key = egg.getKey() + "-" + potion.getKey();
if (pets.containsKey(key)) {
pets.put(key, this.populatePet(pets.get(key), egg, potion, "pets"));
}
if (specialPets.containsKey(key)) {
specialPets.put(key, this.populatePet(specialPets.get(key), egg, potion, "specialPets"));
}
if (premiumPets.containsKey(key)) {
premiumPets.put(key, this.populatePet(premiumPets.get(key), egg, potion, "premiumPets"));
}
if (questPets.containsKey(key)) {
questPets.put(key, this.populatePet(questPets.get(key), egg, potion, "questPets"));
}
if (whackyPets.containsKey(key)) {
whackyPets.put(key, this.populatePet(whackyPets.get(key), egg, potion, "whackyPets"));
}
if (mounts.containsKey(key)) {
mounts.put(key, this.populateMount(mounts.get(key), egg, potion, "mounts"));
}
if (specialMounts.containsKey(key)) {
specialMounts.put(key, this.populateMount(specialMounts.get(key), egg, potion, "specialMounts"));
}
if (premiumMounts.containsKey(key)) {
premiumMounts.put(key, this.populateMount(premiumMounts.get(key), egg, potion, "premiumMounts"));
}
if (questMounts.containsKey(key)) {
questMounts.put(key, this.populateMount(questMounts.get(key), egg, potion, "questMounts"));
}
if (whackyMounts.containsKey(key)) {
whackyMounts.put(key, this.populateMount(whackyMounts.get(key), egg, potion, "whackyMounts"));
}
}
}
for (Pet pet : specialPets.values()) {
pet.setAnimalGroup("specialPets");
}
for (Mount mount : specialMounts.values()) {
mount.setAnimalGroup("specialMounts");
}
result.pets = new RealmList<>();
result.pets.addAll(pets.values());
result.pets.addAll(specialPets.values());
result.pets.addAll(premiumPets.values());
result.pets.addAll(questPets.values());
result.mounts = new RealmList<>();
result.mounts.addAll(mounts.values());
result.mounts.addAll(specialMounts.values());
result.mounts.addAll(premiumMounts.values());
result.mounts.addAll(questMounts.values());
result.spells = context.deserialize(object.get("spells"), new TypeToken<List<Skill>>() {}.getType());
result.appearances = context.deserialize(object.get("appearances"), new TypeToken<RealmList<Customization>>() {}.getType());
result.backgrounds = context.deserialize(object.get("backgrounds"), new TypeToken<RealmList<Customization>>() {}.getType());
result.faq = context.deserialize(object.get("faq"), new TypeToken<RealmList<FAQArticle>>() {}.getType());
return result;
}
private Mount populateMount(Mount mount, Egg egg, HatchingPotion potion, String group) {
mount.setAnimalText(egg.getMountText());
mount.setColorText(potion.getText());
mount.setLimited(potion.getLimited());
mount.setPremium(potion.getPremium());
mount.setAnimalGroup(group);
return mount;
}
private Pet populatePet(Pet pet, Egg egg, HatchingPotion potion, String group) {
pet.setAnimalText(egg.getText());
pet.setColorText(potion.getText());
pet.setLimited(potion.getLimited());
pet.setPremium(potion.getPremium());
pet.setAnimalGroup(group);
return pet;
}
}

View file

@ -0,0 +1,108 @@
package com.habitrpg.android.habitica.utils
import com.google.firebase.perf.FirebasePerformance
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonDeserializer
import com.google.gson.JsonElement
import com.google.gson.JsonParseException
import com.google.gson.reflect.TypeToken
import com.habitrpg.android.habitica.data.CustomizationRepository
import com.habitrpg.android.habitica.extensions.getAsString
import com.habitrpg.android.habitica.models.ContentGear
import com.habitrpg.android.habitica.models.ContentResult
import com.habitrpg.android.habitica.models.FAQArticle
import com.habitrpg.android.habitica.models.Skill
import com.habitrpg.android.habitica.models.inventory.Customization
import com.habitrpg.android.habitica.models.inventory.Egg
import com.habitrpg.android.habitica.models.inventory.Equipment
import com.habitrpg.android.habitica.models.inventory.Food
import com.habitrpg.android.habitica.models.inventory.HatchingPotion
import com.habitrpg.android.habitica.models.inventory.Mount
import com.habitrpg.android.habitica.models.inventory.Pet
import com.habitrpg.android.habitica.models.inventory.QuestContent
import java.lang.reflect.Type
import javax.inject.Inject
import io.realm.RealmList
import java.util.ArrayList
class ContentDeserializer : JsonDeserializer<ContentResult> {
@Throws(JsonParseException::class)
override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): ContentResult {
val deserializeTrace = FirebasePerformance.getInstance().newTrace("ContentDeserialize")
deserializeTrace.start()
val result = ContentResult()
val obj = json.asJsonObject
result.potion = context.deserialize(obj.get("potion"), Equipment::class.java)
result.armoire = context.deserialize(obj.get("armoire"), Equipment::class.java)
result.gear = context.deserialize(obj.get("gear"), ContentGear::class.java)
result.quests = context.deserialize(obj.get("quests"), object : TypeToken<RealmList<QuestContent>>() {}.type)
result.eggs = context.deserialize(obj.get("eggs"), object : TypeToken<RealmList<Egg>>() {}.type)
result.food = context.deserialize(obj.get("food"), object : TypeToken<RealmList<Food>>() {}.type)
result.hatchingPotions = context.deserialize(obj.get("hatchingPotions"), object : TypeToken<RealmList<HatchingPotion>>() {}.type)
result.pets = RealmList()
for (key in obj.getAsJsonObject("petInfo").keySet()) {
val pet = Pet()
val petObj = obj.getAsJsonObject(key)
pet.animal = petObj.getAsString("egg")
pet.color = petObj.getAsString("potion")
pet.key = petObj.getAsString("key")
pet.text = petObj.getAsString("text")
pet.type = petObj.getAsString("type")
if (pet.type == "premium") {
pet.premium = true
}
result.pets.add(pet)
}
result.mounts = RealmList()
for (key in obj.getAsJsonObject("mountInfo").keySet()) {
val mount = Mount()
val mountObj = obj.getAsJsonObject(key)
mount.animal = mountObj.getAsString("egg")
mount.color = mountObj.getAsString("potion")
mount.key = mountObj.getAsString("key")
mount.type = mountObj.getAsString("type")
if (mount.type == "premium") {
mount.premium = true
}
result.mounts.add(mount)
}
result.spells = ArrayList<Skill>()
for ((classname, value) in obj.getAsJsonObject("spells").entrySet()) {
val classObject = value.asJsonObject
for ((_, value1) in classObject.entrySet()) {
val skillObject = value1.asJsonObject
val skill = Skill()
skill.key = skillObject.get("key").asString
skill.text = skillObject.get("text").asString
skill.notes = skillObject.get("notes").asString
skill.key = skillObject.get("key").asString
skill.target = skillObject.get("target").asString
skill.habitClass = classname
skill.mana = skillObject.get("mana").asInt
val lvlElement = skillObject.get("lvl")
if (lvlElement != null) {
skill.lvl = lvlElement.asInt
}
result.spells.add(skill)
}
}
result.appearances = context.deserialize(obj.get("appearances"), object : TypeToken<RealmList<Customization>>() {}.type)
result.backgrounds = context.deserialize(obj.get("backgrounds"), object : TypeToken<RealmList<Customization>>() {}.type)
result.faq = context.deserialize(obj.get("faq"), object : TypeToken<RealmList<FAQArticle>>() {}.type)
deserializeTrace.stop()
return result
}
}

View file

@ -23,7 +23,7 @@ public class SkillDeserializer
JsonDeserializationContext context) throws JsonParseException {
JsonObject object = json.getAsJsonObject();
List<Skill> skills = new ArrayList<Skill>();
List<Skill> skills = new ArrayList<>();
for (Map.Entry<String, JsonElement> classEntry : object.entrySet()) {
String classname = classEntry.getKey();
JsonObject classObject = classEntry.getValue().getAsJsonObject();

View file

@ -1,25 +0,0 @@
package com.habitrpg.android.habitica.utils;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.habitrpg.android.habitica.models.tasks.TaskGroupPlan;
import java.lang.reflect.Type;
public class TaskGroupPlanDeserializer implements JsonDeserializer<TaskGroupPlan> {
@Override
public TaskGroupPlan deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
TaskGroupPlan group = new TaskGroupPlan();
JsonObject object = json.getAsJsonObject();
JsonObject approvalObject = object.getAsJsonObject("approval");
group.setApprovalRequested(approvalObject.getAsJsonPrimitive("requested").getAsBoolean());
group.setApprovalApproved(approvalObject.getAsJsonPrimitive("approved").getAsBoolean());
group.setApprovalRequired(approvalObject.getAsJsonPrimitive("required").getAsBoolean());
return null;
}
}

View file

@ -1,66 +0,0 @@
package com.habitrpg.android.habitica.utils;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonArray;
import com.habitrpg.android.habitica.models.tasks.Task;
import com.habitrpg.android.habitica.models.tasks.TaskList;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by viirus on 09/12/15.
*/
public class TaskListDeserializer implements JsonDeserializer<TaskList> {
private List<Integer> getIntListFromJsonArray(JsonArray jsonArray) {
List<Integer> intList = new ArrayList<>();
for (int i = 0; i < jsonArray.size(); i++) {
intList.add(jsonArray.get(i).getAsInt());
}
return intList;
}
private void getMonthlyDays(JsonElement e, Task task) {
JsonArray weeksOfMonth = e.getAsJsonObject().getAsJsonArray("weeksOfMonth");
if (weeksOfMonth != null && weeksOfMonth.size() > 0) {
task.setWeeksOfMonth(getIntListFromJsonArray(weeksOfMonth));
}
JsonArray daysOfMonth = e.getAsJsonObject().getAsJsonArray("daysOfMonth");
if (weeksOfMonth != null && weeksOfMonth.size() > 0) {
task.setDaysOfMonth(getIntListFromJsonArray(daysOfMonth));
}
}
public TaskList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext ctx) {
TaskList tasks = new TaskList();
Map<String, Task> taskMap = new HashMap<>();
for (JsonElement e : json.getAsJsonArray()) {
try {
Task task = ctx.deserialize(e, Task.class);
// Work around since Realm does not support Arrays of ints
getMonthlyDays(e, task);
//Workaround, since gson doesn't call setter methods
task.setId(task.getId());
taskMap.put(task.getId(), task);
} catch (ClassCastException ignored) {
}
}
tasks.tasks = taskMap;
return tasks;
}
}

View file

@ -0,0 +1,172 @@
package com.habitrpg.android.habitica.utils
import com.google.firebase.perf.FirebasePerformance
import com.google.gson.*
import com.habitrpg.android.habitica.extensions.getAsString
import com.habitrpg.android.habitica.models.Tag
import com.habitrpg.android.habitica.models.tasks.*
import io.realm.Realm
import io.realm.RealmList
import java.lang.reflect.Type
import java.util.*
/**
* Created by viirus on 09/12/15.
*/
class TaskListDeserializer : JsonDeserializer<TaskList> {
private fun getIntListFromJsonArray(jsonArray: JsonArray): List<Int> {
val intList = ArrayList<Int>()
for (i in 0 until jsonArray.size()) {
intList.add(jsonArray.get(i).asInt)
}
return intList
}
private fun getMonthlyDays(e: JsonElement, task: Task) {
val weeksOfMonth = e.asJsonObject.getAsJsonArray("weeksOfMonth")
if (weeksOfMonth != null && weeksOfMonth.size() > 0) {
task.setWeeksOfMonth(getIntListFromJsonArray(weeksOfMonth))
}
val daysOfMonth = e.asJsonObject.getAsJsonArray("daysOfMonth")
if (weeksOfMonth != null && weeksOfMonth.size() > 0) {
task.setDaysOfMonth(getIntListFromJsonArray(daysOfMonth))
}
}
override fun deserialize(json: JsonElement, typeOfT: Type, ctx: JsonDeserializationContext): TaskList {
val tasks = TaskList()
val taskMap = HashMap<String, Task>()
val deserializeTrace = FirebasePerformance.getInstance().newTrace("TaskListDeserialize")
deserializeTrace.start()
var databaseTags: List<Tag>
try {
val realm = Realm.getDefaultInstance()
databaseTags = realm.copyFromRealm(realm.where(Tag::class.java).findAll())
realm.close()
} catch (e: RuntimeException) {
//Tests don't have a database
databaseTags = ArrayList()
}
for (e in json.asJsonArray) {
try {
val obj = e as? JsonObject
if (obj != null) {
val task = Task()
task.text = obj.getAsString("text")
task.notes = obj.getAsString("notes")
task.userId = obj.getAsString("userId")
task.value = obj.get("value")?.asDouble ?: 0.0
task.type = obj.getAsString("type")
task.frequency = obj.getAsString("frequency")
task.attribute = obj.getAsString("attribute")
task.everyX = obj.get("everyX")?.asInt
task.priority = obj.get("priority")?.asFloat ?: 1.0f
task.completed = obj.get("completed")?.asBoolean ?: false
task.up = obj.get("up")?.asBoolean ?: false
task.down = obj.get("down")?.asBoolean ?: false
task.streak = obj.get("streak")?.asInt
task.counterUp = obj.get("counterUp")?.asInt
task.counterDown = obj.get("counterDown")?.asInt
task.dateCreated = ctx.deserialize(obj.get("createdAt"), Date::class.java)
task.dueDate = ctx.deserialize(obj.get("date"), Date::class.java)
task.startDate = ctx.deserialize(obj.get("startDate"), Date::class.java)
task.isDue = obj.get("isDue")?.asBoolean
if (obj.has("nextDue")) {
task.nextDue = RealmList()
for (due in obj.getAsJsonArray("nextDue")) {
task.nextDue?.add(ctx.deserialize(due, Date::class.java))
}
}
task.tags = handleTags(databaseTags, obj.getAsJsonArray("tags"), ctx)
if (obj.has("checklist")) {
task.checklist = RealmList()
for (checklistElement in obj.getAsJsonArray("checklist")) {
task.checklist?.add(ChecklistItem(
obj.getAsString("id"),
obj.getAsString("text"),
obj.get("completed").asBoolean
))
}
}
if (obj.has("reminders")) {
task.reminders = RealmList()
for (reminderElement in obj.getAsJsonArray("reminders")) {
val reminder = RemindersItem()
reminder.id = obj.getAsString("id")
reminder.startDate = ctx.deserialize(obj.get("startDate"), Date::class.java)
reminder.time = ctx.deserialize(obj.get("time"), Date::class.java)
task.reminders?.add(reminder)
}
}
if (obj.has("repeat")) {
task.repeat = ctx.deserialize(obj.get("repeat"), Days::class.java)
}
if (obj.has("group")) {
val group = TaskGroupPlan()
val groupObject = obj.getAsJsonObject("group")
val approvalObject = groupObject.getAsJsonObject("approval")
group.approvalRequested = approvalObject.getAsJsonPrimitive("requested").asBoolean
group.approvalApproved = approvalObject.getAsJsonPrimitive("approved").asBoolean
group.approvalRequired = approvalObject.getAsJsonPrimitive("required").asBoolean
task.group = group
}
// Work around since Realm does not support Arrays of ints
getMonthlyDays(e, task)
//Workaround, since gson doesn't call setter methods
task.id = obj.getAsString("_id")
task.id?.let { taskMap[it] = task }
}
} catch (ignored: ClassCastException) {
}
}
tasks.tasks = taskMap
deserializeTrace.stop()
return tasks
}
private fun handleTags(databaseTags: List<Tag>, json: JsonArray?, context: JsonDeserializationContext): RealmList<Tag>? {
val tags = RealmList<Tag>()
for (tagElement in json ?: listOf<JsonElement>()) {
if (tagElement.isJsonObject) {
tags.add(context.deserialize(tagElement, Tag::class.java))
} else {
try {
val tagId = tagElement.asString
for (tag in databaseTags) {
if (tag.getId() == tagId) {
if (!alreadyContainsTag(tags, tagId)) {
tags.add(tag)
}
break
}
}
} catch (ignored: UnsupportedOperationException) {
}
}
}
return tags
}
private fun alreadyContainsTag(list: List<Tag>, idToCheck: String): Boolean {
for (t in list) {
if (t.getId() == idToCheck) {
return true
}
}
return false
}
}

View file

@ -1,5 +1,7 @@
package com.habitrpg.android.habitica.utils
import android.os.Trace
import com.google.firebase.perf.FirebasePerformance
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonDeserializer
import com.google.gson.JsonElement
@ -21,6 +23,8 @@ import java.util.*
class UserDeserializer : JsonDeserializer<User> {
@Throws(JsonParseException::class)
override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): User {
val deserializeTrace = FirebasePerformance.getInstance().newTrace("UserDeserialize")
deserializeTrace.start()
val user = User()
val obj = json.asJsonObject
@ -132,7 +136,7 @@ class UserDeserializer : JsonDeserializer<User> {
user.abTests?.add(test)
}
}
deserializeTrace.stop()
return user
}
}