Begin redesigning chat

This commit is contained in:
Phillip Thelen 2018-07-13 15:58:53 +02:00
parent 58fb5e465a
commit 5040574bf0
32 changed files with 362 additions and 338 deletions

View file

@ -0,0 +1,4 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/transparent" />
</shape>

View file

@ -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">
<com.habitrpg.android.habitica.ui.RoundedFrameLayout
android:layout_width="@dimen/avatar_chat_size"
android:layout_height="@dimen/avatar_chat_size"
android:clipChildren="true"
android:layout_marginRight="@dimen/spacing_medium"
android:layout_marginEnd="@dimen/spacing_medium"
android:background="@drawable/rounded_avatar_bg">
<com.habitrpg.android.habitica.ui.AvatarView
android:id="@+id/avatar_view"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_gravity="center"
app:showMount="false"
app:showPet="false" />
</com.habitrpg.android.habitica.ui.RoundedFrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
style="@style/CardContent.Compact">
style="@style/CardContent.Compact"
android:background="@drawable/layout_rounded_bg"
android:padding="@dimen/spacing_medium">
<LinearLayout
android:layout_width="fill_parent"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:weightSum="1.0"
android:baselineAligned="false"
android:gravity="center_vertical">
<com.habitrpg.android.habitica.ui.views.social.UsernameLabel
android:id="@+id/user_label"
style="@style/ChatMessageUserTextViewStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:weightSum="1.0"
android:baselineAligned="false">
<LinearLayout
android:clickable="true"
tools:text="Username"
android:focusable="true" />
<TextView
android:id="@+id/ago_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:lines="1"
android:ellipsize="end"
tools:text="2d ago"
android:textSize="12sp"
android:textColor="@color/gray_300"
android:layout_marginLeft="@dimen/spacing_medium"
android:layout_marginStart="@dimen/spacing_medium"/>
<View
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.5">
<LinearLayout
android:id="@+id/user_background_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|center"
android:layout_margin="10dp"
android:background="@drawable/layout_rounded_bg">
<TextView
android:id="@+id/user_label"
style="@style/ChatMessageUserTextViewStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:ellipsize="middle"
android:lines="1"
android:singleLine="true"
tools:text="Username" />
</LinearLayout>
</LinearLayout>
android:layout_height="1dp"
android:layout_weight="1" />
<LinearLayout
android:layout_width="0dp"
android:id="@+id/like_background_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:gravity="right">
android:layout_gravity="center_vertical|right"
<LinearLayout
android:layout_marginLeft="5dp"
android:layout_marginStart="5dp"
android:layout_weight="1"
android:background="@drawable/layout_rounded_bg">
<TextView
android:id="@+id/tvLikes"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center|right"
android:layout_margin="5dp">
<LinearLayout
android:id="@+id/like_background_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|right"
android:layout_marginLeft="5dp"
android:layout_marginStart="5dp"
android:layout_weight="1"
android:background="@drawable/layout_rounded_bg">
<TextView
android:id="@+id/tvLikes"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:clickable="true"
android:gravity="center_vertical" />
</LinearLayout>
<ImageView
android:id="@+id/btn_options"
android:layout_width="25dp"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="8dp"
android:layout_marginTop="5dp"
android:layout_weight="0.06"
android:src="@drawable/ic_action_more_vert" />
</LinearLayout>
android:layout_margin="5dp"
android:clickable="true"
android:gravity="center_vertical"
android:focusable="true" />
</LinearLayout>
</LinearLayout>
@ -96,15 +91,42 @@
android:layout_margin="8dp"
android:lineSpacingMultiplier="1.0"
tools:text="This is the chat message"/>
<TextView
android:id="@+id/ago_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center|right"
android:layout_marginRight="8dp"
android:singleLine="true"
android:lines="1"
android:ellipsize="end"/>
<LinearLayout
android:id="@+id/buttons_wrapper"
android:layout_width="match_parent"
android:layout_height="36dp">
<Button
android:id="@+id/reply_button"
android:layout_width="wrap_content"
android:layout_height="match_parent"
style="@style/Base.Widget.AppCompat.Button.Borderless"
android:textSize="12sp"
android:textColor="@color/gray_300"
android:text="@string/reply" />
<Button
android:id="@+id/copy_button"
android:layout_width="wrap_content"
android:layout_height="match_parent"
style="@style/Base.Widget.AppCompat.Button.Borderless"
android:textSize="12sp"
android:textColor="@color/gray_300"
android:text="@string/copy" />
<Button
android:id="@+id/report_button"
android:layout_width="wrap_content"
android:layout_height="match_parent"
style="@style/Base.Widget.AppCompat.Button.Borderless"
android:textSize="12sp"
android:textColor="@color/gray_300"
android:text="@string/report" />
<Button
android:id="@+id/delete_button"
android:layout_width="wrap_content"
android:layout_height="match_parent"
style="@style/Base.Widget.AppCompat.Button.Borderless"
android:textSize="12sp"
android:textColor="@color/gray_300"
android:text="@string/delete" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

