diff --git a/Habitica/res/drawable/rounded_avatar_bg.xml b/Habitica/res/drawable/rounded_avatar_bg.xml
new file mode 100644
index 000000000..50d0f26f0
--- /dev/null
+++ b/Habitica/res/drawable/rounded_avatar_bg.xml
@@ -0,0 +1,4 @@
+
+
+
diff --git a/Habitica/res/layout/tavern_chat_item.xml b/Habitica/res/layout/tavern_chat_item.xml
index 760bb2f45..ad5fc56d1 100644
--- a/Habitica/res/layout/tavern_chat_item.xml
+++ b/Habitica/res/layout/tavern_chat_item.xml
@@ -3,89 +3,84 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
- android:orientation="vertical">
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:orientation="horizontal"
+ android:background="@color/gray_600"
+ android:paddingLeft="@dimen/chat_horizontal_inset"
+ android:paddingRight="@dimen/chat_horizontal_inset"
+ android:paddingTop="@dimen/spacing_small"
+ android:paddingBottom="@dimen/spacing_small">
+
+
+
+ style="@style/CardContent.Compact"
+ android:background="@drawable/layout_rounded_bg"
+ android:padding="@dimen/spacing_medium">
+
-
-
+
+
-
-
-
-
-
-
-
+ android:layout_height="1dp"
+ android:layout_weight="1" />
+ android:layout_gravity="center_vertical|right"
-
+
+
-
-
-
-
-
-
-
-
-
+ android:layout_margin="5dp"
+ android:clickable="true"
+ android:gravity="center_vertical"
+ android:focusable="true" />
@@ -96,15 +91,42 @@
android:layout_margin="8dp"
android:lineSpacingMultiplier="1.0"
tools:text="This is the chat message"/>
-
-
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Habitica/res/values/dimens.xml b/Habitica/res/values/dimens.xml
index c04c333f4..d7f8ad542 100644
--- a/Habitica/res/values/dimens.xml
+++ b/Habitica/res/values/dimens.xml
@@ -125,5 +125,7 @@
46dp
6dp
18dp
+ 16dp
+ 36dp
diff --git a/Habitica/res/values/strings.xml b/Habitica/res/values/strings.xml
index a9fb8cb5b..88b9ed287 100644
--- a/Habitica/res/values/strings.xml
+++ b/Habitica/res/values/strings.xml
@@ -301,12 +301,12 @@
Quest Invitation
Are you sure? Only %1$d of your %2$d party members have joined this quest! Quests start automatically when all players have joined or rejected the invitation.
You have been invited to participate in a quest!
- 1 day ago
- %d days ago
- 1 minute ago
- %d minutes ago
- %d hours ago
- 1 hour ago
+ 1d ago
+ %dd ago
+ 1m ago
+ %dm ago
+ %dh ago
+ 1h ago
Today
Items
Eggs
@@ -779,4 +779,7 @@
Seasonal Sorceress
Rage attack:
Oh dear, pay no heed to the monster below -- this is still a safe haven to chat on your breaks.
+ Report
+ Like
+ Reply
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/InventoryRepositoryImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/InventoryRepositoryImpl.kt
index 61f64bee1..5826f1813 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/InventoryRepositoryImpl.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/InventoryRepositoryImpl.kt
@@ -125,7 +125,7 @@ class InventoryRepositoryImpl(localRepository: InventoryLocalRepository, apiClie
item.owned = item.owned - 1
}
if (user.stats != null) {
- user1.stats.userId = user.id
+ user1.stats?.userId = user.id
val stats = realm.copyToRealmOrUpdate(user1.stats)
user.stats = stats
}
@@ -190,21 +190,21 @@ class InventoryRepositoryImpl(localRepository: InventoryLocalRepository, apiClie
copiedUser.items = buyResponse.items
}
if (buyResponse.hp != null) {
- copiedUser.stats.hp = buyResponse.hp
+ copiedUser.stats?.hp = buyResponse.hp
}
if (buyResponse.exp != null) {
- copiedUser.stats.exp = buyResponse.exp
+ copiedUser.stats?.exp = buyResponse.exp
}
if (buyResponse.mp != null) {
- copiedUser.stats.mp = buyResponse.mp
+ copiedUser.stats?.mp = buyResponse.mp
}
if (buyResponse.gp != null) {
- copiedUser.stats.gp = buyResponse.gp
+ copiedUser.stats?.gp = buyResponse.gp
} else {
- copiedUser.stats.gp = copiedUser.stats.gp ?: 0 - value
+ copiedUser.stats?.gp = copiedUser.stats?.gp ?: 0 - value
}
if (buyResponse.lvl != null) {
- copiedUser.stats.lvl = buyResponse.lvl
+ copiedUser.stats?.lvl = buyResponse.lvl
}
localRepository.save(copiedUser)
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/SetupCustomizationRepositoryImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/SetupCustomizationRepositoryImpl.kt
index 6eb6fc9d2..04a81ba02 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/SetupCustomizationRepositoryImpl.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/SetupCustomizationRepositoryImpl.kt
@@ -86,15 +86,15 @@ constructor(private val context: Context) : SetupCustomizationRepository {
"body" -> {
return when (subcategory) {
"size" -> sizes
- "shirt" -> getShirts(user.preferences.size ?: "slim")
+ "shirt" -> getShirts(user.preferences?.size ?: "slim")
else -> emptyList()
}
}
"skin" -> return skins
"hair" -> {
return when (subcategory) {
- "bangs" -> getBangs(user.preferences.hair!!.color)
- "ponytail" -> getHairBases(user.preferences.hair!!.color)
+ "bangs" -> getBangs(user.preferences?.hair!!.color)
+ "ponytail" -> getHairBases(user.preferences?.hair!!.color)
"color" -> hairColors
else -> emptyList()
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/TaskRepositoryImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/TaskRepositoryImpl.kt
index ed6c97eb0..19dfe2c53 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/TaskRepositoryImpl.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/TaskRepositoryImpl.kt
@@ -71,11 +71,11 @@ class TaskRepositoryImpl(localRepository: TaskLocalRepository, apiClient: ApiCli
val stats = user.stats
result.taskValueDelta = res.delta
- result.healthDelta = res.hp - (stats.hp ?: 0.0)
- result.experienceDelta = res.exp - (stats.exp ?: 0.0)
- result.manaDelta = res.mp - (stats.mp ?: 0.0)
- result.goldDelta = res.gp - (stats.gp ?: 0.0)
- result.hasLeveledUp = res.lvl > stats.lvl ?: 0
+ result.healthDelta = res.hp - (stats?.hp ?: 0.0)
+ result.experienceDelta = res.exp - (stats?.exp ?: 0.0)
+ result.manaDelta = res.mp - (stats?.mp ?: 0.0)
+ result.goldDelta = res.gp - (stats?.gp ?: 0.0)
+ result.hasLeveledUp = res.lvl > stats?.lvl ?: 0
result.questDamage = res._tmp.quest?.progressDelta
if (res._tmp != null) {
result.drop = res._tmp.drop
@@ -90,11 +90,11 @@ class TaskRepositoryImpl(localRepository: TaskLocalRepository, apiClient: ApiCli
task.completed = up
}
}
- stats.hp = res.hp
- stats.exp = res.exp
- stats.mp = res.mp
- stats.gp = res.gp
- stats.lvl = res.lvl
+ stats?.hp = res.hp
+ stats?.exp = res.exp
+ stats?.mp = res.mp
+ stats?.gp = res.gp
+ stats?.lvl = res.lvl
user.party?.quest?.progress?.up = (user.party?.quest?.progress?.up ?: 0F) + (res._tmp.quest?.progressDelta?.toFloat() ?: 0F)
user.stats = stats
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/UserRepositoryImpl.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/UserRepositoryImpl.kt
index 11ab56467..181e50971 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/UserRepositoryImpl.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/implementation/UserRepositoryImpl.kt
@@ -100,7 +100,7 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli
}
override fun sleep(user: User): Flowable {
- localRepository.executeTransaction { user.preferences.isSleep = !user.preferences.sleep }
+ localRepository.executeTransaction { user.preferences?.isSleep = !(user.preferences?.sleep ?: false) }
return apiClient.sleep().map { user }
}
@@ -121,9 +121,9 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli
override fun useSkill(user: User?, key: String, target: String): Flowable {
return apiClient.useSkill(key, target)
.map { response ->
- response.hpDiff = response.user.stats.hp ?: 0 - (user?.stats?.hp ?: 0.0)
- response.expDiff = response.user.stats.exp ?: 0 - (user?.stats?.exp ?: 0.0)
- response.goldDiff = response.user.stats.gp ?: 0 - (user?.stats?.gp ?: 0.0)
+ response.hpDiff = response.user.stats?.hp ?: 0 - (user?.stats?.hp ?: 0.0)
+ response.expDiff = response.user.stats?.exp ?: 0 - (user?.stats?.exp ?: 0.0)
+ response.goldDiff = response.user.stats?.gp ?: 0 - (user?.stats?.gp ?: 0.0)
response
}
.doOnNext { skillResponse ->
@@ -211,24 +211,24 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli
if (user != null && user.isManaged) {
localRepository.executeTransaction {
when (stat) {
- Stats.STRENGTH -> user.stats.str = user.stats.str?.inc()
- Stats.INTELLIGENCE -> user.stats._int = user.stats._int?.inc()
- Stats.CONSTITUTION -> user.stats.con= user.stats.con?.inc()
- Stats.PERCEPTION -> user.stats.per = user.stats.per?.inc()
+ Stats.STRENGTH -> user.stats?.str = user.stats?.str?.inc()
+ Stats.INTELLIGENCE -> user.stats?._int = user.stats?._int?.inc()
+ Stats.CONSTITUTION -> user.stats?.con= user.stats?.con?.inc()
+ Stats.PERCEPTION -> user.stats?.per = user.stats?.per?.inc()
}
- user.stats.points = user.stats.points?.dec()
+ user.stats?.points = user.stats?.points?.dec()
}
}
return apiClient.allocatePoint(stat)
.doOnNext { stats ->
if (user != null && user.isManaged) {
localRepository.executeTransaction {
- user.stats.str = stats.str
- user.stats.con = stats.con
- user.stats.per = stats.per
- user.stats._int = stats._int
- user.stats.points = stats.points
- user.stats.mp = stats.mp
+ user.stats?.str = stats.str
+ user.stats?.con = stats.con
+ user.stats?.per = stats.per
+ user.stats?._int = stats._int
+ user.stats?.points = stats.points
+ user.stats?.mp = stats.mp
}
}
}
@@ -239,12 +239,12 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli
.doOnNext { stats ->
if (user != null && user.isManaged) {
localRepository.executeTransaction {
- user.stats.str = stats.str
- user.stats.con = stats.con
- user.stats.per = stats.per
- user.stats._int = stats._int
- user.stats.points = stats.points
- user.stats.mp = stats.mp
+ user.stats?.str = stats.str
+ user.stats?.con = stats.con
+ user.stats?.per = stats.per
+ user.stats?._int = stats._int
+ user.stats?.points = stats.points
+ user.stats?.mp = stats.mp
}
}
}
@@ -288,7 +288,7 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli
copiedUser.flags = newUser.flags
}
if (newUser.stats != null) {
- copiedUser.stats.merge(newUser.stats)
+ copiedUser.stats?.merge(newUser.stats)
}
localRepository.saveUser(copiedUser)
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmUserLocalRepository.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmUserLocalRepository.kt
index 0f0f8ba87..89d5c4acf 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmUserLocalRepository.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/data/local/implementation/RealmUserLocalRepository.kt
@@ -73,17 +73,17 @@ class RealmUserLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
}
override fun getSkills(user: User): Flowable> {
- val habitClass = if (user.preferences.disableClasses) "none" else user.stats.habitClass
+ val habitClass = if (user.preferences?.disableClasses == true) "none" else user.stats?.habitClass
return realm.where(Skill::class.java)
.equalTo("habitClass", habitClass)
- .lessThanOrEqualTo("lvl", user.stats.lvl ?: 0)
+ .lessThanOrEqualTo("lvl", user.stats?.lvl ?: 0)
.findAll()
.asFlowable()
.filter { it.isLoaded }
}
override fun getSpecialItems(user: User): Flowable> {
- val specialItems = user.items.special
+ val specialItems = user.items?.special
val ownedItems = ArrayList()
if (specialItems != null) {
if (specialItems.snowball > 0) {
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/Avatar.java b/Habitica/src/main/java/com/habitrpg/android/habitica/models/Avatar.java
index 6ecaa7cda..6b32e5fe1 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/Avatar.java
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/Avatar.java
@@ -11,20 +11,24 @@ import com.habitrpg.android.habitica.models.user.Stats;
*/
public interface Avatar {
+ @Nullable
String getCurrentMount();
+ @Nullable
String getCurrentPet();
- String getBackground();
-
boolean getSleep();
+ @Nullable
Stats getStats();
+ @Nullable
AvatarPreferences getPreferences();
+ @Nullable
Integer getGemCount();
+ @Nullable
Integer getHourglassCount();
@Nullable
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/members/Member.java b/Habitica/src/main/java/com/habitrpg/android/habitica/models/members/Member.java
index 00abad0d7..aed774ef1 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/members/Member.java
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/members/Member.java
@@ -183,14 +183,6 @@ public class Member extends RealmObject implements Avatar {
this.currentPet = currentPet;
}
- @Override
- public String getBackground() {
- if (getPreferences() != null) {
- return getPreferences().getBackground();
- }
- return "";
- }
-
@Override
public boolean getSleep() {
return getPreferences() != null && getPreferences().getSleep();
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/social/ChatMessage.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/models/social/ChatMessage.kt
index 13adce0ff..89f41c70c 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/social/ChatMessage.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/social/ChatMessage.kt
@@ -19,6 +19,8 @@ open class ChatMessage : RealmObject() {
set(value) {
field = value
likes?.forEach { it.messageId = value }
+ userStyles?.id = id
+ contributor?.userId = id
}
var text: String? = null
@@ -46,34 +48,7 @@ open class ChatMessage : RealmObject() {
var isInboxMessage: Boolean = false
- val contributorColor: Int
- get() {
- var rColor = android.R.color.black
-
- val level = contributor?.level
- if (level != null) {
- if (ContributorInfo.CONTRIBUTOR_COLOR_DICT.get(level, -1) > 0) {
- rColor = ContributorInfo.CONTRIBUTOR_COLOR_DICT[level]
- }
- }
-
- if (backer?.npc != null) {
- rColor = android.R.color.black
- }
-
- return rColor
- }
-
- val contributorForegroundColor: Int
- get() {
- var rColor = android.R.color.white
-
- if (backer?.npc != null) {
- rColor = R.color.contributor_npc_font
- }
-
- return rColor
- }
+ var userStyles: UserStyles? = null
val isSystemMessage: Boolean
get() = uuid == "system"
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/social/UserStyles.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/models/social/UserStyles.kt
new file mode 100644
index 000000000..5e0ce6b99
--- /dev/null
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/social/UserStyles.kt
@@ -0,0 +1,61 @@
+package com.habitrpg.android.habitica.models.social
+
+import com.habitrpg.android.habitica.models.Avatar
+import com.habitrpg.android.habitica.models.AvatarPreferences
+import com.habitrpg.android.habitica.models.user.*
+import io.realm.RealmObject
+import io.realm.annotations.PrimaryKey
+
+open class UserStyles : RealmObject(), Avatar {
+ @PrimaryKey
+ var id: String? = null
+ set(value) {
+ field = value
+ stats?.userId = id
+ preferences?.userId = id
+ items?.userId = id
+ }
+ override fun getCurrentMount(): String? {
+ return items?.currentMount
+ }
+
+ override fun getCurrentPet(): String? {
+ return items?.currentPet
+ }
+
+ override fun getSleep(): Boolean {
+ return false
+ }
+
+ override fun getStats(): Stats? {
+ return stats
+ }
+
+ override fun getPreferences(): AvatarPreferences? {
+ return preferences
+ }
+
+ override fun getGemCount(): Int {
+ return 0
+ }
+
+ override fun getHourglassCount(): Int {
+ return 0
+ }
+
+ override fun getCostume(): Outfit? {
+ return items?.gear?.costume
+ }
+
+ override fun getEquipped(): Outfit? {
+ return items?.gear?.equipped
+ }
+
+ override fun hasClass(): Boolean {
+ return false
+ }
+
+ private var stats: Stats? = null
+ private var preferences: Preferences? = null
+ private var items: Items? = null
+}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/user/Preferences.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/models/user/Preferences.kt
index b5d0aefc8..0ab8b988f 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/user/Preferences.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/user/Preferences.kt
@@ -105,7 +105,7 @@ open class Preferences : RealmObject(), AvatarPreferences {
return userId
}
- fun setUserId(userId: String) {
+ fun setUserId(userId: String?) {
this.userId = userId
if (hair?.isManaged == false) {
hair?.userId = userId
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/models/user/User.java b/Habitica/src/main/java/com/habitrpg/android/habitica/models/user/User.java
index 1bf1c11bc..0ff165e73 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/models/user/User.java
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/models/user/User.java
@@ -289,14 +289,6 @@ public class User extends RealmObject implements Avatar {
return "";
}
- @Override
- public String getBackground() {
- if (getPreferences() != null) {
- return getPreferences().getBackground();
- }
- return "";
- }
-
@Override
public boolean getSleep() {
return getPreferences() != null && getPreferences().getSleep();
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/AvatarView.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/AvatarView.kt
index 615af8c8c..4906a3076 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/AvatarView.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/AvatarView.kt
@@ -173,7 +173,7 @@ class AvatarView : View {
if (resetHasAttributes) hasPet = true
}
- val backgroundName = avatar.background
+ val backgroundName = avatar.preferences?.background
if (showBackground && !TextUtils.isEmpty(backgroundName)) {
layerMap[LayerType.BACKGROUND] = "background_$backgroundName"
if (resetHasAttributes) hasBackground = true
@@ -202,8 +202,8 @@ class AvatarView : View {
var hasVisualBuffs = false
- if (avatar.stats != null && avatar.stats.buffs != null) {
- val buffs = avatar.stats.buffs
+ if (avatar.stats != null && avatar.stats?.buffs != null) {
+ val buffs = avatar.stats?.buffs
if (buffs?.snowball == true) {
layerMap[AvatarView.LayerType.VISUAL_BUFF] = "snowman"
@@ -216,7 +216,7 @@ class AvatarView : View {
}
if (buffs?.shinySeed == true) {
- layerMap[AvatarView.LayerType.VISUAL_BUFF] = "avatar_floral_" + avatar.stats.habitClass
+ layerMap[AvatarView.LayerType.VISUAL_BUFF] = "avatar_floral_" + avatar.stats?.habitClass
hasVisualBuffs = true
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/AvatarWithBarsViewModel.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/AvatarWithBarsViewModel.kt
index f575de802..85bc456df 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/AvatarWithBarsViewModel.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/AvatarWithBarsViewModel.kt
@@ -59,7 +59,7 @@ class AvatarWithBarsViewModel(private val context: Context, view: View, userRepo
fun updateData(user: Avatar) {
userObject = user
- val stats = user.stats
+ val stats = user.stats ?: return
var userClass = ""
@@ -69,13 +69,13 @@ class AvatarWithBarsViewModel(private val context: Context, view: View, userRepo
userClass = stats.getTranslatedClassName(context)
}
- mpBar.visibility = if (stats.habitClass == null || stats.lvl ?: 0 < 10 || user.preferences.disableClasses) View.GONE else View.VISIBLE
+ mpBar.visibility = if (stats.habitClass == null || stats.lvl ?: 0 < 10 || user.preferences?.disableClasses == true) View.GONE else View.VISIBLE
if (!user.hasClass()) {
- lvlText.text = context.getString(R.string.user_level, user.stats.lvl)
+ lvlText.text = context.getString(R.string.user_level, stats.lvl)
lvlText.setCompoundDrawables(null, null, null, null)
} else {
- lvlText.text = context.getString(R.string.user_level_with_class, user.stats.lvl, userClass.substring(0, 1).toUpperCase(Locale.getDefault()) + userClass.substring(1))
+ lvlText.text = context.getString(R.string.user_level_with_class, stats.lvl, userClass.substring(0, 1).toUpperCase(Locale.getDefault()) + userClass.substring(1))
var drawable: Drawable? = null
when (stats.habitClass) {
Stats.WARRIOR -> drawable = BitmapDrawable(context.resources, HabiticaIconsHelper.imageOfWarriorDarkBg())
@@ -93,7 +93,7 @@ class AvatarWithBarsViewModel(private val context: Context, view: View, userRepo
currencyView.gold = stats.gp ?: 0.0
if (user is User) {
- currencyView.hourglasses = user.getHourglassCount().toDouble()
+ currencyView.hourglasses = user.hourglassCount?.toDouble() ?: 0.0
currencyView.gems = user.gemCount.toDouble()
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/RoundedFrameLayout.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/RoundedFrameLayout.kt
new file mode 100644
index 000000000..bc6d7bd58
--- /dev/null
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/RoundedFrameLayout.kt
@@ -0,0 +1,25 @@
+package com.habitrpg.android.habitica.ui
+
+import android.content.Context
+import android.graphics.Canvas
+import android.graphics.Path
+import android.graphics.RectF
+import android.util.AttributeSet
+import android.widget.FrameLayout
+
+
+class RoundedFrameLayout @JvmOverloads constructor(
+ context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
+) : FrameLayout(context, attrs, defStyleAttr) {
+
+ var radius = 4f
+ var isCirclular = true
+
+ override fun onDraw(canvas: Canvas) {
+ val clipPath = Path()
+ val radius = if (isCirclular) (canvas.height/2).toFloat() else radius
+ clipPath.addRoundRect(RectF(canvas.clipBounds), radius, radius, Path.Direction.CW)
+ canvas.clipPath(clipPath)
+ super.onDraw(canvas)
+ }
+}
\ No newline at end of file
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/SpeechBubbleView.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/SpeechBubbleView.kt
index 50c34f592..c8f72c0dd 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/SpeechBubbleView.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/SpeechBubbleView.kt
@@ -43,7 +43,6 @@ class SpeechBubbleView(context: Context, attrs: AttributeSet) : FrameLayout(cont
this.setOnClickListener(this)
}
-
fun setConfirmationButtonVisibility(visibility: Int) {
confirmationButtons.visibility = visibility
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FixCharacterValuesActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FixCharacterValuesActivity.kt
index 32a83db3b..75c16fcdd 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FixCharacterValuesActivity.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FixCharacterValuesActivity.kt
@@ -88,7 +88,7 @@ class FixCharacterValuesActivity: BaseActivity() {
levelEditText.text = user.stats?.lvl.toString()
streakEditText.text = user.streakCount.toString()
- when (user.stats.habitClass) {
+ when (user.stats?.habitClass) {
Stats.WARRIOR -> {
levelEditText.iconBackgroundColor = ContextCompat.getColor(this, R.color.red_500)
levelEditText.setIconBitmap(HabiticaIconsHelper.imageOfWarriorLightBg())
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FullProfileActivity.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FullProfileActivity.kt
index 950e93430..0ac451739 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FullProfileActivity.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/activities/FullProfileActivity.kt
@@ -21,6 +21,7 @@ import com.habitrpg.android.habitica.components.AppComponent
import com.habitrpg.android.habitica.data.ApiClient
import com.habitrpg.android.habitica.data.InventoryRepository
import com.habitrpg.android.habitica.data.SocialRepository
+import com.habitrpg.android.habitica.extensions.notNull
import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.helpers.UserStatComputer
import com.habitrpg.android.habitica.models.AchievementGroup
@@ -73,7 +74,7 @@ class FullProfileActivity : BaseActivity() {
private var userId = ""
private var userName: String? = null
- private var avatarWithBars = AvatarWithBarsViewModel(this, avatar_with_bars)
+ private var avatarWithBars: AvatarWithBarsViewModel? = null
private var attributeStrSum = 0f
private var attributeIntSum = 0f
private var attributeConSum = 0f
@@ -92,12 +93,14 @@ class FullProfileActivity : BaseActivity() {
socialRepository.getMember(this.userId).subscribe(Consumer { this.updateView(it) }, RxErrorHandler.handleEmptyError())
- avatarWithBars.valueBarLabelsToBlack()
+ avatarWithBars?.valueBarLabelsToBlack()
avatar_with_bars.setBackgroundColor(ContextCompat.getColor(this, R.color.transparent))
attributeRows.clear()
attributesCardView.setOnClickListener { toggleAttributeDetails() }
+
+ avatarWithBars = AvatarWithBarsViewModel(this, avatar_with_bars)
}
override fun onDestroy() {
@@ -186,11 +189,11 @@ class FullProfileActivity : BaseActivity() {
avatarView.setAvatar(user)
- avatarWithBars.updateData(user)
+ avatarWithBars?.updateData(user)
loadItemDataByOutfit(user.equipped).subscribe(Consumer { gear -> this.gotGear(gear, user) }, RxErrorHandler.handleEmptyError())
- if (user.preferences.costume) {
+ if (user.preferences?.costume == true) {
loadItemDataByOutfit(user.costume).subscribe(Consumer> { this.gotCostume(it) }, RxErrorHandler.handleEmptyError())
} else {
costumeCard.visibility = View.GONE
@@ -300,7 +303,7 @@ class FullProfileActivity : BaseActivity() {
}
private fun addLevelAttributes(user: Member) {
- val byLevelStat = Math.min((user.stats.lvl ?: 0) / 2.0f, 50f)
+ val byLevelStat = Math.min((user.stats?.lvl ?: 0) / 2.0f, 50f)
addAttributeRow(getString(R.string.profile_level), byLevelStat, byLevelStat, byLevelStat, byLevelStat, true, false)
}
@@ -341,7 +344,7 @@ class FullProfileActivity : BaseActivity() {
}
}
- addNormalAddBuffAttributes(user.stats)
+ user.stats.notNull { addNormalAddBuffAttributes(it) }
}
private fun gotCostume(obj: List) {
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/ChatRecyclerViewAdapter.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/ChatRecyclerViewAdapter.kt
index a36e87fcd..0bced54ec 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/ChatRecyclerViewAdapter.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/ChatRecyclerViewAdapter.kt
@@ -3,13 +3,11 @@ package com.habitrpg.android.habitica.ui.adapter.social
import android.content.Context
import android.content.res.Resources
import android.support.v4.content.ContextCompat
-import android.support.v7.widget.PopupMenu
import android.support.v7.widget.RecyclerView
import android.text.method.LinkMovementMethod
-import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
-import android.widget.ImageView
+import android.widget.Button
import android.widget.LinearLayout
import android.widget.TextView
import com.habitrpg.android.habitica.R
@@ -17,9 +15,11 @@ import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.android.habitica.extensions.notNull
import com.habitrpg.android.habitica.models.social.ChatMessage
import com.habitrpg.android.habitica.models.user.User
+import com.habitrpg.android.habitica.ui.AvatarView
import com.habitrpg.android.habitica.ui.helpers.DataBindingUtils
import com.habitrpg.android.habitica.ui.helpers.MarkdownParser
import com.habitrpg.android.habitica.ui.helpers.bindView
+import com.habitrpg.android.habitica.ui.views.social.UsernameLabel
import io.reactivex.BackpressureStrategy
import io.reactivex.Flowable
import io.reactivex.Maybe
@@ -33,13 +33,13 @@ import net.pherth.android.emoji_library.EmojiTextView
class ChatRecyclerViewAdapter(data: OrderedRealmCollection?, autoUpdate: Boolean, private val user: User?, private val isTavern: Boolean) : RealmRecyclerViewAdapter(data, autoUpdate) {
private var uuid: String = ""
private var sendingUser: User? = null
+ private var expandedMessageId: String? = null
private val likeMessageEvents = PublishSubject.create()
private val userLabelClickEvents = PublishSubject.create()
- private val privateMessageClickEvents = PublishSubject.create()
private val deleteMessageEvents = PublishSubject.create()
private val flagMessageEvents = PublishSubject.create()
- private val copyMessageAsTodoEvents = PublishSubject.create()
+ private val replyMessageEvents = PublishSubject.create()
private val copyMessageEvents = PublishSubject.create()
init {
@@ -66,10 +66,6 @@ class ChatRecyclerViewAdapter(data: OrderedRealmCollection?, autoUp
return userLabelClickEvents.toFlowable(BackpressureStrategy.DROP)
}
- fun getPrivateMessageClickFlowable(): Flowable {
- return privateMessageClickEvents.toFlowable(BackpressureStrategy.DROP)
- }
-
fun getFlagMessageClickFlowable(): Flowable {
return flagMessageEvents.toFlowable(BackpressureStrategy.DROP)
}
@@ -78,8 +74,8 @@ class ChatRecyclerViewAdapter(data: OrderedRealmCollection?, autoUp
return deleteMessageEvents.toFlowable(BackpressureStrategy.DROP)
}
- fun getCopyMessageAsTodoFlowable(): Flowable {
- return copyMessageAsTodoEvents.toFlowable(BackpressureStrategy.DROP)
+ fun getReplyMessageEvents(): Flowable {
+ return replyMessageEvents.toFlowable(BackpressureStrategy.DROP)
}
fun getCopyMessageFlowable(): Flowable {
@@ -87,23 +83,39 @@ class ChatRecyclerViewAdapter(data: OrderedRealmCollection?, autoUp
}
- inner class ChatRecyclerViewHolder(itemView: View, private val userId: String, private val isTavern: Boolean) : RecyclerView.ViewHolder(itemView), View.OnClickListener, PopupMenu.OnMenuItemClickListener {
+ inner class ChatRecyclerViewHolder(itemView: View, private val userId: String, private val isTavern: Boolean) : RecyclerView.ViewHolder(itemView) {
- private val btnOptions: ImageView by bindView(R.id.btn_options)
- private val userBackground: LinearLayout by bindView(R.id.user_background_layout)
- private val userLabel: TextView by bindView(R.id.user_label)
+ private val avatarView: AvatarView by bindView(R.id.avatar_view)
+ private val userLabel: UsernameLabel by bindView(R.id.user_label)
private val messageText: EmojiTextView by bindView(R.id.message_text)
private val agoLabel: TextView by bindView(R.id.ago_label)
private val likeBackground: LinearLayout by bindView(R.id.like_background_layout)
private val tvLikes: TextView by bindView(R.id.tvLikes)
+ private val buttonsWrapper: LinearLayout by bindView(R.id.buttons_wrapper)
+ private val replyButton: Button by bindView(R.id.reply_button)
+ private val copyButton: Button by bindView(R.id.copy_button)
+ private val reportButton: Button by bindView(R.id.report_button)
+ private val deleteButton: Button by bindView(R.id.delete_button)
val context: Context = itemView.context
val res: Resources = itemView.resources
private var chatMessage: ChatMessage? = null
init {
- btnOptions.setOnClickListener(this)
- tvLikes.setOnClickListener { toggleLike() }
+ itemView.setOnClickListener {
+ expandedMessageId = if (expandedMessageId == chatMessage?.id) {
+ null
+ } else {
+ chatMessage?.id
+ }
+ notifyItemChanged(adapterPosition)
+ }
+ tvLikes.setOnClickListener { chatMessage.notNull { likeMessageEvents.onNext(it) } }
+ userLabel.setOnClickListener { chatMessage?.uuid.notNull {userLabelClickEvents.onNext(it) } }
+ replyButton.setOnClickListener { chatMessage?.text.notNull { replyMessageEvents.onNext(it) } }
+ copyButton.setOnClickListener { chatMessage.notNull { copyMessageEvents.onNext(it) } }
+ reportButton.setOnClickListener { chatMessage.notNull { flagMessageEvents.onNext(it) } }
+ deleteButton.setOnClickListener { chatMessage.notNull { deleteMessageEvents.onNext(it) } }
}
fun bind(msg: ChatMessage) {
@@ -112,26 +124,21 @@ class ChatRecyclerViewAdapter(data: OrderedRealmCollection?, autoUp
setLikeProperties()
if (msg.sent != null && msg.sent == "true" && sendingUser != null) {
- DataBindingUtils.setRoundedBackgroundInt(userBackground, sendingUser!!.contributorColor)
+ userLabel.tier = sendingUser?.contributor?.level ?: 0
} else {
- DataBindingUtils.setRoundedBackgroundInt(userBackground, msg.contributorColor)
+ userLabel.tier = msg.contributor?.level ?: 0
}
if (msg.sent != null && msg.sent == "true") {
- userLabel.text = sendingUser?.profile?.name
+ userLabel.username = sendingUser?.profile?.name
} else {
if (msg.user != null && msg.user?.isNotEmpty() == true) {
- userLabel.text = msg.user
+ userLabel.username = msg.user
} else {
- userLabel.setText(R.string.system)
+ userLabel.username = context.getString(R.string.system)
}
}
- userLabel.isClickable = true
- userLabel.setOnClickListener { view -> userLabelClickEvents.onNext(msg.uuid ?: "") }
-
- DataBindingUtils.setForegroundTintColor(userLabel, msg.contributorForegroundColor)
-
messageText.text = chatMessage?.parsedText
if (msg.parsedText == null) {
messageText.text = chatMessage?.text
@@ -147,6 +154,18 @@ class ChatRecyclerViewAdapter(data: OrderedRealmCollection?, autoUp
this.messageText.movementMethod = LinkMovementMethod.getInstance()
agoLabel.text = msg.getAgoString(res)
+
+ msg.userStyles.notNull {
+ avatarView.setAvatar(it)
+ }
+
+ if (expandedMessageId == msg.id) {
+ buttonsWrapper.visibility = View.VISIBLE
+ deleteButton.visibility = if (shouldShowDelete()) View.VISIBLE else View.GONE
+ replyButton.visibility = if (chatMessage?.isInboxMessage == true) View.GONE else View.VISIBLE
+ } else {
+ buttonsWrapper.visibility = View.GONE
+ }
}
private fun setLikeProperties() {
@@ -173,91 +192,8 @@ class ChatRecyclerViewAdapter(data: OrderedRealmCollection?, autoUp
tvLikes.setTextColor(ContextCompat.getColor(context, foregroundColorRes))
}
- override fun onClick(v: View) {
- if (chatMessage != null) {
- if (btnOptions === v) {
- val popupMenu = PopupMenu(context, v)
-
- //set my own listener giving the View that activates the event onClick (i.e. YOUR ImageView)
- popupMenu.setOnMenuItemClickListener(this)
- //inflate your PopUpMenu
- popupMenu.menuInflater.inflate(R.menu.chat_message, popupMenu.menu)
-
- // Force icons to show
- var menuHelper: Any? = null
- var argTypes: Array>
- try {
- val fMenuHelper = PopupMenu::class.java.getDeclaredField("mPopup")
- fMenuHelper.isAccessible = true
- menuHelper = fMenuHelper.get(popupMenu)
- argTypes = arrayOf(Boolean::class.java)
- menuHelper?.javaClass?.getDeclaredMethod("setForceShowIcon", *argTypes)?.invoke(menuHelper, true)
- } catch (ignored: Exception) {
- }
-
-
- popupMenu.menu.findItem(R.id.menu_chat_delete).isVisible = shouldShowDelete(chatMessage)
- popupMenu.menu.findItem(R.id.menu_chat_flag).isVisible = chatMessage?.uuid != "system"
- popupMenu.menu.findItem(R.id.menu_chat_copy_as_todo).isVisible = false
- popupMenu.menu.findItem(R.id.menu_chat_send_pm).isVisible = false
-
- popupMenu.show()
-
- // Try to force some horizontal offset
- try {
- val fListPopup = menuHelper?.javaClass?.getDeclaredField("mPopup")
- fListPopup?.isAccessible = true
- val listPopup = fListPopup?.get(menuHelper)
- argTypes = arrayOf(Int::class.java)
- val listPopupClass = listPopup?.javaClass
-
- // Get the width of the popup window
- val width = listPopupClass?.getDeclaredMethod("getWidth")?.invoke(listPopup) as Int?
-
- // Invoke setHorizontalOffset() with the negative width to move left by that distance
- listPopupClass?.getDeclaredMethod("setHorizontalOffset", *argTypes)?.invoke(listPopup, -(width ?: 0))
-
- // Invoke show() to update the window's position
- listPopupClass?.getDeclaredMethod("show")?.invoke(listPopup)
- } catch (ignored: Exception) {
-
- }
-
- }
- }
- }
-
- private fun shouldShowDelete(chatMsg: ChatMessage?): Boolean {
- return chatMsg?.isSystemMessage != true && (chatMsg?.uuid == userId || user?.contributor != null && user.contributor.admin)
- }
-
- fun toggleLike() {
- chatMessage.notNull { likeMessageEvents.onNext(it) }
- }
-
- override fun onMenuItemClick(item: MenuItem): Boolean {
- chatMessage.notNull {
- when (item.itemId) {
- R.id.menu_chat_delete -> {
- deleteMessageEvents.onNext(it)
- }
- R.id.menu_chat_flag -> {
- flagMessageEvents.onNext(it)
- }
- R.id.menu_chat_copy_as_todo -> {
- copyMessageAsTodoEvents.onNext(it)
- }
-
- R.id.menu_chat_send_pm -> {
- privateMessageClickEvents.onNext(it.uuid ?: "")
- }
-
- R.id.menu_chat_copy -> {
- copyMessageEvents.onNext(it)
- }
- }
- }
- return false
+ private fun shouldShowDelete(): Boolean {
+ return chatMessage?.isSystemMessage != true && (chatMessage?.uuid == userId || user?.contributor != null && user.contributor.admin)
}
}
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/PartyMemberRecyclerViewAdapter.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/PartyMemberRecyclerViewAdapter.kt
index f7fb9a778..93b5a64ea 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/PartyMemberRecyclerViewAdapter.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/adapter/social/PartyMemberRecyclerViewAdapter.kt
@@ -1,6 +1,5 @@
package com.habitrpg.android.habitica.ui.adapter.social
-import android.content.Context
import android.support.v4.content.ContextCompat
import android.support.v7.widget.RecyclerView
import android.view.View
@@ -58,13 +57,13 @@ class PartyMemberRecyclerViewAdapter(data: OrderedRealmCollection?, auto
fun bind(user: Member) {
avatarView.setAvatar(user)
- AvatarWithBarsViewModel.setHpBarData(hpBar, user.stats)
+ user.stats.notNull { AvatarWithBarsViewModel.setHpBarData(hpBar, it) }
- lvl.text = itemView.context.getString(R.string.user_level, user.stats.lvl)
+ lvl.text = itemView.context.getString(R.string.user_level, user.stats?.lvl)
- classLabel.text = user.stats.getTranslatedClassName(itemView.context)
+ classLabel.text = user.stats?.getTranslatedClassName(itemView.context)
- val colorResourceID: Int = when (user.stats.habitClass) {
+ val colorResourceID: Int = when (user.stats?.habitClass) {
Stats.HEALER -> {
R.color.class_healer
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/StatsFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/StatsFragment.kt
index 22920d2e1..6c7741753 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/StatsFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/StatsFragment.kt
@@ -204,7 +204,7 @@ class StatsFragment: BaseMainFragment() {
private fun updateStats() {
val currentUser = user ?: return
- val levelStat = Math.min((currentUser.stats.lvl ?: 0) / 2.0f, 50f).toInt()
+ val levelStat = Math.min((currentUser.stats?.lvl ?: 0) / 2.0f, 50f).toInt()
totalStrength = levelStat
totalIntelligence = levelStat
@@ -225,14 +225,14 @@ class StatsFragment: BaseMainFragment() {
constitutionStatsView.buffValue = currentUser.stats?.buffs?.con?.toInt() ?: 0
perceptionStatsView.buffValue = currentUser.stats?.buffs?.per?.toInt() ?: 0
- totalStrength += currentUser.stats?.str?.toInt() ?: 0
- totalIntelligence += currentUser.stats?._int?.toInt() ?: 0
- totalConstitution += currentUser.stats?.con?.toInt() ?: 0
- totalPerception += currentUser.stats?.per?.toInt() ?: 0
- strengthStatsView.allocatedValue = currentUser.stats?.str?.toInt() ?: 0
- intelligenceStatsView.allocatedValue = currentUser.stats?._int?.toInt() ?: 0
- constitutionStatsView.allocatedValue = currentUser.stats?.con?.toInt() ?: 0
- perceptionStatsView.allocatedValue = currentUser.stats?.per?.toInt() ?: 0
+ totalStrength += currentUser.stats?.str ?: 0
+ totalIntelligence += currentUser.stats?._int ?: 0
+ totalConstitution += currentUser.stats?.con ?: 0
+ totalPerception += currentUser.stats?.per ?: 0
+ strengthStatsView.allocatedValue = currentUser.stats?.str ?: 0
+ intelligenceStatsView.allocatedValue = currentUser.stats?._int ?: 0
+ constitutionStatsView.allocatedValue = currentUser.stats?.con ?: 0
+ perceptionStatsView.allocatedValue = currentUser.stats?.per ?: 0
val outfit = currentUser.items.gear.equipped
val outfitList = ArrayList()
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/customization/AvatarOverviewFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/customization/AvatarOverviewFragment.kt
index f174b94fd..edc264987 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/customization/AvatarOverviewFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/inventory/customization/AvatarOverviewFragment.kt
@@ -103,7 +103,7 @@ class AvatarOverviewFragment : BaseMainFragment(), AdapterView.OnItemSelectedLis
override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
val newSize: String = if (position == 0) "slim" else "broad"
- if (this.user != null && this.user!!.preferences.size != newSize) {
+ if (this.user != null && this.user!!.preferences?.size != newSize) {
userRepository.updateUser(user, "preferences.size", newSize)
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError())
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/PreferencesFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/PreferencesFragment.kt
index 841e61576..afe6b1eef 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/PreferencesFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/preferences/PreferencesFragment.kt
@@ -228,7 +228,7 @@ class PreferencesFragment : BasePreferencesFragment(), SharedPreferences.OnShare
this.user = user
if (10 <= user?.stats?.lvl ?: 0) {
if (user?.flags?.classSelected == true) {
- if (user.preferences.disableClasses) {
+ if (user.preferences?.disableClasses == true) {
classSelectionPreference?.title = getString(R.string.enable_class)
} else {
classSelectionPreference?.title = getString(R.string.change_class)
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/skills/SkillsFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/skills/SkillsFragment.kt
index 5435d6165..f17e92117 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/skills/SkillsFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/skills/SkillsFragment.kt
@@ -108,7 +108,7 @@ class SkillsFragment : BaseMainFragment() {
private fun displaySkillResult(usedSkill: Skill?, response: SkillResponse) {
removeProgressDialog()
- adapter?.mana = response.user.stats.mp ?: 0.0
+ adapter?.mana = response.user.stats?.mp ?: 0.0
val activity = activity ?: return
if ("special" == usedSkill?.habitClass) {
showSnackbar(activity.floatingMenuWrapper, context!!.getString(R.string.used_skill_without_mana, usedSkill.text), HabiticaSnackbar.SnackbarDisplayType.BLUE)
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/ChatListFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/ChatListFragment.kt
index 681ec6745..3a2096761 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/ChatListFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/ChatListFragment.kt
@@ -12,6 +12,7 @@ import android.support.v7.widget.LinearLayoutManager
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.widget.TextView
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.components.AppComponent
import com.habitrpg.android.habitica.data.SocialRepository
@@ -110,7 +111,7 @@ class ChatListFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener {
}, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(it.getDeleteMessageFlowable().subscribe(Consumer { this.showDeleteConfirmationDialog(it) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(it.getFlagMessageClickFlowable().subscribe(Consumer { this.showFlagConfirmationDialog(it) }, RxErrorHandler.handleEmptyError()))
- compositeSubscription.add(it.getCopyMessageAsTodoFlowable().subscribe(Consumer{ this.copyMessageAsTodo(it) }, RxErrorHandler.handleEmptyError()))
+ compositeSubscription.add(it.getReplyMessageEvents().subscribe(Consumer{ chatEditText.setText(it, TextView.BufferType.EDITABLE) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(it.getCopyMessageFlowable().subscribe(Consumer { this.copyMessageToClipboard(it) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(it.getLikeMessageFlowable().flatMap { socialRepository.likeMessage(it) }.subscribe(Consumer { }, RxErrorHandler.handleEmptyError()))
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/InboxMessageListFragment.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/InboxMessageListFragment.kt
index db6e894db..3648162cf 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/InboxMessageListFragment.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/fragments/social/InboxMessageListFragment.kt
@@ -10,6 +10,7 @@ import android.support.v7.widget.LinearLayoutManager
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.widget.TextView
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.components.AppComponent
import com.habitrpg.android.habitica.data.SocialRepository
@@ -64,10 +65,9 @@ class InboxMessageListFragment : BaseMainFragment(), SwipeRefreshLayout.OnRefres
compositeSubscription.add(it.getUserLabelClickFlowable().subscribe(Consumer {
context.notNull { context -> FullProfileActivity.open(context, it) }
}, RxErrorHandler.handleEmptyError()))
- compositeSubscription.add(it.getDeleteMessageFlowable().subscribe(Consumer { this.showDeleteConfirmationDialog(it) }, RxErrorHandler.handleEmptyError()))
- compositeSubscription.add(it.getFlagMessageClickFlowable().subscribe(Consumer { this.showFlagConfirmationDialog(it) }, RxErrorHandler.handleEmptyError()))
- compositeSubscription.add(it.getCopyMessageAsTodoFlowable().subscribe(Consumer { this.copyMessageAsTodo(it) }, RxErrorHandler.handleEmptyError()))
- compositeSubscription.add(it.getCopyMessageFlowable().subscribe(Consumer { this.copyMessageToClipboard(it) }, RxErrorHandler.handleEmptyError()))
+ compositeSubscription.add(it.getDeleteMessageFlowable().subscribe(Consumer { this.showDeleteConfirmationDialog(it) }, RxErrorHandler.handleEmptyError()))
+ compositeSubscription.add(it.getFlagMessageClickFlowable().subscribe(Consumer { this.showFlagConfirmationDialog(it) }, RxErrorHandler.handleEmptyError()))
+ compositeSubscription.add(it.getCopyMessageFlowable().subscribe(Consumer { this.copyMessageToClipboard(it) }, RxErrorHandler.handleEmptyError()))
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialog.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialog.kt
index ee7e9e8c7..46b17768c 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialog.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/shops/PurchaseDialog.kt
@@ -111,7 +111,7 @@ class PurchaseDialog(context: Context, component: AppComponent?, val item: ShopI
return
}
- if (shopItem.habitClass != null && shopItem.habitClass != "special" && user.stats.habitClass != shopItem.habitClass) {
+ if (shopItem.habitClass != "special" && user.stats?.habitClass != shopItem.habitClass) {
limitedTextView.text = context.getString(R.string.class_equipment_shop_dialog)
limitedTextView.visibility = View.VISIBLE
limitedTextView.setBackgroundColor(ContextCompat.getColor(context, R.color.gray_100))
@@ -152,9 +152,9 @@ class PurchaseDialog(context: Context, component: AppComponent?, val item: ShopI
private fun setUser(user: User) {
this.user = user
- currencyView.gold = user.stats.gp ?: 0.0
+ currencyView.gold = user.stats?.gp ?: 0.0
currencyView.gems = user.gemCount.toDouble()
- currencyView.hourglasses = user.hourglassCount.toDouble()
+ currencyView.hourglasses = user.hourglassCount?.toDouble() ?: 0.0
if ("gems" == shopItem.purchaseType) {
val gemsLeft = if (shopItem.limitedNumberLeft != null) shopItem.limitedNumberLeft else 0
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/social/UsernameLabel.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/social/UsernameLabel.kt
index 315d2db59..ef6335d97 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/social/UsernameLabel.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/views/social/UsernameLabel.kt
@@ -17,7 +17,7 @@ class UsernameLabel(context: Context?, attrs: AttributeSet?) : LinearLayout(cont
private val textView = TextView(context)
private val tierIconView = ImageView(context)
- var username: String = ""
+ var username: String? = ""
set(value) {
textView.text = value
}
diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/utils/ChatMessageDeserializer.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/utils/ChatMessageDeserializer.kt
index 746f139f6..199a2ae93 100644
--- a/Habitica/src/main/java/com/habitrpg/android/habitica/utils/ChatMessageDeserializer.kt
+++ b/Habitica/src/main/java/com/habitrpg/android/habitica/utils/ChatMessageDeserializer.kt
@@ -7,23 +7,22 @@ import com.google.gson.JsonParseException
import com.habitrpg.android.habitica.models.social.Backer
import com.habitrpg.android.habitica.models.social.ChatMessage
import com.habitrpg.android.habitica.models.social.ChatMessageLike
+import com.habitrpg.android.habitica.models.social.UserStyles
import com.habitrpg.android.habitica.models.user.ContributorInfo
import io.realm.RealmList
import java.lang.reflect.Type
+import java.util.*
class ChatMessageDeserializer : JsonDeserializer {
@Throws(JsonParseException::class)
override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): ChatMessage {
val message = ChatMessage()
val obj = json.asJsonObject
- if (obj.has("id")) {
- message.id = obj.get("id").asString
- }
if (obj.has("text") && !obj.get("text").isJsonNull && obj.get("text").isJsonPrimitive) {
message.text = obj.get("text").asString
}
if (obj.has("timestamp")) {
- message.timestamp = obj.get("timestamp").asLong
+ message.timestamp = context.deserialize(obj.get("timestamp"), Date::class.java).time
}
if (obj.has("likes")) {
message.likes = RealmList()
@@ -66,6 +65,13 @@ class ChatMessageDeserializer : JsonDeserializer {
message.sent = obj.get("sent").asString
}
+ if (obj.has("userStyles")) {
+ message.userStyles = context.deserialize(obj.get("userStyles"), UserStyles::class.java)
+ }
+ if (obj.has("id")) {
+ message.id = obj.get("id").asString
+ }
+
return message
}
}