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=