View file

@ -125,5 +125,7 @@
<dimen name="snackbar_image_size">46dp</dimen>
<dimen name="bullet_size">6dp</dimen>
<dimen name="icon_size">18dp</dimen>
<dimen name="chat_horizontal_inset">16dp</dimen>
<dimen name="avatar_chat_size">36dp</dimen>
</resources>

View file

@ -301,12 +301,12 @@
<string name="quest.invitation">Quest Invitation</string>
<string name="quest_begin_message">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.</string>
<string name="quest.invitation.text">You have been invited to participate in a quest!</string>
<string name="ago_1day">1 day ago</string>
<string name="ago_days">%d days ago</string>
<string name="ago_1Minute">1 minute ago</string>
<string name="ago_minutes">%d minutes ago</string>
<string name="ago_hours">%d hours ago</string>
<string name="ago_1hour">1 hour ago</string>
<string name="ago_1day">1d ago</string>
<string name="ago_days">%dd ago</string>
<string name="ago_1Minute">1m ago</string>
<string name="ago_minutes">%dm ago</string>
<string name="ago_hours">%dh ago</string>
<string name="ago_1hour">1h ago</string>
<string name="today">Today</string>
<string name="sidebar_items">Items</string>
<string name="eggs">Eggs</string>
@ -779,4 +779,7 @@
<string name="seasonalShop_owner_long">Seasonal Sorceress</string>
<string name="rage_attack">Rage attack:</string>
<string name="tavern_description_world_boss">Oh dear, pay no heed to the monster below -- this is still a safe haven to chat on your breaks.</string>
<string name="report">Report</string>
<string name="like">Like</string>
<string name="reply">Reply</string>
</resources>

View file

@ -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)
}

View file

@ -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()
}

View file

@ -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
}

View file

@ -100,7 +100,7 @@ class UserRepositoryImpl(localRepository: UserLocalRepository, apiClient: ApiCli
}
override fun sleep(user: User): Flowable<User> {
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<SkillResponse> {
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)

View file

@ -73,17 +73,17 @@ class RealmUserLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
}
override fun getSkills(user: User): Flowable<RealmResults<Skill>> {
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<RealmResults<Skill>> {
val specialItems = user.items.special
val specialItems = user.items?.special
val ownedItems = ArrayList<String>()
if (specialItems != null) {
if (specialItems.snowball > 0) {

View file

@ -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

View file

@ -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();

View file

@ -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"

View file

@ -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
}

View file

@ -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

View file

@ -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();

View file

@ -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
}

View file

@ -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()
}

View file

@ -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)
}
}

View file

@ -43,7 +43,6 @@ class SpeechBubbleView(context: Context, attrs: AttributeSet) : FrameLayout(cont
this.setOnClickListener(this)
}
fun setConfirmationButtonVisibility(visibility: Int) {
confirmationButtons.visibility = visibility
}

View file

@ -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())

View file

