diff --git a/Habitica/res/layout/drawer_main.xml b/Habitica/res/layout/drawer_main.xml
index e43b817e0..be312e20a 100644
--- a/Habitica/res/layout/drawer_main.xml
+++ b/Habitica/res/layout/drawer_main.xml
@@ -12,6 +12,7 @@
tools:context="com.habitrpg.android.habitica.ui.fragments.NavigationDrawerFragment">
+
+
+
+
-
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/api/ApiService.java b/Habitica/src/main/java/com/habitrpg/android/habitica/api/ApiService.java
index 32049c844..f71b87b4a 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/api/ApiService.java
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/api/ApiService.java
@@ -7,6 +7,7 @@ import com.habitrpg.android.habitica.models.PurchaseValidationRequest;
import com.habitrpg.android.habitica.models.PurchaseValidationResult;
import com.habitrpg.android.habitica.models.SubscriptionValidationRequest;
import com.habitrpg.android.habitica.models.Tag;
+import com.habitrpg.android.habitica.models.WorldState;
import com.habitrpg.android.habitica.models.auth.UserAuth;
import com.habitrpg.android.habitica.models.auth.UserAuthResponse;
import com.habitrpg.android.habitica.models.auth.UserAuthSocial;
@@ -355,4 +356,7 @@ public interface ApiService {
@POST("user/allocate-bulk")
Observable> bulkAllocatePoints(@Body Map> stats);
+
+ @POST("world-state")
+ Observable> getWorldState();
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/components/AppComponent.java b/Habitica/src/main/java/com/habitrpg/android/habitica/components/AppComponent.java
index 417ff1cc3..b185bcc8f 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/components/AppComponent.java
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/components/AppComponent.java
@@ -40,6 +40,7 @@ import com.habitrpg.android.habitica.ui.adapter.tasks.HabitsRecyclerViewAdapter;
import com.habitrpg.android.habitica.ui.adapter.tasks.RewardsRecyclerViewAdapter;
import com.habitrpg.android.habitica.ui.adapter.tasks.TodosRecyclerViewAdapter;
import com.habitrpg.android.habitica.ui.fragments.GemsPurchaseFragment;
+import com.habitrpg.android.habitica.ui.fragments.NavigationDrawerFragment;
import com.habitrpg.android.habitica.ui.fragments.NewsFragment;
import com.habitrpg.android.habitica.ui.fragments.StatsFragment;
import com.habitrpg.android.habitica.ui.fragments.SubscriptionFragment;
@@ -296,4 +297,6 @@ public interface AppComponent {
void inject(@NotNull PushNotificationsPreferencesFragment pushNotificationsPreferencesFragment);
void inject(WelcomeFragment welcomeFragment);
+
+ void inject(@NotNull NavigationDrawerFragment navigationDrawerFragment);
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/ApiClient.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/ApiClient.java
index 3fad9c360..cca3360f5 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/ApiClient.java
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/ApiClient.java
@@ -9,6 +9,7 @@ import com.habitrpg.android.habitica.models.PurchaseValidationRequest;
import com.habitrpg.android.habitica.models.PurchaseValidationResult;
import com.habitrpg.android.habitica.models.SubscriptionValidationRequest;
import com.habitrpg.android.habitica.models.Tag;
+import com.habitrpg.android.habitica.models.WorldState;
import com.habitrpg.android.habitica.models.auth.UserAuthResponse;
import com.habitrpg.android.habitica.models.inventory.Equipment;
import com.habitrpg.android.habitica.models.inventory.Quest;
@@ -253,4 +254,6 @@ public interface ApiClient {
Observable bulkAllocatePoints(int strength, int intelligence, int constitution, int perception);
Observable retrieveMarketGear();
+
+ Observable getWorldState();
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/ContentRepository.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/ContentRepository.java
index c044e2f8e..7703a1489 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/ContentRepository.java
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/ContentRepository.java
@@ -1,6 +1,7 @@
package com.habitrpg.android.habitica.data;
import com.habitrpg.android.habitica.models.ContentResult;
+import com.habitrpg.android.habitica.models.WorldState;
import rx.Observable;
@@ -8,4 +9,6 @@ public interface ContentRepository extends BaseRepository {
Observable retrieveContent();
Observable retrieveContent(boolean forced);
+
+ Observable retrieveWorldState();
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.java
index 96091bc51..ab6db75d9 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.java
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ApiClientImpl.java
@@ -28,6 +28,7 @@ import com.habitrpg.android.habitica.models.Skill;
import com.habitrpg.android.habitica.models.SubscriptionValidationRequest;
import com.habitrpg.android.habitica.models.Tag;
import com.habitrpg.android.habitica.models.TutorialStep;
+import com.habitrpg.android.habitica.models.WorldState;
import com.habitrpg.android.habitica.models.auth.UserAuth;
import com.habitrpg.android.habitica.models.auth.UserAuthResponse;
import com.habitrpg.android.habitica.models.auth.UserAuthSocial;
@@ -197,6 +198,9 @@ public class ApiClientImpl implements Action1, ApiClient {
if (userAgent != null) {
builder = builder.header("user-agent", userAgent);
}
+ if (!BuildConfig.STAGING_KEY.isEmpty()) {
+ builder = builder.header("Authorization", "Basic " + BuildConfig.STAGING_KEY);
+ }
Request request = builder.method(original.method(), original.body())
.build();
lastAPICallURL = original.url().toString();
@@ -1011,4 +1015,9 @@ public class ApiClientImpl implements Action1, ApiClient {
public Observable retrieveMarketGear() {
return apiService.retrieveMarketGear().compose(configureApiCallObserver());
}
+
+ @Override
+ public Observable getWorldState() {
+ return apiService.getWorldState().compose(configureApiCallObserver());
+ }
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ContentRepositoryImpl.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ContentRepositoryImpl.java
deleted file mode 100644
index fb0c24079..000000000
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ContentRepositoryImpl.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.habitrpg.android.habitica.data.implementation;
-
-import com.habitrpg.android.habitica.data.ApiClient;
-import com.habitrpg.android.habitica.data.ContentRepository;
-import com.habitrpg.android.habitica.data.local.ContentLocalRepository;
-import com.habitrpg.android.habitica.models.ContentResult;
-
-import java.util.Date;
-
-import rx.Observable;
-
-abstract class ContentRepositoryImpl extends BaseRepositoryImpl implements ContentRepository {
-
- private Date lastSync = null;
-
- public ContentRepositoryImpl(T localRepository, ApiClient apiClient) {
- super(localRepository, apiClient);
- }
-
- @Override
- public Observable retrieveContent() {
- return retrieveContent(false);
- }
-
- @Override
- public Observable retrieveContent(boolean forced) {
- if (forced || this.lastSync == null || (new Date().getTime() - this.lastSync.getTime()) > 3600000) {
- lastSync = new Date();
- return apiClient.getContent().doOnNext(localRepository::saveContent);
- } else {
- return Observable.just(null);
- }
- }
-}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ContentRepositoryImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ContentRepositoryImpl.kt
new file mode 100644
index 000000000..eebe7cc7d
--- /dev/null
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/ContentRepositoryImpl.kt
@@ -0,0 +1,40 @@
+package com.habitrpg.android.habitica.data.implementation
+
+import com.habitrpg.android.habitica.data.ApiClient
+import com.habitrpg.android.habitica.data.ContentRepository
+import com.habitrpg.android.habitica.data.local.ContentLocalRepository
+import com.habitrpg.android.habitica.models.ContentResult
+import com.habitrpg.android.habitica.models.WorldState
+
+import java.util.Date
+
+import rx.Observable
+import rx.functions.Action1
+
+internal abstract class ContentRepositoryImpl(localRepository: T, apiClient: ApiClient) : BaseRepositoryImpl(localRepository, apiClient), ContentRepository {
+
+ private var lastContentSync = Date()
+ private var lastWorldStateSync = Date()
+
+ override fun retrieveContent(): Observable {
+ return retrieveContent(false)
+ }
+
+ override fun retrieveContent(forced: Boolean): Observable {
+ return if (forced || Date().time - this.lastContentSync.time > 3600000) {
+ lastContentSync = Date()
+ apiClient.content.doOnNext({ localRepository.saveContent(it) })
+ } else {
+ Observable.just(null)
+ }
+ }
+
+ override fun retrieveWorldState(): Observable {
+ return if (Date().time - this.lastWorldStateSync.time > 3600000) {
+ lastWorldStateSync = Date()
+ apiClient.worldState.doOnNext({ localRepository.saveWorldState(it) })
+ } else {
+ Observable.just(null)
+ }
+ }
+}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/ContentLocalRepository.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/ContentLocalRepository.java
deleted file mode 100644
index bff989203..000000000
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/ContentLocalRepository.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.habitrpg.android.habitica.data.local;
-
-import com.habitrpg.android.habitica.models.ContentResult;
-
-public interface ContentLocalRepository extends BaseLocalRepository {
- void saveContent(ContentResult contentResult);
-}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/ContentLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/ContentLocalRepository.kt
new file mode 100644
index 000000000..4798a35d7
--- /dev/null
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/ContentLocalRepository.kt
@@ -0,0 +1,9 @@
+package com.habitrpg.android.habitica.data.local
+
+import com.habitrpg.android.habitica.models.ContentResult
+import com.habitrpg.android.habitica.models.WorldState
+
+interface ContentLocalRepository : BaseLocalRepository {
+ fun saveContent(contentResult: ContentResult)
+ fun saveWorldState(worldState: WorldState)
+}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmContentLocalRepository.java b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmContentLocalRepository.java
deleted file mode 100644
index ba9aea743..000000000
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmContentLocalRepository.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.habitrpg.android.habitica.data.local.implementation;
-
-import com.habitrpg.android.habitica.data.local.ContentLocalRepository;
-import com.habitrpg.android.habitica.models.ContentResult;
-
-import io.realm.Realm;
-
-
-class RealmContentLocalRepository extends RealmBaseLocalRepository implements ContentLocalRepository {
-
- RealmContentLocalRepository(Realm realm) {
- super(realm);
- }
-
- @Override
- public void saveContent(ContentResult result) {
- realm.executeTransactionAsync(realm1 -> {
- realm1.insertOrUpdate(result.potion);
- realm1.insertOrUpdate(result.armoire);
- realm1.insertOrUpdate(result.gear.flat);
-
- realm1.insertOrUpdate(result.quests);
- realm1.insertOrUpdate(result.eggs);
- realm1.insertOrUpdate(result.food);
- realm1.insertOrUpdate(result.hatchingPotions);
-
- realm1.insertOrUpdate(result.pets);
- realm1.insertOrUpdate(result.mounts);
-
- realm1.insertOrUpdate(result.spells);
- realm1.insertOrUpdate(result.appearances);
- realm1.insertOrUpdate(result.backgrounds);
- realm1.insertOrUpdate(result.faq);
- });
- }
-}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmContentLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmContentLocalRepository.kt
new file mode 100644
index 000000000..bd01b2a6d
--- /dev/null
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmContentLocalRepository.kt
@@ -0,0 +1,44 @@
+package com.habitrpg.android.habitica.data.local.implementation
+
+import com.habitrpg.android.habitica.data.local.ContentLocalRepository
+import com.habitrpg.android.habitica.models.ContentResult
+import com.habitrpg.android.habitica.models.WorldState
+import com.habitrpg.android.habitica.models.social.Group
+
+import io.realm.Realm
+
+
+internal open class RealmContentLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), ContentLocalRepository {
+
+ override fun saveContent(contentResult: ContentResult) {
+ realm.executeTransactionAsync { realm1 ->
+ realm1.insertOrUpdate(contentResult.potion)
+ realm1.insertOrUpdate(contentResult.armoire)
+ realm1.insertOrUpdate(contentResult.gear.flat)
+
+ realm1.insertOrUpdate(contentResult.quests)
+ realm1.insertOrUpdate(contentResult.eggs)
+ realm1.insertOrUpdate(contentResult.food)
+ realm1.insertOrUpdate(contentResult.hatchingPotions)
+
+ realm1.insertOrUpdate(contentResult.pets)
+ realm1.insertOrUpdate(contentResult.mounts)
+
+ realm1.insertOrUpdate(contentResult.spells)
+ realm1.insertOrUpdate(contentResult.appearances)
+ realm1.insertOrUpdate(contentResult.backgrounds)
+ realm1.insertOrUpdate(contentResult.faq)
+ }
+ }
+
+ override fun saveWorldState(worldState: WorldState) {
+ val tavern = realm.where(Group::class.java)
+ .equalTo("id", Group.TAVERN_ID)
+ .findFirst() ?: Group()
+ tavern.id = Group.TAVERN_ID
+ tavern.quest?.active = worldState.worldBossActive
+ tavern.quest?.key = worldState.worldBossKey
+ tavern.quest?.progress = worldState.progress
+ save(tavern)
+ }
+}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/WorldState.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/models/WorldState.kt
new file mode 100644
index 000000000..cb99a5444
--- /dev/null
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/WorldState.kt
@@ -0,0 +1,14 @@
+package com.habitrpg.android.habitica.models
+
+import com.facebook.internal.Mutable
+import com.habitrpg.android.habitica.models.inventory.QuestProgress
+import com.habitrpg.android.habitica.models.inventory.QuestRageStrike
+
+class WorldState {
+
+ var worldBossKey: String = ""
+ var worldBossActive: Boolean = false
+ var progress: QuestProgress? = null
+ var rageStrikes: MutableList? = null
+
+}
\ No newline at end of file
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/social/Group.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/models/social/Group.kt
index 7e16cbef9..f2e8c883b 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/social/Group.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/social/Group.kt
@@ -44,26 +44,26 @@ open class Group : RealmObject() {
var leaderMessage: String? = null
- override fun equals(o: Any?): Boolean {
- if (this === o) {
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
return true
}
- if (o == null || javaClass != o.javaClass) {
+ if (other == null || javaClass != other.javaClass) {
return false
}
- val group = o as Group?
+ val group = other as Group
- return if (id != null) id == group!!.id else group!!.id == null
+ return id == group.id
}
override fun hashCode(): Int {
- return if (id != null) id!!.hashCode() else 0
+ return id.hashCode()
}
companion object {
- val TAVERN_ID = "00000000-0000-4000-A000-000000000000"
+ const val TAVERN_ID = "00000000-0000-4000-A000-000000000000"
}
val hasActiveQuest: Boolean
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java
index 1fde0b2ba..b29397430 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/MainActivity.java
@@ -309,13 +309,17 @@ public class MainActivity extends BaseActivity implements TutorialView.OnTutoria
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
- drawerToggle.syncState();
+ if (drawerToggle != null) {
+ drawerToggle.syncState();
+ }
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- drawerToggle.onConfigurationChanged(newConfig);
+ if (drawerToggle != null) {
+ drawerToggle.onConfigurationChanged(newConfig);
+ }
}
@Override
@@ -794,6 +798,7 @@ public class MainActivity extends BaseActivity implements TutorialView.OnTutoria
pushNotificationManager.addPushDeviceUsingStoredToken();
})
.flatMap(user1 -> inventoryRepository.retrieveContent(false))
+ .flatMap(contentResult -> inventoryRepository.retrieveWorldState())
.subscribe(user1 -> {}, RxErrorHandler.handleEmptyError());
}
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/NavigationDrawerAdapter.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/NavigationDrawerAdapter.kt
index 11c0c3f3d..df19f9b5a 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/NavigationDrawerAdapter.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/NavigationDrawerAdapter.kt
@@ -1,5 +1,6 @@
package com.habitrpg.android.habitica.ui.adapter
+import android.graphics.PorterDuff
import android.support.v4.content.ContextCompat
import android.support.v7.widget.RecyclerView
import android.view.View
@@ -11,8 +12,26 @@ import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.android.habitica.ui.menu.HabiticaDrawerItem
import rx.Observable
import rx.subjects.PublishSubject
+import android.support.v4.graphics.drawable.DrawableCompat.setTint
+import android.graphics.drawable.Drawable
+import android.support.v4.graphics.drawable.DrawableCompat
+import com.habitrpg.android.habitica.extensions.backgroundCompat
+
+
+class NavigationDrawerAdapter(tintColor: Int, backgroundTintColor: Int): RecyclerView.Adapter() {
+
+ var tintColor: Int = tintColor
+ set(value) {
+ field = value
+ notifyDataSetChanged()
+ }
+
+ var backgroundTintColor: Int = backgroundTintColor
+ set(value) {
+ field = value
+ notifyDataSetChanged()
+ }
-class NavigationDrawerAdapter: RecyclerView.Adapter() {
internal val items: MutableList = ArrayList()
var selectedItem: String? = null
@@ -48,9 +67,12 @@ class NavigationDrawerAdapter: RecyclerView.Adapter() {
val drawerItem = getItem(position)
if (getItemViewType(position) == 0) {
(holder as DrawerItemViewHolder?)?.bind(drawerItem, drawerItem.identifier == selectedItem)
+ holder?.tintColor = tintColor
+ holder?.backgroundTintColor = backgroundTintColor
holder?.itemView?.setOnClickListener { itemSelectedEvents.onNext(drawerItem.identifier) }
} else {
(holder as SectionHeaderViewHolder?)?.bind(drawerItem)
+ holder?.backgroundTintColor = backgroundTintColor
}
}
@@ -70,6 +92,9 @@ class NavigationDrawerAdapter: RecyclerView.Adapter() {
class DrawerItemViewHolder(itemView: View?) : RecyclerView.ViewHolder(itemView) {
+ var tintColor: Int = 0
+ var backgroundTintColor: Int = 0
+
private val titleTextView: TextView? by bindOptionalView(itemView, R.id.titleTextView)
private val additionalInfoView: TextView? by bindOptionalView(itemView, R.id.additionalInfoView)
@@ -78,25 +103,43 @@ class NavigationDrawerAdapter: RecyclerView.Adapter() {
if (isSelected) {
itemView.setBackgroundColor(ContextCompat.getColor(itemView.context, R.color.gray_600))
- titleTextView?.setTextColor(ContextCompat.getColor(itemView.context, R.color.brand_300))
+ titleTextView?.setTextColor(tintColor)
} else {
itemView.setBackgroundColor(ContextCompat.getColor(itemView.context, R.color.white))
titleTextView?.setTextColor(ContextCompat.getColor(itemView.context, R.color.gray_50))
}
- if (drawerItem.additionalInfo != null) {
- additionalInfoView?.visibility = View.VISIBLE
- additionalInfoView?.text = drawerItem.additionalInfo
- } else {
- additionalInfoView?.visibility = View.GONE
+ val additionalInfoView = this.additionalInfoView
+ if (additionalInfoView != null) {
+ if (drawerItem.additionalInfo != null) {
+ additionalInfoView.visibility = View.VISIBLE
+ additionalInfoView.text = drawerItem.additionalInfo
+ val drawable = ContextCompat.getDrawable(itemView.context, R.drawable.pill_bg)
+ if (drawable != null) {
+ DrawableCompat.setTint(drawable, backgroundTintColor)
+
+ val pL = additionalInfoView.paddingLeft
+ val pT = additionalInfoView.paddingTop
+ val pR = additionalInfoView.paddingRight
+ val pB = additionalInfoView.paddingBottom
+
+ additionalInfoView.backgroundCompat = drawable
+ additionalInfoView.setPadding(pL, pT, pR, pB)
+ }
+ } else {
+ additionalInfoView.visibility = View.GONE
+ }
}
}
}
class SectionHeaderViewHolder(itemView: View?) : RecyclerView.ViewHolder(itemView) {
+ var backgroundTintColor: Int = 0
+
fun bind(drawerItem: HabiticaDrawerItem) {
(itemView as TextView).text = drawerItem.text
+ itemView.setBackgroundColor(backgroundTintColor)
}
}
}
\ No newline at end of file
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/NavigationDrawerFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/NavigationDrawerFragment.kt
index d0f2152d5..8eaf3488c 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/NavigationDrawerFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/NavigationDrawerFragment.kt
@@ -3,19 +3,25 @@ package com.habitrpg.android.habitica.ui.fragments
import android.app.ActionBar
import android.content.Intent
-import android.content.res.Configuration
import android.os.Bundle
import android.support.v4.app.DialogFragment
+import android.support.v4.content.ContextCompat
import android.support.v4.view.GravityCompat
import android.support.v4.widget.DrawerLayout
-import android.support.v7.app.ActionBarDrawerToggle
import android.support.v7.widget.LinearLayoutManager
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import com.habitrpg.android.habitica.HabiticaBaseApplication
import com.habitrpg.android.habitica.R
+import com.habitrpg.android.habitica.data.InventoryRepository
+import com.habitrpg.android.habitica.data.SocialRepository
+import com.habitrpg.android.habitica.data.UserRepository
import com.habitrpg.android.habitica.extensions.notNull
import com.habitrpg.android.habitica.helpers.RxErrorHandler
+import com.habitrpg.android.habitica.models.inventory.Quest
+import com.habitrpg.android.habitica.models.inventory.QuestContent
+import com.habitrpg.android.habitica.models.social.Group
import com.habitrpg.android.habitica.ui.activities.AboutActivity
import com.habitrpg.android.habitica.ui.activities.GemPurchaseActivity
import com.habitrpg.android.habitica.ui.activities.MainActivity
@@ -37,8 +43,9 @@ import com.habitrpg.android.habitica.ui.fragments.tasks.TasksFragment
import com.habitrpg.android.habitica.ui.helpers.NavbarUtils
import com.habitrpg.android.habitica.ui.menu.HabiticaDrawerItem
import kotlinx.android.synthetic.main.drawer_main.*
-import rx.Subscription
import rx.functions.Action1
+import rx.subscriptions.CompositeSubscription
+import javax.inject.Inject
/**
* Fragment used for managing interactions for and presentation of a navigation drawer.
@@ -47,13 +54,22 @@ import rx.functions.Action1
*/
class NavigationDrawerFragment : DialogFragment() {
+ @Inject
+ lateinit var socialRepository: SocialRepository
+ @Inject
+ lateinit var inventoryRepository: InventoryRepository
+ @Inject
+ lateinit var userRepository: UserRepository
+
private var drawerLayout: DrawerLayout? = null
private var fragmentContainerView: View? = null
private var mCurrentSelectedPosition = 0
private var mFromSavedInstanceState: Boolean = false
- private var adapter: NavigationDrawerAdapter = NavigationDrawerAdapter()
+ private lateinit var adapter: NavigationDrawerAdapter
+
+ private var subscriptions: CompositeSubscription? = null
val isDrawerOpen: Boolean
get() = drawerLayout?.isDrawerOpen(fragmentContainerView!!) ?: false
@@ -61,7 +77,48 @@ class NavigationDrawerFragment : DialogFragment() {
private val actionBar: ActionBar?
get() = activity?.actionBar
+ private var questContent: QuestContent? = null
+ set(value) {
+ field = value
+ updateQuestDisplay()
+ }
+ private var quest: Quest? = null
+ set(value) {
+ field = value
+ updateQuestDisplay()
+ }
+
+ private fun updateQuestDisplay() {
+ val quest = this.quest
+ val questContent = this.questContent
+ if (quest == null || questContent == null || !quest.active) {
+ questMenuView.visibility = View.GONE
+ context.notNull {
+ adapter.tintColor = ContextCompat.getColor(it, R.color.brand_300)
+ adapter.backgroundTintColor = ContextCompat.getColor(it, R.color.brand_200)
+ }
+ return
+ }
+ questMenuView.visibility = View.VISIBLE
+
+ menuHeaderView.setBackgroundColor(questContent.colors?.darkColor ?: 0)
+ questMenuView.configure(quest)
+ questMenuView.configure(questContent)
+ adapter.tintColor = questContent.colors?.lightColor ?: 0
+ adapter.backgroundTintColor = questContent.colors?.darkColor ?: 0
+
+ questMenuView.hideBossArt()
+ }
+
override fun onCreate(savedInstanceState: Bundle?) {
+ val context = context
+ adapter = if (context != null) {
+ NavigationDrawerAdapter(ContextCompat.getColor(context, R.color.brand_300), ContextCompat.getColor(context, R.color.brand_200))
+ } else {
+ NavigationDrawerAdapter(0, 0)
+ }
+ subscriptions = CompositeSubscription()
+ HabiticaBaseApplication.getComponent().inject(this)
super.onCreate(savedInstanceState)
if (savedInstanceState != null) {
@@ -75,14 +132,11 @@ class NavigationDrawerFragment : DialogFragment() {
// Indicate that this fragment would like to influence the set of actions in the action bar.
setHasOptionsMenu(true)
- context?.let {recyclerView.setPadding(0, 0, 0, NavbarUtils.getNavbarHeight(it)) }
+ context?.notNull {recyclerView.setPadding(0, 0, 0, NavbarUtils.getNavbarHeight(it)) }
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?): View? =
- inflater.inflate(R.layout.drawer_main, container, false) as ViewGroup
-
- private var selectionSubscription: Subscription? = null
+ savedInstanceState: Bundle?): View? = inflater.inflate(R.layout.drawer_main, container, false) as ViewGroup
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
@@ -90,14 +144,35 @@ class NavigationDrawerFragment : DialogFragment() {
recyclerView.layoutManager = LinearLayoutManager(context)
initializeMenuItems()
- selectionSubscription = adapter.getItemSelectionEvents().subscribe(Action1 {
+ subscriptions?.add(adapter.getItemSelectionEvents().subscribe(Action1 {
setSelection(it, true)
- }, RxErrorHandler.handleEmptyError())
+ }, RxErrorHandler.handleEmptyError()))
+
+ subscriptions?.add(socialRepository.getGroup(Group.TAVERN_ID)
+ .doOnNext({ quest = it.quest })
+ .filter { it.hasActiveQuest }
+ .flatMap { inventoryRepository.getQuestContent(it.quest?.key).first() }
+ .subscribe(Action1 {
+ questContent = it
+ }, RxErrorHandler.handleEmptyError()))
+
+ subscriptions?.add(userRepository.getUser().subscribe(Action1 {
+ setUsername(it.profile.name)
+ avatarView.setAvatar(it)
+ }, RxErrorHandler.handleEmptyError()))
messagesButton.setOnClickListener { setSelection(SIDEBAR_INBOX) }
settingsButton.setOnClickListener { setSelection(SIDEBAR_SETTINGS) }
}
+ override fun onDestroy() {
+ subscriptions?.clear()
+ socialRepository.close()
+ inventoryRepository.close()
+ userRepository.close()
+ super.onDestroy()
+ }
+
private fun initializeMenuItems() {
val items = ArrayList()
context.notNull {context ->
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/TavernDetailFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/TavernDetailFragment.kt
index 2e26b4bb3..d6bc9b3e7 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/TavernDetailFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/TavernDetailFragment.kt
@@ -109,7 +109,7 @@ class TavernDetailFragment : BaseFragment() {
.doOnNext({ if (!it.hasActiveQuest) worldBossSection.visibility = View.GONE })
.filter { it.hasActiveQuest }
.doOnNext({ questProgressView.progress = it.quest})
- .flatMap { inventoryRepository.getQuestContent(it.quest?.key) }
+ .flatMap { inventoryRepository.getQuestContent(it.quest?.key).first() }
.subscribe(Action1 {
questProgressView.quest = it
worldBossSection.visibility = View.VISIBLE
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/NavbarUtils.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/NavbarUtils.java
deleted file mode 100644
index 327fd440a..000000000
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/NavbarUtils.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package com.habitrpg.android.habitica.ui.helpers;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Point;
-import android.os.Build;
-import android.support.annotation.IntRange;
-import android.support.annotation.NonNull;
-import android.util.DisplayMetrics;
-import android.view.Display;
-import android.view.KeyCharacterMap;
-import android.view.KeyEvent;
-import android.view.ViewConfiguration;
-import android.view.WindowManager;
-
-import com.habitrpg.android.habitica.R;
-
-public class NavbarUtils {
-
- private static final int RESOURCE_NOT_FOUND = 0;
-
- @IntRange(from = 0)
- public static int getNavbarHeight(@NonNull Context context) {
- Resources res = context.getResources();
- int navBarIdentifier = res.getIdentifier("navigation_bar_height", "dimen", "android");
- return navBarIdentifier != RESOURCE_NOT_FOUND
- ? res.getDimensionPixelSize(navBarIdentifier) : 0;
- }
-
- static boolean shouldDrawBehindNavbar(@NonNull Context context) {
- return isPortrait(context)
- && hasSoftKeys(context);
- }
-
- private static boolean isPortrait(@NonNull Context context) {
- Resources res = context.getResources();
- return res.getBoolean(R.bool.bb_bottom_bar_is_portrait_mode);
- }
-
- /**
- * http://stackoverflow.com/a/14871974
- */
- public static boolean hasSoftKeys(@NonNull Context context) {
- boolean hasSoftwareKeys = true;
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
- Display d = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
-
- DisplayMetrics realDisplayMetrics = new DisplayMetrics();
- d.getRealMetrics(realDisplayMetrics);
-
- int realHeight = realDisplayMetrics.heightPixels;
- int realWidth = realDisplayMetrics.widthPixels;
-
- DisplayMetrics displayMetrics = new DisplayMetrics();
- d.getMetrics(displayMetrics);
-
- int displayHeight = displayMetrics.heightPixels;
- int displayWidth = displayMetrics.widthPixels;
-
- hasSoftwareKeys = (realWidth - displayWidth) > 0 || (realHeight - displayHeight) > 0;
- } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
- boolean hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey();
- boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
- hasSoftwareKeys = !hasMenuKey && !hasBackKey;
- }
-
- return hasSoftwareKeys;
- }
-
- public static boolean isBehindNavbar(int[] parentLocation, Context context) {
- WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- Display display = wm.getDefaultDisplay();
- Point size = new Point();
- display.getSize(size);
- return parentLocation[1] > (size.y - getNavbarHeight(context));
- }
-}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/NavbarUtils.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/NavbarUtils.kt
new file mode 100644
index 000000000..2adeaba9a
--- /dev/null
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/NavbarUtils.kt
@@ -0,0 +1,78 @@
+package com.habitrpg.android.habitica.ui.helpers
+
+import android.content.Context
+import android.content.res.Resources
+import android.graphics.Point
+import android.os.Build
+import android.support.annotation.IntRange
+import android.util.DisplayMetrics
+import android.view.Display
+import android.view.KeyCharacterMap
+import android.view.KeyEvent
+import android.view.ViewConfiguration
+import android.view.WindowManager
+
+import com.habitrpg.android.habitica.R
+
+object NavbarUtils {
+
+ private const val RESOURCE_NOT_FOUND = 0
+
+ @IntRange(from = 0)
+ fun getNavbarHeight(context: Context): Int {
+ val res = context.resources
+ val navBarIdentifier = res.getIdentifier("navigation_bar_height", "dimen", "android")
+ return if (navBarIdentifier != RESOURCE_NOT_FOUND)
+ res.getDimensionPixelSize(navBarIdentifier)
+ else
+ 0
+ }
+
+ internal fun shouldDrawBehindNavbar(context: Context): Boolean {
+ return isPortrait(context) && hasSoftKeys(context)
+ }
+
+ private fun isPortrait(context: Context): Boolean {
+ val res = context.resources
+ return res.getBoolean(R.bool.bb_bottom_bar_is_portrait_mode)
+ }
+
+ /**
+ * http://stackoverflow.com/a/14871974
+ */
+ fun hasSoftKeys(context: Context): Boolean {
+ var hasSoftwareKeys = true
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ val d = (context.getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay
+
+ val realDisplayMetrics = DisplayMetrics()
+ d.getRealMetrics(realDisplayMetrics)
+
+ val realHeight = realDisplayMetrics.heightPixels
+ val realWidth = realDisplayMetrics.widthPixels
+
+ val displayMetrics = DisplayMetrics()
+ d.getMetrics(displayMetrics)
+
+ val displayHeight = displayMetrics.heightPixels
+ val displayWidth = displayMetrics.widthPixels
+
+ hasSoftwareKeys = realWidth - displayWidth > 0 || realHeight - displayHeight > 0
+ } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
+ val hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey()
+ val hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK)
+ hasSoftwareKeys = !hasMenuKey && !hasBackKey
+ }
+
+ return hasSoftwareKeys
+ }
+
+ fun isBehindNavbar(parentLocation: IntArray, context: Context): Boolean {
+ val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
+ val display = wm.defaultDisplay
+ val size = Point()
+ display.getSize(size)
+ return parentLocation[1] > size.y - getNavbarHeight(context)
+ }
+}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/HabiticaSnackbar.java b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/HabiticaSnackbar.java
index f92bd0af8..bc2f0a429 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/HabiticaSnackbar.java
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/HabiticaSnackbar.java
@@ -33,11 +33,11 @@ public class HabiticaSnackbar extends BaseTransientBottomBar {
private static HabiticaSnackbar make(@NonNull ViewGroup parent, int duration) {
final LayoutInflater inflater = LayoutInflater.from(parent.getContext());
final View content = inflater.inflate(R.layout.snackbar_view, parent, false);
- if (NavbarUtils.hasSoftKeys(parent.getContext())) {
+ if (NavbarUtils.INSTANCE.hasSoftKeys(parent.getContext())) {
int[] parentLocation = new int[2];
parent.getLocationInWindow(parentLocation);
- if (NavbarUtils.isBehindNavbar(parentLocation, parent.getContext())) {
- content.setPadding(0, 0, 0, NavbarUtils.getNavbarHeight(parent.getContext()));
+ if (NavbarUtils.INSTANCE.isBehindNavbar(parentLocation, parent.getContext())) {
+ content.setPadding(0, 0, 0, NavbarUtils.INSTANCE.getNavbarHeight(parent.getContext()));
}
}
final ContentViewCallback viewCallback = new ContentViewCallback(content);
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/RoundedCornerLayout.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/RoundedCornerLayout.kt
new file mode 100644
index 000000000..e91971e9e
--- /dev/null
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/RoundedCornerLayout.kt
@@ -0,0 +1,80 @@
+package com.habitrpg.android.habitica.ui.views
+
+import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Paint
+import android.graphics.PorterDuff
+import android.graphics.PorterDuffXfermode
+import android.graphics.RectF
+import android.util.AttributeSet
+import android.util.DisplayMetrics
+import android.util.TypedValue
+import android.widget.FrameLayout
+
+// https://stackoverflow.com/a/26201117
+class RoundedCornerLayout : FrameLayout {
+
+ private var maskBitmap: Bitmap? = null
+ private var paint: Paint? = null
+ private var maskPaint: Paint? = null
+ private var cornerRadius: Float = CORNER_RADIUS
+
+ constructor(context: Context) : super(context) {
+ init(context, null, 0)
+ }
+
+ constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
+ init(context, attrs, 0)
+ }
+
+ constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {
+ init(context, attrs, defStyle)
+ }
+
+ private fun init(context: Context, attrs: AttributeSet?, defStyle: Int) {
+ val metrics = context.resources.displayMetrics
+ cornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, CORNER_RADIUS, metrics)
+
+ paint = Paint(Paint.ANTI_ALIAS_FLAG)
+
+ maskPaint = Paint(Paint.ANTI_ALIAS_FLAG or Paint.FILTER_BITMAP_FLAG)
+ maskPaint?.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)
+
+ setWillNotDraw(false)
+ }
+
+ override fun draw(canvas: Canvas) {
+ val offscreenBitmap = Bitmap.createBitmap(canvas.width, canvas.height, Bitmap.Config.ARGB_8888)
+ val offscreenCanvas = Canvas(offscreenBitmap)
+
+ super.draw(offscreenCanvas)
+
+ if (maskBitmap == null) {
+ maskBitmap = createMask(canvas.width, canvas.height)
+ }
+
+ offscreenCanvas.drawBitmap(maskBitmap, 0f, 0f, maskPaint)
+ canvas.drawBitmap(offscreenBitmap, 0f, 0f, paint)
+ }
+
+ private fun createMask(width: Int, height: Int): Bitmap {
+ val mask = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8)
+ val canvas = Canvas(mask)
+
+ val paint = Paint(Paint.ANTI_ALIAS_FLAG)
+ paint.color = Color.WHITE
+
+ canvas.drawRect(0f, 0f, width.toFloat(), height.toFloat(), paint)
+
+ paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)
+ canvas.drawRoundRect(RectF(0f, 0f, width.toFloat(), height.toFloat()), cornerRadius, cornerRadius, paint)
+
+ return mask
+ }
+
+ companion object {
+ private const val CORNER_RADIUS = 40.0f
+ }
+}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/ValueBar.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/ValueBar.kt
index 7e0aba1c2..80c330614 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/ValueBar.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/ValueBar.kt
@@ -24,6 +24,24 @@ class ValueBar(context: Context, attrs: AttributeSet) : FrameLayout(context, att
private val barView: View by bindView(R.id.bar)
private val barEmptySpace: View by bindView(R.id.empty_bar_space)
+ var currentValue: Double = 0.0
+ set(value) {
+ field = value
+ updateBar()
+ }
+
+ var maxValue: Double = 0.0
+ set(value) {
+ field = value
+ updateBar()
+ }
+
+ private fun updateBar() {
+ val percent = Math.min(1.0, currentValue / maxValue)
+
+ this.setBarWeight(percent)
+ this.setValueText(currentValue.toInt().toString() + "/" + maxValue.toInt())
+ }
init {
View.inflate(context, R.layout.value_bar, this)
@@ -88,10 +106,8 @@ class ValueBar(context: Context, attrs: AttributeSet) : FrameLayout(context, att
}
fun set(value: Double, valueMax: Double) {
- val percent = Math.min(1.0, value / valueMax)
-
- this.setBarWeight(percent)
- this.setValueText(value.toInt().toString() + "/" + valueMax.toInt())
+ currentValue = value
+ maxValue = valueMax
}
companion object {
@@ -109,4 +125,9 @@ class ValueBar(context: Context, attrs: AttributeSet) : FrameLayout(context, att
}
}
}
+
+ fun setLabelVisibility(visibility: Int) {
+ valueTextView.visibility = visibility
+ descriptionTextView.visibility = visibility
+ }
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/social/QuestMenuView.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/social/QuestMenuView.kt
new file mode 100644
index 000000000..81373e689
--- /dev/null
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/social/QuestMenuView.kt
@@ -0,0 +1,79 @@
+package com.habitrpg.android.habitica.ui.views.social
+
+import android.content.Context
+import android.support.v4.content.ContextCompat
+import android.util.AttributeSet
+import android.view.Gravity
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.LinearLayout
+import android.widget.TextView
+import com.habitrpg.android.habitica.R
+import com.habitrpg.android.habitica.extensions.bindView
+import com.habitrpg.android.habitica.models.inventory.Quest
+import com.habitrpg.android.habitica.models.inventory.QuestContent
+import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
+import com.habitrpg.android.habitica.ui.views.ValueBar
+
+class QuestMenuView : LinearLayout {
+
+ private val bossNameView: TextView by bindView(R.id.bossNameView)
+ private val typeTextView: TextView by bindView(R.id.typeTextView)
+ private val healthBarView: ValueBar by bindView(R.id.healthBarView)
+ private val topView: LinearLayout by bindView(R.id.topView)
+
+ private var questContent: QuestContent? = null
+
+ var collapsed = false
+ set(value) {
+ field = value
+ if (field) {
+ showBossArt()
+ } else {
+ hideBossArt()
+ }
+ }
+
+ constructor(context: Context) : super(context) {
+ setupView(context)
+ }
+
+ constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
+ setupView(context)
+ }
+
+ private fun setupView(context: Context) {
+ val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
+ inflater.inflate(R.layout.quest_menu_view, this)
+
+ healthBarView.setIcon(HabiticaIconsHelper.imageOfHeartDarkBg())
+ healthBarView.setLabelVisibility(View.GONE)
+ }
+
+ fun configure(quest: Quest) {
+ healthBarView.currentValue = quest.progress?.hp ?: 0.0
+ }
+
+ fun configure(questContent: QuestContent) {
+ this.questContent = questContent
+ healthBarView.maxValue = questContent.boss.hp.toDouble()
+ healthBarView.setBackgroundColor(questContent.colors?.darkColor ?: 0)
+ topView.setBackgroundColor(questContent.colors?.mediumColor ?: 0)
+ bossNameView.text = questContent.boss.name
+ }
+
+ fun hideBossArt() {
+ topView.orientation = LinearLayout.HORIZONTAL
+ bossNameView.gravity = Gravity.LEFT
+ bossNameView.layoutParams = LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1F)
+ typeTextView.setTextColor(questContent?.colors?.extraLightColor ?: 0)
+ }
+
+ fun showBossArt() {
+ topView.orientation = LinearLayout.VERTICAL
+ bossNameView.gravity = Gravity.RIGHT
+ bossNameView.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
+ typeTextView.setTextColor(ContextCompat.getColor(context, R.color.white))
+ }
+}
\ No newline at end of file
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/utils/GroupSerialization.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/utils/GroupSerialization.kt
index c767c98e4..b7f81d700 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/utils/GroupSerialization.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/utils/GroupSerialization.kt
@@ -98,8 +98,8 @@ class GroupSerialization : JsonDeserializer, JsonSerializer {
group.quest?.participants = newMembers
}
- if (questObject.has("extra")) {
- val worldDamageObject = questObject.getAsJsonObject("extra")
+ if (questObject.has("extra") && questObject["extra"].asJsonObject.has("worldDmg")) {
+ val worldDamageObject = questObject.getAsJsonObject("extra").getAsJsonObject("worldDmg")
worldDamageObject.entrySet().forEach { (key, value) ->
val rageStrike = QuestRageStrike(key, value.asBoolean)
group.quest?.addRageStrike(rageStrike)
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/utils/WorldStateSerialization.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/utils/WorldStateSerialization.kt
new file mode 100644
index 000000000..54afacd08
--- /dev/null
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/utils/WorldStateSerialization.kt
@@ -0,0 +1,36 @@
+package com.habitrpg.android.habitica.utils
+
+import com.google.gson.JsonDeserializationContext
+import com.google.gson.JsonDeserializer
+import com.google.gson.JsonElement
+import com.habitrpg.android.habitica.models.WorldState
+import com.habitrpg.android.habitica.models.inventory.QuestProgress
+import com.habitrpg.android.habitica.models.inventory.QuestRageStrike
+import java.lang.reflect.Type
+
+class WorldStateSerialization: JsonDeserializer {
+
+ override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?): WorldState {
+ val worldBossObject = json?.asJsonObject?.get("worldBoss")?.asJsonObject
+ val state = WorldState()
+ if (worldBossObject == null) {
+ return state
+ }
+ state.worldBossActive = worldBossObject["active"].asBoolean
+ state.worldBossKey = worldBossObject["key"].asString
+ state.progress = context?.deserialize(worldBossObject["progress"], QuestProgress::class.java)
+ if (worldBossObject.has("extra")) {
+ val extra = worldBossObject["extra"].asJsonObject
+ if (extra.has("worldDmg")) {
+ val worldDmg = extra["worldDmg"].asJsonObject
+ state.rageStrikes = mutableListOf()
+ worldDmg.entrySet().forEach { (key, value) ->
+ val strike = QuestRageStrike(key, value.asBoolean)
+ state.rageStrikes?.add(strike)
+ }
+ }
+ }
+ return state
+ }
+
+}
\ No newline at end of file
diff --git a/habitica.properties.example b/habitica.properties.example
index 00f3fb4b7..3af43be42 100644
--- a/habitica.properties.example
+++ b/habitica.properties.example
@@ -12,3 +12,5 @@ PORT=80
# Production
BASE_URL=https://habitica.com
+
+STAGING_KEY=
diff --git a/habitica.properties.travis b/habitica.properties.travis
index 04673d89f..86925b693 100644
--- a/habitica.properties.travis
+++ b/habitica.properties.travis
@@ -1,2 +1,3 @@
PORT=3000
BASE_URL=http://localhost:3000
+STAGING_KEY=