mirror of
https://github.com/sudoxnym/habitica-android.git
synced 2026-05-19 04:09:03 +00:00
Show world boss in menu
This commit is contained in:
parent
27d290d963
commit
52fe568d29
29 changed files with 647 additions and 193 deletions
|
|
@ -12,6 +12,7 @@
|
|||
tools:context="com.habitrpg.android.habitica.ui.fragments.NavigationDrawerFragment">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/menuHeaderView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="80dp"
|
||||
android:background="@color/brand_200"
|
||||
|
|
@ -21,6 +22,17 @@
|
|||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.habitrpg.android.habitica.ui.views.RoundedCornerLayout
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginRight="@dimen/spacing_large">
|
||||
<com.habitrpg.android.habitica.ui.AvatarView
|
||||
android:id="@+id/avatarView"
|
||||
android:layout_width="70dp"
|
||||
android:layout_height="70dp"
|
||||
android:layout_gravity="center"/>
|
||||
</com.habitrpg.android.habitica.ui.views.RoundedCornerLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/toolbarTitle"
|
||||
android:layout_width="0dp"
|
||||
|
|
@ -47,8 +59,12 @@
|
|||
android:background="@color/transparent"
|
||||
android:src="@drawable/menu_settings"
|
||||
android:layout_marginLeft="20dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
<com.habitrpg.android.habitica.ui.views.social.QuestMenuView
|
||||
android:id="@+id/questMenuView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"/>
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
|||
44
Habitica/res/layout/quest_menu_view.xml
Normal file
44
Habitica/res/layout/quest_menu_view.xml
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<LinearLayout
|
||||
android:id="@+id/topView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="@dimen/spacing_large"
|
||||
android:paddingRight="@dimen/spacing_large"
|
||||
android:paddingTop="@dimen/spacing_medium"
|
||||
android:paddingBottom="@dimen/spacing_medium">
|
||||
<TextView
|
||||
android:id="@+id/bossNameView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="right"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
/>
|
||||
<TextView
|
||||
android:id="@+id/typeTextView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/world_boss"
|
||||
android:layout_gravity="right|center_vertical"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="12sp"/>
|
||||
</LinearLayout>
|
||||
<com.habitrpg.android.habitica.ui.views.ValueBar
|
||||
android:id="@+id/healthBarView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="@dimen/spacing_medium"
|
||||
android:paddingRight="@dimen/spacing_large"
|
||||
android:paddingTop="@dimen/spacing_medium"
|
||||
android:paddingBottom="@dimen/spacing_small"
|
||||
app:barForegroundColor="@color/red_100"
|
||||
app:barBackgroundColor="@color/white_15_alpha"/>
|
||||
</LinearLayout>
|
||||
|
|
@ -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<HabitResponse<Stats>> bulkAllocatePoints(@Body Map<String, Map<String, Integer>> stats);
|
||||
|
||||
@POST("world-state")
|
||||
Observable<HabitResponse<WorldState>> getWorldState();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Stats> bulkAllocatePoints(int strength, int intelligence, int constitution, int perception);
|
||||
|
||||
Observable<Shop> retrieveMarketGear();
|
||||
|
||||
Observable<WorldState> getWorldState();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<ContentResult> retrieveContent();
|
||||
Observable<ContentResult> retrieveContent(boolean forced);
|
||||
|
||||
Observable<WorldState> retrieveWorldState();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Throwable>, 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<Throwable>, ApiClient {
|
|||
public Observable<Shop> retrieveMarketGear() {
|
||||
return apiService.retrieveMarketGear().compose(configureApiCallObserver());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Observable<WorldState> getWorldState() {
|
||||
return apiService.getWorldState().compose(configureApiCallObserver());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<T extends ContentLocalRepository> extends BaseRepositoryImpl<T> implements ContentRepository {
|
||||
|
||||
private Date lastSync = null;
|
||||
|
||||
public ContentRepositoryImpl(T localRepository, ApiClient apiClient) {
|
||||
super(localRepository, apiClient);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Observable<ContentResult> retrieveContent() {
|
||||
return retrieveContent(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Observable<ContentResult> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<T : ContentLocalRepository>(localRepository: T, apiClient: ApiClient) : BaseRepositoryImpl<T>(localRepository, apiClient), ContentRepository {
|
||||
|
||||
private var lastContentSync = Date()
|
||||
private var lastWorldStateSync = Date()
|
||||
|
||||
override fun retrieveContent(): Observable<ContentResult> {
|
||||
return retrieveContent(false)
|
||||
}
|
||||
|
||||
override fun retrieveContent(forced: Boolean): Observable<ContentResult> {
|
||||
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<WorldState> {
|
||||
return if (Date().time - this.lastWorldStateSync.time > 3600000) {
|
||||
lastWorldStateSync = Date()
|
||||
apiClient.worldState.doOnNext({ localRepository.saveWorldState(it) })
|
||||
} else {
|
||||
Observable.just(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);
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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<QuestRageStrike>? = null
|
||||
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<RecyclerView.ViewHolder>() {
|
||||
|
||||
var tintColor: Int = tintColor
|
||||
set(value) {
|
||||
field = value
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
var backgroundTintColor: Int = backgroundTintColor
|
||||
set(value) {
|
||||
field = value
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
class NavigationDrawerAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||
|
||||
internal val items: MutableList<HabiticaDrawerItem> = ArrayList()
|
||||
var selectedItem: String? = null
|
||||
|
|
@ -48,9 +67,12 @@ class NavigationDrawerAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
|||
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<RecyclerView.ViewHolder>() {
|
|||
|
||||
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<RecyclerView.ViewHolder>() {
|
|||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<HabiticaDrawerItem>()
|
||||
context.notNull {context ->
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -33,11 +33,11 @@ public class HabiticaSnackbar extends BaseTransientBottomBar<HabiticaSnackbar> {
|
|||
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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
@ -98,8 +98,8 @@ class GroupSerialization : JsonDeserializer<Group>, JsonSerializer<Group> {
|
|||
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)
|
||||
|
|
|
|||
|
|
@ -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<WorldState> {
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -12,3 +12,5 @@ PORT=80
|
|||
|
||||
# Production
|
||||
BASE_URL=https://habitica.com
|
||||
|
||||
STAGING_KEY=
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
PORT=3000
|
||||
BASE_URL=http://localhost:3000
|
||||
STAGING_KEY=
|
||||
|
|
|
|||
Loading…
Reference in a new issue