@ -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<RealmResults<Equipment>> { 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<Equipment>) {

View file

@ -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<ChatMessage>?, autoUpdate: Boolean, private val user: User?, private val isTavern: Boolean) : RealmRecyclerViewAdapter<ChatMessage, ChatRecyclerViewAdapter.ChatRecyclerViewHolder>(data, autoUpdate) {
private var uuid: String = ""
private var sendingUser: User? = null
private var expandedMessageId: String? = null
private val likeMessageEvents = PublishSubject.create<ChatMessage>()
private val userLabelClickEvents = PublishSubject.create<String>()
private val privateMessageClickEvents = PublishSubject.create<String>()
private val deleteMessageEvents = PublishSubject.create<ChatMessage>()
private val flagMessageEvents = PublishSubject.create<ChatMessage>()
private val copyMessageAsTodoEvents = PublishSubject.create<ChatMessage>()
private val replyMessageEvents = PublishSubject.create<String>()
private val copyMessageEvents = PublishSubject.create<ChatMessage>()
init {
@ -66,10 +66,6 @@ class ChatRecyclerViewAdapter(data: OrderedRealmCollection<ChatMessage>?, autoUp
return userLabelClickEvents.toFlowable(BackpressureStrategy.DROP)
}
fun getPrivateMessageClickFlowable(): Flowable<String> {
return privateMessageClickEvents.toFlowable(BackpressureStrategy.DROP)
}
fun getFlagMessageClickFlowable(): Flowable<ChatMessage> {
return flagMessageEvents.toFlowable(BackpressureStrategy.DROP)
}
@ -78,8 +74,8 @@ class ChatRecyclerViewAdapter(data: OrderedRealmCollection<ChatMessage>?, autoUp
return deleteMessageEvents.toFlowable(BackpressureStrategy.DROP)
}
fun getCopyMessageAsTodoFlowable(): Flowable<ChatMessage> {
return copyMessageAsTodoEvents.toFlowable(BackpressureStrategy.DROP)
fun getReplyMessageEvents(): Flowable<String> {
return replyMessageEvents.toFlowable(BackpressureStrategy.DROP)
}
fun getCopyMessageFlowable(): Flowable<ChatMessage> {
@ -87,23 +83,39 @@ class ChatRecyclerViewAdapter(data: OrderedRealmCollection<ChatMessage>?, 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<ChatMessage>?, 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<ChatMessage>?, 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<ChatMessage>?, 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<Class<*>>
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)
}
}
}

View file

@ -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<Member>?, 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
}

View file

@ -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<String>()

View file

@ -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())
}

View file

@ -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)

View file

@ -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)

View file

@ -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<ChatMessage> { socialRepository.likeMessage(it) }.subscribe(Consumer { }, RxErrorHandler.handleEmptyError()))
}

View file

@ -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<String> {
context.notNull { context -> FullProfileActivity.open(context, it) }
}, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(it.getDeleteMessageFlowable().subscribe(Consumer<ChatMessage> { this.showDeleteConfirmationDialog(it) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(it.getFlagMessageClickFlowable().subscribe(Consumer<ChatMessage> { this.showFlagConfirmationDialog(it) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(it.getCopyMessageAsTodoFlowable().subscribe(Consumer<ChatMessage> { this.copyMessageAsTodo(it) }, RxErrorHandler.handleEmptyError()))
compositeSubscription.add(it.getCopyMessageFlowable().subscribe(Consumer<ChatMessage> { 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()))
}

View file

@ -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

View file

@ -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
}

View file

@ -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<ChatMessage> {
@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<Date>(obj.get("timestamp"), Date::class.java).time
}
if (obj.has("likes")) {
message.likes = RealmList()
@ -66,6 +65,13 @@ class ChatMessageDeserializer : JsonDeserializer<ChatMessage> {
message.sent = obj.get("sent").asString
}
if (obj.has("userStyles")) {
message.userStyles = context.deserialize<UserStyles>(obj.get("userStyles"), UserStyles::class.java)
}
if (obj.has("id")) {
message.id = obj.get("id").asString
}
return message
}
}