mirror of
https://github.com/sudoxnym/habitica-android.git
synced 2026-05-17 11:19:01 +00:00
various fixes
This commit is contained in:
parent
25fa75497e
commit
e50f2f42be
30 changed files with 256 additions and 168 deletions
|
|
@ -102,13 +102,13 @@ dependencies {
|
|||
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
|
||||
implementation "androidx.navigation:navigation-fragment-ktx:$navigation_version"
|
||||
implementation "androidx.navigation:navigation-ui-ktx:$navigation_version"
|
||||
implementation "androidx.fragment:fragment-ktx:1.5.4"
|
||||
implementation "androidx.fragment:fragment-ktx:1.5.5"
|
||||
implementation "androidx.paging:paging-runtime-ktx:3.1.1"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
||||
implementation "com.google.android.material:compose-theme-adapter:1.1.21"
|
||||
implementation "com.google.accompanist:accompanist-themeadapter-material:$accompanist_version"
|
||||
implementation "androidx.compose.material3:material3:1.0.1"
|
||||
implementation "com.google.accompanist:accompanist-systemuicontroller:0.27.1"
|
||||
implementation "com.google.accompanist:accompanist-systemuicontroller:$accompanist_version"
|
||||
|
||||
implementation 'androidx.activity:activity-compose:1.6.1'
|
||||
implementation "androidx.compose.runtime:runtime-livedata:$compose_version"
|
||||
|
|
|
|||
|
|
@ -171,7 +171,8 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:text="@string/months_subscribed"
|
||||
android:gravity="center"
|
||||
android:fontFamily="sans-serif-medium"/>
|
||||
android:fontFamily="sans-serif-medium"
|
||||
android:textColor="@color/text_secondary"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
|
|
@ -194,9 +195,10 @@
|
|||
style="@style/subscriptionBoxCompactText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/months_subscribed"
|
||||
android:text="@string/monthly_gem_cap"
|
||||
android:gravity="center"
|
||||
android:fontFamily="sans-serif-medium"/>
|
||||
android:fontFamily="sans-serif-medium"
|
||||
android:textColor="@color/text_secondary"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
|
|
|
|||
|
|
@ -1286,6 +1286,7 @@
|
|||
<string name="unmute_user">Unmute User</string>
|
||||
<string name="status">Status</string>
|
||||
<string name="regular_access">Regular Access</string>
|
||||
<string name="message_flagged">Message flagged %d times.</string>
|
||||
<plurals name="you_x_others">
|
||||
<item quantity="zero">You</item>
|
||||
<item quantity="one">You, %d other</item>
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@
|
|||
<item name="colorPrimaryOffset">@color/gray_10</item>
|
||||
<item name="colorBoxStroke">@color/red_10</item>
|
||||
<item name="textColorPrimaryDark">@color/gray_200</item>
|
||||
<item name="toolbarContentColor">@color/red_100</item>
|
||||
<item name="toolbarContentColor">@color/red_1</item>
|
||||
<item name="colorTintedBackground">@color/red_00</item>
|
||||
<item name="colorTintedBackgroundOffset">@color/red_0</item>
|
||||
<item name="colorPrimaryText">@color/red_600</item>
|
||||
|
|
@ -136,7 +136,7 @@
|
|||
<item name="barColor">@color/gray_1</item>
|
||||
<item name="colorPrimaryOffset">@color/gray_10</item>
|
||||
<item name="textColorPrimaryDark">@color/gray_200</item>
|
||||
<item name="toolbarContentColor">@color/maroon_100</item>
|
||||
<item name="toolbarContentColor">@color/white</item>
|
||||
<item name="colorTintedBackground">@color/maroon_00</item>
|
||||
<item name="colorTintedBackgroundOffset">@color/maroon_0</item>
|
||||
<item name="colorPrimaryText">@color/maroon_600</item>
|
||||
|
|
@ -169,7 +169,7 @@
|
|||
<item name="colorPrimaryOffset">@color/gray_10</item>
|
||||
<item name="colorBoxStroke">@color/orange_10</item>
|
||||
<item name="textColorPrimaryDark">@color/gray_200</item>
|
||||
<item name="toolbarContentColor">@color/orange_100</item>
|
||||
<item name="toolbarContentColor">@color/orange_1</item>
|
||||
<item name="colorTintedBackground">@color/orange_00</item>
|
||||
<item name="colorTintedBackgroundOffset">@color/orange_0</item>
|
||||
<item name="colorPrimaryText">@color/orange_600</item>
|
||||
|
|
@ -202,7 +202,7 @@
|
|||
<item name="colorPrimaryOffset">@color/gray_10</item>
|
||||
<item name="colorBoxStroke">@color/yellow_5</item>
|
||||
<item name="textColorPrimaryDark">@color/gray_200</item>
|
||||
<item name="toolbarContentColor">@color/yellow_100</item>
|
||||
<item name="toolbarContentColor">@color/yellow_1</item>
|
||||
<item name="colorTintedBackground">@color/yellow_00</item>
|
||||
<item name="colorTintedBackgroundOffset">@color/yellow_0</item>
|
||||
<item name="colorPrimaryText">@color/yellow_600</item>
|
||||
|
|
@ -235,7 +235,7 @@
|
|||
<item name="colorPrimaryOffset">@color/gray_10</item>
|
||||
<item name="colorBoxStroke">@color/green_10</item>
|
||||
<item name="textColorPrimaryDark">@color/gray_200</item>
|
||||
<item name="toolbarContentColor">@color/green_100</item>
|
||||
<item name="toolbarContentColor">@color/green_1</item>
|
||||
<item name="colorTintedBackground">@color/green_00</item>
|
||||
<item name="colorTintedBackgroundOffset">@color/green_0</item>
|
||||
<item name="colorPrimaryText">@color/green_600</item>
|
||||
|
|
@ -268,7 +268,7 @@
|
|||
<item name="colorPrimaryOffset">@color/gray_10</item>
|
||||
<item name="colorBoxStroke">@color/teal_10</item>
|
||||
<item name="textColorPrimaryDark">@color/gray_200</item>
|
||||
<item name="toolbarContentColor">@color/teal_100</item>
|
||||
<item name="toolbarContentColor">@color/teal_1</item>
|
||||
<item name="colorTintedBackground">@color/teal_00</item>
|
||||
<item name="colorTintedBackgroundOffset">@color/teal_0</item>
|
||||
<item name="colorPrimaryText">@color/teal_600</item>
|
||||
|
|
@ -301,7 +301,7 @@
|
|||
<item name="colorPrimaryOffset">@color/gray_10</item>
|
||||
<item name="textColorPrimaryDark">@color/gray_200</item>
|
||||
<item name="colorBoxStroke">@color/blue_10</item>
|
||||
<item name="toolbarContentColor">@color/blue_100</item>
|
||||
<item name="toolbarContentColor">@color/blue_1</item>
|
||||
<item name="colorTintedBackground">@color/blue_00</item>
|
||||
<item name="colorTintedBackgroundOffset">@color/blue_0</item>
|
||||
<item name="colorPrimaryText">@color/blue_600</item>
|
||||
|
|
@ -393,6 +393,7 @@
|
|||
<style name="Toolbar.Modern" parent="ThemeOverlay.AppCompat.DayNight.ActionBar">
|
||||
<item name="android:textColorPrimary">?attr/headerTextColor</item>
|
||||
<item name="textColorSecondary">?attr/headerTextColor</item>
|
||||
<item name="textColorPrimary">?attr/toolbarContentColor</item>
|
||||
<item name="android:background">?attr/headerBackgroundColor</item>
|
||||
<item name="actionMenuTextColor">?attr/toolbarContentColor</item>
|
||||
<item name="android:actionMenuTextColor">?attr/toolbarContentColor</item>
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@ open class UserStyles : RealmObject(), Avatar {
|
|||
get() {
|
||||
return false
|
||||
}
|
||||
override val id: String?
|
||||
get() = null
|
||||
override var balance: Double = 0.0
|
||||
override var authentication: Authentication? = null
|
||||
override var stats: Stats? = null
|
||||
|
|
|
|||
|
|
@ -255,7 +255,7 @@ open class Task : RealmObject, BaseMainObject, Parcelable, BaseTask {
|
|||
this.value < 1 -> return R.color.yellow_0
|
||||
this.value < 5 -> return R.color.green_0
|
||||
this.value < 10 -> return R.color.teal_0
|
||||
else -> R.color.blue_1
|
||||
else -> R.color.blue_0
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -268,7 +268,7 @@ open class Task : RealmObject, BaseMainObject, Parcelable, BaseTask {
|
|||
this.value < 1 -> return R.color.yellow_00
|
||||
this.value < 5 -> return R.color.green_00
|
||||
this.value < 10 -> return R.color.teal_00
|
||||
else -> R.color.blue_1
|
||||
else -> R.color.blue_00
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
package com.habitrpg.android.habitica.models.user
|
||||
|
||||
import android.content.res.Resources
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.models.BaseObject
|
||||
import com.habitrpg.shared.habitica.models.AvatarStats
|
||||
import io.realm.RealmObject
|
||||
|
|
@ -50,16 +48,6 @@ open class Stats : RealmObject(), AvatarStats, BaseObject {
|
|||
}
|
||||
}
|
||||
|
||||
fun getTranslatedClassName(resources: Resources): String {
|
||||
return when (habitClass) {
|
||||
HEALER -> resources.getString(R.string.healer)
|
||||
ROGUE -> resources.getString(R.string.rogue)
|
||||
WARRIOR -> resources.getString(R.string.warrior)
|
||||
MAGE -> resources.getString(R.string.mage)
|
||||
else -> resources.getString(R.string.warrior)
|
||||
}
|
||||
}
|
||||
|
||||
fun merge(stats: Stats?) {
|
||||
if (stats == null) {
|
||||
return
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ open class User : RealmObject(), BaseMainObject, Avatar, VersionedObject {
|
|||
|
||||
@PrimaryKey
|
||||
@SerializedName("_id")
|
||||
var id: String? = null
|
||||
override var id: String? = null
|
||||
|
||||
@SerializedName("_v")
|
||||
override var versionNumber: Int = 0
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ import android.view.ViewGroup
|
|||
import android.widget.TableLayout
|
||||
import android.widget.TableRow
|
||||
import android.widget.TextView
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.view.MenuCompat
|
||||
|
|
@ -34,12 +36,12 @@ import com.habitrpg.android.habitica.models.members.Member
|
|||
import com.habitrpg.android.habitica.models.user.Outfit
|
||||
import com.habitrpg.android.habitica.models.user.Permission
|
||||
import com.habitrpg.android.habitica.models.user.Stats
|
||||
import com.habitrpg.android.habitica.ui.AvatarWithBarsViewModel
|
||||
import com.habitrpg.android.habitica.ui.adapter.social.AchievementProfileAdapter
|
||||
import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
|
||||
import com.habitrpg.android.habitica.ui.views.AppHeaderView
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar.SnackbarDisplayType
|
||||
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
|
||||
import com.habitrpg.common.habitica.extensions.getThemeColor
|
||||
import com.habitrpg.common.habitica.extensions.loadImage
|
||||
import com.habitrpg.common.habitica.helpers.RecyclerViewState
|
||||
import com.habitrpg.common.habitica.helpers.setMarkdown
|
||||
|
|
@ -57,7 +59,7 @@ import kotlin.math.min
|
|||
class FullProfileActivity : BaseActivity() {
|
||||
private var blocks: List<String> = listOf()
|
||||
private var isModerator = false
|
||||
private var member: Member? = null
|
||||
private var member: MutableState<Member?> = mutableStateOf(null)
|
||||
|
||||
@Inject
|
||||
lateinit var inventoryRepository: InventoryRepository
|
||||
|
|
@ -78,7 +80,6 @@ class FullProfileActivity : BaseActivity() {
|
|||
private var attributeDetailsHidden = true
|
||||
private val attributeRows = ArrayList<TableRow>()
|
||||
private val dateFormatter = SimpleDateFormat.getDateInstance()
|
||||
private var avatarWithBars: AvatarWithBarsViewModel? = null
|
||||
private lateinit var binding: ActivityFullProfileBinding
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
|
@ -95,17 +96,13 @@ class FullProfileActivity : BaseActivity() {
|
|||
lifecycleScope.launch(ExceptionHandler.coroutine()) {
|
||||
refresh()
|
||||
}
|
||||
avatarWithBars = AvatarWithBarsViewModel(this, binding.avatarWithBars)
|
||||
|
||||
binding.avatarWithBars.root.setBackgroundColor(
|
||||
ContextCompat.getColor(
|
||||
this,
|
||||
R.color.transparent
|
||||
)
|
||||
)
|
||||
binding.avatarWithBars.hpBar.barBackgroundColor = getThemeColor(R.attr.colorWindowBackground)
|
||||
binding.avatarWithBars.xpBar.barBackgroundColor = getThemeColor(R.attr.colorWindowBackground)
|
||||
binding.avatarWithBars.mpBar.barBackgroundColor = getThemeColor(R.attr.colorWindowBackground)
|
||||
binding.avatarWithBars.setContent {
|
||||
HabiticaTheme {
|
||||
AppHeaderView(member.value) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
attributeRows.clear()
|
||||
binding.attributesCardView.setOnClickListener { toggleAttributeDetails() }
|
||||
|
|
@ -137,7 +134,7 @@ class FullProfileActivity : BaseActivity() {
|
|||
if (member != null) {
|
||||
updateView(member)
|
||||
}
|
||||
this@FullProfileActivity.member = member
|
||||
this@FullProfileActivity.member.value = member
|
||||
}
|
||||
invalidateOptionsMenu()
|
||||
}
|
||||
|
|
@ -149,7 +146,7 @@ class FullProfileActivity : BaseActivity() {
|
|||
if (member != null) {
|
||||
updateView(member)
|
||||
}
|
||||
this@FullProfileActivity.member = member
|
||||
this@FullProfileActivity.member.value = member
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
|
|
@ -169,17 +166,17 @@ class FullProfileActivity : BaseActivity() {
|
|||
}
|
||||
menu.setGroupVisible(R.id.admin_items, isModerator)
|
||||
if (isModerator) {
|
||||
menu.findItem(R.id.ban_user)?.title = getString(if (member?.authentication?.blocked == true) {
|
||||
menu.findItem(R.id.ban_user)?.title = getString(if (member.value?.authentication?.blocked == true) {
|
||||
R.string.unban_user
|
||||
} else {
|
||||
R.string.ban_user
|
||||
})
|
||||
menu.findItem(R.id.shadow_mute_user)?.title = getString(if (member?.flags?.chatShadowMuted == true) {
|
||||
menu.findItem(R.id.shadow_mute_user)?.title = getString(if (member.value?.flags?.chatShadowMuted == true) {
|
||||
R.string.unshadowmute_user
|
||||
} else {
|
||||
R.string.shadow_mute_user
|
||||
})
|
||||
menu.findItem(R.id.mute_user)?.title = getString(if (member?.flags?.chatRevoked == true) {
|
||||
menu.findItem(R.id.mute_user)?.title = getString(if (member.value?.flags?.chatRevoked == true) {
|
||||
R.string.unmute_user
|
||||
} else {
|
||||
R.string.mute_user
|
||||
|
|
@ -247,7 +244,7 @@ class FullProfileActivity : BaseActivity() {
|
|||
}
|
||||
|
||||
private fun muteUser() {
|
||||
val isMuted = member?.flags?.chatRevoked == true
|
||||
val isMuted = member.value?.flags?.chatRevoked == true
|
||||
val alert = HabiticaAlertDialog(this)
|
||||
if (isMuted) {
|
||||
alert.setTitle(R.string.mute_user_confirm)
|
||||
|
|
@ -256,7 +253,7 @@ class FullProfileActivity : BaseActivity() {
|
|||
}
|
||||
alert.addButton(R.string.yes, isPrimary = true, isDestructive = true) { _, _ ->
|
||||
lifecycleScope.launchCatching {
|
||||
member?.id?.let { socialRepository.updateMember(it, "flags.chatRevoked", !isMuted) }
|
||||
member.value?.id?.let { socialRepository.updateMember(it, "flags.chatRevoked", !isMuted) }
|
||||
refresh()
|
||||
invalidateOptionsMenu()
|
||||
}
|
||||
|
|
@ -265,7 +262,7 @@ class FullProfileActivity : BaseActivity() {
|
|||
}
|
||||
|
||||
private fun shadowMuteUser() {
|
||||
val isBanned = member?.flags?.chatShadowMuted == true
|
||||
val isBanned = member.value?.flags?.chatShadowMuted == true
|
||||
val alert = HabiticaAlertDialog(this)
|
||||
if (isBanned) {
|
||||
alert.setTitle(R.string.shadowmute_user_confirm)
|
||||
|
|
@ -274,7 +271,7 @@ class FullProfileActivity : BaseActivity() {
|
|||
}
|
||||
alert.addButton(R.string.yes, isPrimary = true, isDestructive = true) { _, _ ->
|
||||
lifecycleScope.launchCatching {
|
||||
member?.id?.let { socialRepository.updateMember(it, "flags.chatShadowMuted", !isBanned) }
|
||||
member.value?.id?.let { socialRepository.updateMember(it, "flags.chatShadowMuted", !isBanned) }
|
||||
refresh()
|
||||
invalidateOptionsMenu()
|
||||
}
|
||||
|
|
@ -283,7 +280,7 @@ class FullProfileActivity : BaseActivity() {
|
|||
}
|
||||
|
||||
private fun banUser() {
|
||||
val isBanned = member?.authentication?.blocked == true
|
||||
val isBanned = member.value?.authentication?.blocked == true
|
||||
val alert = HabiticaAlertDialog(this)
|
||||
if (isBanned) {
|
||||
alert.setTitle(R.string.ban_user_confirm)
|
||||
|
|
@ -292,7 +289,7 @@ class FullProfileActivity : BaseActivity() {
|
|||
}
|
||||
alert.addButton(R.string.yes, isPrimary = true, isDestructive = true) { _, _ ->
|
||||
lifecycleScope.launchCatching {
|
||||
member?.id?.let { socialRepository.updateMember(it, "auth.blocked", !isBanned) }
|
||||
member.value?.id?.let { socialRepository.updateMember(it, "auth.blocked", !isBanned) }
|
||||
refresh()
|
||||
invalidateOptionsMenu()
|
||||
}
|
||||
|
|
@ -361,8 +358,6 @@ class FullProfileActivity : BaseActivity() {
|
|||
}
|
||||
binding.totalCheckinsView.text = user.loginIncentives.toString()
|
||||
|
||||
avatarWithBars?.updateData(user)
|
||||
|
||||
val status = mutableListOf<String>()
|
||||
if (user.authentication?.blocked == true) status.add("Banned")
|
||||
if (user.flags?.chatShadowMuted == true) status.add("Shadow Muted")
|
||||
|
|
|
|||
|
|
@ -242,7 +242,10 @@ open class MainActivity : BaseActivity(), SnackbarActivity {
|
|||
|
||||
binding.content.headerView.setContent {
|
||||
HabiticaTheme {
|
||||
AppHeaderView(viewModel.userViewModel) {
|
||||
val user by viewModel.user.observeAsState(null)
|
||||
val teamPlan by viewModel.userViewModel.currentTeamPlan.collectAsState(null)
|
||||
val teamPlanMembers by viewModel.userViewModel.currentTeamPlanMembers.observeAsState()
|
||||
AppHeaderView(user, teamPlan, teamPlanMembers) {
|
||||
showAsBottomSheet { onClose ->
|
||||
val group by viewModel.userViewModel.currentTeamPlanGroup.collectAsState(null)
|
||||
val members by viewModel.userViewModel.currentTeamPlanMembers.observeAsState()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.habitrpg.android.habitica.ui.activities
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Bundle
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.viewModels
|
||||
|
|
@ -24,8 +25,10 @@ import androidx.compose.runtime.livedata.observeAsState
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.shadow
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
|
|
@ -110,8 +113,11 @@ fun TaskSummaryView(viewModel: TaskSummaryViewModel) {
|
|||
val task by viewModel.task.observeAsState()
|
||||
val titleModifier = Modifier.padding(top = 30.dp)
|
||||
val textModifier = Modifier.padding(top = 4.dp)
|
||||
val activity = LocalContext.current as? Activity
|
||||
|
||||
if (task != null) {
|
||||
val darkestColor = HabiticaTheme.colors.textPrimaryFor(task)
|
||||
val topTextColor = if ((task?.value ?: 0.0) >= -20) colorResource(task?.extraDarkTaskColor ?: R.color.white) else Color.White
|
||||
val systemUiController = rememberSystemUiController()
|
||||
val statusBarColor = HabiticaTheme.colors.primaryBackgroundFor(task)
|
||||
val lightestColor = HabiticaTheme.colors.contentBackgroundFor(task)
|
||||
|
|
@ -127,6 +133,10 @@ fun TaskSummaryView(viewModel: TaskSummaryViewModel) {
|
|||
) {
|
||||
Button(
|
||||
onClick = {
|
||||
if (activity != null) {
|
||||
activity.finish()
|
||||
return@Button
|
||||
}
|
||||
MainNavigationController.navigateBack()
|
||||
},
|
||||
colors = ButtonDefaults.textButtonColors(contentColor = darkestColor),
|
||||
|
|
@ -136,7 +146,7 @@ fun TaskSummaryView(viewModel: TaskSummaryViewModel) {
|
|||
painterResource(R.drawable.arrow_back),
|
||||
stringResource(R.string.action_back),
|
||||
colorFilter = ColorFilter.tint(
|
||||
darkestColor
|
||||
topTextColor
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
@ -144,7 +154,7 @@ fun TaskSummaryView(viewModel: TaskSummaryViewModel) {
|
|||
stringResource(R.string.task_summary),
|
||||
fontSize = 18.sp,
|
||||
fontWeight = FontWeight.Medium,
|
||||
color = darkestColor,
|
||||
color = topTextColor,
|
||||
modifier = Modifier.padding(start = 0.dp)
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ class ShopRecyclerAdapter : androidx.recyclerview.widget.RecyclerView.Adapter<an
|
|||
val view = parent.inflate(R.layout.row_shopitem)
|
||||
val viewHolder = ShopItemViewHolder(view)
|
||||
viewHolder.shopIdentifier = shopIdentifier
|
||||
viewHolder
|
||||
viewHolder.onNeedsRefresh = onNeedsRefresh
|
||||
viewHolder
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,7 +113,8 @@ fun AvatarOverviewView(userViewModel: MainUserViewModel,
|
|||
verticalAlignment = Alignment.CenterVertically) {
|
||||
Text(
|
||||
stringResource(R.string.avatar_size),
|
||||
style = HabiticaTheme.typography.subtitle2
|
||||
style = HabiticaTheme.typography.subtitle2,
|
||||
color = HabiticaTheme.colors.textSecondary
|
||||
)
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
SegmentedControl(items = listOf(stringResource(R.string.avatar_size_slim), stringResource(R.string.avatar_size_broad
|
||||
|
|
@ -127,11 +128,13 @@ fun AvatarOverviewView(userViewModel: MainUserViewModel,
|
|||
.padding(horizontal = 12.dp)
|
||||
.padding(top = 15.dp),
|
||||
verticalAlignment = Alignment.CenterVertically) {
|
||||
Text(stringResource(R.string.equipped), style = HabiticaTheme.typography.subtitle2)
|
||||
Text(stringResource(R.string.equipped), style = HabiticaTheme.typography.subtitle2,
|
||||
color = HabiticaTheme.colors.textSecondary)
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
Text(
|
||||
stringResource(R.string.equip_automatically),
|
||||
style = HabiticaTheme.typography.body2
|
||||
style = HabiticaTheme.typography.body2,
|
||||
color = HabiticaTheme.colors.textPrimary
|
||||
)
|
||||
Switch(checked = user?.preferences?.autoEquip == true, onCheckedChange = {
|
||||
userViewModel.updateUser("preferences.autoEquip", it)
|
||||
|
|
@ -148,12 +151,14 @@ fun AvatarOverviewView(userViewModel: MainUserViewModel,
|
|||
) {
|
||||
Text(
|
||||
stringResource(R.string.costume),
|
||||
style = HabiticaTheme.typography.subtitle2
|
||||
style = HabiticaTheme.typography.subtitle2,
|
||||
color = HabiticaTheme.colors.textSecondary
|
||||
)
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
Text(
|
||||
stringResource(R.string.wear_costume),
|
||||
style = HabiticaTheme.typography.body2
|
||||
style = HabiticaTheme.typography.body2,
|
||||
color = HabiticaTheme.colors.textPrimary
|
||||
)
|
||||
Switch(checked = user?.preferences?.costume == true, onCheckedChange = {
|
||||
userViewModel.updateUser("preferences.costume", it)
|
||||
|
|
|
|||
|
|
@ -225,9 +225,9 @@ open class ShopFragment : BaseMainFragment<FragmentRefreshRecyclerviewBinding>()
|
|||
}
|
||||
Shop.SEASONAL_SHOP -> {
|
||||
shop1.categories.sortWith(
|
||||
compareBy<ShopCategory> { it.items.size != 1 }
|
||||
.thenBy { it.items.firstOrNull()?.currency != "gold" }
|
||||
compareBy<ShopCategory> { it.items.firstOrNull()?.currency != "gold" }
|
||||
.thenByDescending { it.items.firstOrNull()?.event?.end }
|
||||
.thenBy { it.items.firstOrNull()?.locked }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import androidx.compose.ui.text.font.FontWeight
|
|||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.google.android.material.composethemeadapter.createMdcTheme
|
||||
import com.google.accompanist.themeadapter.material.createMdcTheme
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.models.tasks.Task
|
||||
import com.habitrpg.common.habitica.extensions.getThemeColor
|
||||
|
|
@ -27,7 +27,7 @@ fun HabiticaTheme(
|
|||
) {
|
||||
val context = LocalContext.current
|
||||
val layoutDirection = LocalLayoutDirection.current
|
||||
val (colors, _, shapes) = createMdcTheme(
|
||||
val (colors, _, _) = createMdcTheme(
|
||||
context = context,
|
||||
layoutDirection = layoutDirection,
|
||||
setTextColors = true
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import android.graphics.drawable.BitmapDrawable
|
|||
import android.text.method.LinkMovementMethod
|
||||
import android.view.View
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.databinding.ChatItemBinding
|
||||
|
|
@ -211,7 +212,15 @@ class ChatRecyclerMessageViewHolder(
|
|||
}
|
||||
|
||||
if ((chatMessage?.flagCount ?: 0) > 0) {
|
||||
|
||||
binding.flagCountTextview.text = context.getString(R.string.message_flagged, (chatMessage?.flagCount ?: 0))
|
||||
binding.flagCountTextview.isVisible = true
|
||||
if (chatMessage?.flagCount == 1) {
|
||||
binding.flagCountTextview.setTextColor(ContextCompat.getColor(context, R.color.text_orange))
|
||||
} else {
|
||||
binding.flagCountTextview.setTextColor(ContextCompat.getColor(context, R.color.text_red))
|
||||
}
|
||||
} else {
|
||||
binding.flagCountTextview.isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import com.habitrpg.android.habitica.databinding.PartyMemberBinding
|
|||
import com.habitrpg.android.habitica.models.members.Member
|
||||
import com.habitrpg.android.habitica.models.user.Stats
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaIconsHelper
|
||||
import com.habitrpg.android.habitica.ui.views.getTranslatedClassName
|
||||
|
||||
class GroupMemberViewHolder(itemView: View) : androidx.recyclerview.widget.RecyclerView.ViewHolder(itemView), PopupMenu.OnMenuItemClickListener {
|
||||
private val binding = PartyMemberBinding.bind(itemView)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import android.view.ViewGroup
|
|||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
|
|
@ -63,7 +64,9 @@ abstract class ChecklistedViewHolder(
|
|||
if (isLocked) {
|
||||
this.checkmarkView.visibility = View.GONE
|
||||
this.lockView.visibility = View.VISIBLE
|
||||
lockView.drawable.setTint(ContextCompat.getColor(context, if (data.isDue == true || data.type == TaskType.TODO) data.extraExtraDarkTaskColor else R.color.text_dimmed))
|
||||
val icon = AppCompatResources.getDrawable(context, R.drawable.task_lock)
|
||||
icon?.setTint(ContextCompat.getColor(context, if (data.isDue == true || data.type == TaskType.TODO) data.extraExtraDarkTaskColor else R.color.text_dimmed))
|
||||
lockView.setImageDrawable(icon)
|
||||
} else {
|
||||
this.checkmarkView.visibility = if (completed) View.VISIBLE else View.GONE
|
||||
checkmarkView.drawable.setTint(ContextCompat.getColor(context, R.color.gray_400))
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.habitrpg.android.habitica.ui.views
|
||||
|
||||
import android.content.res.Resources
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
|
|
@ -26,9 +27,6 @@ import androidx.compose.foundation.shape.CircleShape
|
|||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
|
|
@ -39,16 +37,27 @@ import androidx.compose.ui.res.colorResource
|
|||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.core.os.bundleOf
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.helpers.MainNavigationController
|
||||
import com.habitrpg.android.habitica.models.TeamPlan
|
||||
import com.habitrpg.android.habitica.models.auth.LocalAuthentication
|
||||
import com.habitrpg.android.habitica.models.members.Member
|
||||
import com.habitrpg.android.habitica.models.user.Authentication
|
||||
import com.habitrpg.android.habitica.models.user.Profile
|
||||
import com.habitrpg.android.habitica.models.user.Stats
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
|
||||
import com.habitrpg.shared.habitica.models.Avatar
|
||||
import com.habitrpg.shared.habitica.models.AvatarStats
|
||||
import kotlin.random.Random
|
||||
|
||||
@Composable
|
||||
fun UserLevelText(user: User) {
|
||||
fun UserLevelText(user: Avatar) {
|
||||
val text = if (user.hasClass) {
|
||||
stringResource(
|
||||
id = R.string.user_level_with_class,
|
||||
|
|
@ -68,14 +77,23 @@ fun UserLevelText(user: User) {
|
|||
)
|
||||
}
|
||||
|
||||
fun AvatarStats.getTranslatedClassName(resources: Resources): String {
|
||||
return when (habitClass) {
|
||||
Stats.HEALER -> resources.getString(R.string.healer)
|
||||
Stats.ROGUE -> resources.getString(R.string.rogue)
|
||||
Stats.WARRIOR -> resources.getString(R.string.warrior)
|
||||
Stats.MAGE -> resources.getString(R.string.mage)
|
||||
else -> resources.getString(R.string.warrior)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun AppHeaderView(
|
||||
viewModel: MainUserViewModel,
|
||||
user: Avatar?,
|
||||
teamPlan: TeamPlan? = null,
|
||||
teamPlanMembers: List<Member>? = null,
|
||||
onMemberRowClicked: () -> Unit
|
||||
) {
|
||||
val user by viewModel.user.observeAsState(null)
|
||||
val teamPlan by viewModel.currentTeamPlan.collectAsState(null)
|
||||
val teamPlanMembers by viewModel.currentTeamPlanMembers.observeAsState()
|
||||
Column {
|
||||
Row {
|
||||
ComposableAvatarView(
|
||||
|
|
@ -107,6 +125,7 @@ fun AppHeaderView(
|
|||
maxValue = user?.stats?.toNextLevel?.toDouble() ?: 0.0,
|
||||
displayCompact = teamPlan != null,
|
||||
abbreviateValue = false,
|
||||
abbreviateMax = false,
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
if (user?.hasClass == true) {
|
||||
|
|
@ -114,10 +133,13 @@ fun AppHeaderView(
|
|||
icon = HabiticaIconsHelper.imageOfMagic(),
|
||||
label = stringResource(R.string.MP_default),
|
||||
color = colorResource(R.color.mpColor),
|
||||
value = user?.stats?.mp ?: 0.0,
|
||||
maxValue = user?.stats?.maxMP?.toDouble() ?: 0.0,
|
||||
value = user.stats?.mp ?: 0.0,
|
||||
maxValue = user.stats?.maxMP?.toDouble() ?: 0.0,
|
||||
displayCompact = teamPlan != null,
|
||||
modifier = Modifier.weight(1f)
|
||||
abbreviateValue = false,
|
||||
abbreviateMax = false,
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.clickable {
|
||||
MainNavigationController.navigate(R.id.skillsFragment)
|
||||
}
|
||||
|
|
@ -173,18 +195,18 @@ fun AppHeaderView(
|
|||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 12.dp, start = 12.dp, end = 12.dp)
|
||||
.height(40.dp)
|
||||
.width(72.dp)
|
||||
.clip(MaterialTheme.shapes.medium)
|
||||
.background(
|
||||
colorResource(R.color.window_background)
|
||||
)
|
||||
.padding(top = 12.dp, start = 12.dp, end = 12.dp)
|
||||
.clickable {
|
||||
onMemberRowClicked()
|
||||
}
|
||||
) {
|
||||
for (member in teamPlanMembers?.filter { it.id != user?.id }?.sortedBy { it.authentication?.timestamps?.lastLoggedIn }?.take(6) ?: emptyList()) {
|
||||
for (member in teamPlanMembers?.filter { it.id != user?.id }?.sortedByDescending { it.authentication?.timestamps?.lastLoggedIn }?.take(6) ?: emptyList()) {
|
||||
Box(modifier = Modifier
|
||||
.clip(CircleShape)
|
||||
.size(26.dp)
|
||||
|
|
@ -205,21 +227,52 @@ fun AppHeaderView(
|
|||
ClassIcon(className = user?.stats?.habitClass, hasClass = user?.hasClass ?: false, modifier = Modifier.padding(4.dp))
|
||||
user?.let { UserLevelText(it) }
|
||||
Spacer(Modifier.weight(1f))
|
||||
if (user?.isSubscribed == true) {
|
||||
user?.hourglassCount?.toDouble()
|
||||
?.let {
|
||||
CurrencyText(
|
||||
"hourglasses",
|
||||
it,
|
||||
modifier = Modifier.padding(end = 12.dp).clickable {
|
||||
MainNavigationController.navigate(R.id.subscriptionPurchaseActivity)
|
||||
})
|
||||
}
|
||||
if (user is User && user.isSubscribed) {
|
||||
CurrencyText(
|
||||
"hourglasses",
|
||||
user.hourglassCount.toDouble(),
|
||||
modifier = Modifier
|
||||
.padding(end = 12.dp)
|
||||
.clickable {
|
||||
MainNavigationController.navigate(R.id.subscriptionPurchaseActivity)
|
||||
}, decimals = 0)
|
||||
}
|
||||
CurrencyText("gold", user?.stats?.gp ?: 0.0, modifier = Modifier.padding(end = 12.dp))
|
||||
CurrencyText("gold", user?.stats?.gp ?: 0.0, modifier = Modifier.padding(end = 12.dp), decimals = 0)
|
||||
CurrencyText("gems", user?.gemCount?.toDouble() ?: 0.0, modifier = Modifier.clickable {
|
||||
MainNavigationController.navigate(R.id.gemPurchaseActivity)
|
||||
})
|
||||
}, decimals = 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class UserProvider : PreviewParameterProvider<User> {
|
||||
override val values: Sequence<User>
|
||||
get() {
|
||||
val list = mutableListOf<User>()
|
||||
val member = User()
|
||||
member.profile = Profile()
|
||||
member.profile?.name = "User"
|
||||
member.authentication = Authentication()
|
||||
member.authentication?.localAuthentication = LocalAuthentication()
|
||||
member.authentication?.localAuthentication?.username = "username"
|
||||
member.stats = Stats()
|
||||
member.stats?.hp = Random.nextDouble()
|
||||
member.stats?.maxHealth = 50
|
||||
member.stats?.toNextLevel = Random.nextInt()
|
||||
member.stats?.exp =
|
||||
Random.nextDouble(until = (member.stats?.toNextLevel ?: 0).toDouble())
|
||||
member.stats?.maxMP = Random.nextInt()
|
||||
member.stats?.mp = Random.nextDouble(until = (member.stats?.maxMP ?: 0).toDouble())
|
||||
member.stats?.lvl = Random.nextInt()
|
||||
list.add(member)
|
||||
return list.asSequence()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview
|
||||
private fun Preview(@PreviewParameter(UserProvider::class) user: User) {
|
||||
AppHeaderView(user) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -77,6 +77,7 @@ private fun BottomSheetWrapper(
|
|||
val radius = 20.dp
|
||||
ModalBottomSheetLayout(
|
||||
sheetBackgroundColor = Color.Transparent,
|
||||
scrimColor = colorResource(R.color.content_background).copy(alpha = 0.3f),
|
||||
sheetState = modalBottomSheetState,
|
||||
sheetShape = RoundedCornerShape(topStart = radius, topEnd = radius),
|
||||
sheetContent = {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
package com.habitrpg.android.habitica.ui.views
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
|
||||
@Composable
|
||||
fun BuffIcon(buffed: Boolean?, modifier: Modifier = Modifier) {
|
||||
if (buffed == true) {
|
||||
Image(HabiticaIconsHelper.imageOfBuffIcon().asImageBitmap(), null, modifier = modifier)
|
||||
}
|
||||
}
|
||||
|
|
@ -23,12 +23,13 @@ fun CurrencyText(
|
|||
value: Double,
|
||||
modifier: Modifier = Modifier,
|
||||
decimals: Int = 2,
|
||||
minForAbbrevation: Int = 0
|
||||
minForAbbrevation: Int = 0,
|
||||
animated: Boolean = true
|
||||
) {
|
||||
val animatedValue = animateFloatAsState(
|
||||
val animatedValue = if (animated) animateFloatAsState(
|
||||
targetValue = value.toFloat(),
|
||||
animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec,
|
||||
).value
|
||||
).value else value.toFloat()
|
||||
Row(verticalAlignment = Alignment.CenterVertically, modifier = modifier) {
|
||||
when (currency) {
|
||||
"gold" -> HabiticaIconsHelper.imageOfGold()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.habitrpg.android.habitica.ui.views
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
|
|
@ -18,7 +17,6 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
|
|
@ -47,43 +45,36 @@ fun GroupPlanMemberList(
|
|||
) {
|
||||
LazyColumn {
|
||||
item {
|
||||
Text(stringResource(R.string.member_list),
|
||||
fontSize = 16.sp,
|
||||
Text(
|
||||
stringResource(R.string.member_list),
|
||||
fontSize = 16.sp,
|
||||
fontWeight = FontWeight.Medium,
|
||||
color = HabiticaTheme.colors.textTertiary,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = 20.dp)
|
||||
)
|
||||
)
|
||||
}
|
||||
for (member in members?.sortedWith(compareByDescending<Member> {
|
||||
group?.isLeader(
|
||||
it.id ?: ""
|
||||
)
|
||||
}.thenByDescending {
|
||||
group?.isManager(
|
||||
it.id ?: ""
|
||||
)
|
||||
}.thenBy { it.username }) ?: emptyList()) {
|
||||
item {
|
||||
val role = if (group?.isLeader(member.id ?: "") == true) {
|
||||
stringResource(R.string.owner)
|
||||
} else if (group?.isManager(member.id ?: "") == true) {
|
||||
stringResource(R.string.manager)
|
||||
} else {
|
||||
stringResource(R.string.member)
|
||||
|
||||
}
|
||||
MemberItem(
|
||||
member,
|
||||
role,
|
||||
onMemberClicked,
|
||||
onMoreClicked,
|
||||
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp)
|
||||
)
|
||||
for (member in members?.sortedByDescending { it.authentication?.timestamps?.lastLoggedIn }
|
||||
?: emptyList()) {
|
||||
item {
|
||||
val role = if (group?.isLeader(member.id ?: "") == true) {
|
||||
stringResource(R.string.owner)
|
||||
} else if (group?.isManager(member.id ?: "") == true) {
|
||||
stringResource(R.string.manager)
|
||||
} else {
|
||||
stringResource(R.string.member)
|
||||
}
|
||||
MemberItem(
|
||||
member,
|
||||
role,
|
||||
onMemberClicked,
|
||||
modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
@ -91,7 +82,6 @@ fun MemberItem(
|
|||
member: Member,
|
||||
role: String,
|
||||
onMemberClicked: (String) -> Unit,
|
||||
onMoreClicked: (Member) -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
Box(
|
||||
|
|
@ -107,10 +97,17 @@ fun MemberItem(
|
|||
horizontalArrangement = Arrangement.spacedBy(10.dp),
|
||||
modifier = Modifier.padding(8.dp)
|
||||
) {
|
||||
ComposableAvatarView(avatar = member, modifier = Modifier
|
||||
.padding(6.dp)
|
||||
.size(94.dp, 98.dp))
|
||||
Column(verticalArrangement = Arrangement.SpaceBetween, modifier = Modifier.height(104.dp).padding(end = 6.dp)) {
|
||||
ComposableAvatarView(
|
||||
avatar = member, modifier = Modifier
|
||||
.padding(6.dp)
|
||||
.size(94.dp, 98.dp)
|
||||
)
|
||||
Column(
|
||||
verticalArrangement = Arrangement.SpaceBetween,
|
||||
modifier = Modifier
|
||||
.height(104.dp)
|
||||
.padding(end = 6.dp)
|
||||
) {
|
||||
Text(
|
||||
member.displayName,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
|
|
@ -135,7 +132,12 @@ fun MemberItem(
|
|||
modifier = Modifier.size(18.dp)
|
||||
)
|
||||
BuffIcon(member.stats?.isBuffed)
|
||||
CurrencyText(currency = "gold", value = member.stats?.gp ?: 0.0)
|
||||
CurrencyText(
|
||||
currency = "gold",
|
||||
value = (member.stats?.gp) ?: 0.0,
|
||||
decimals = 0,
|
||||
animated = false
|
||||
)
|
||||
}
|
||||
LabeledBar(
|
||||
color = colorResource(R.color.hpColor),
|
||||
|
|
@ -143,7 +145,8 @@ fun MemberItem(
|
|||
value = member.stats?.hp ?: 0.0,
|
||||
maxValue = (member.stats?.maxHealth ?: 0).toDouble(),
|
||||
displayCompact = true,
|
||||
barHeight = 5.dp
|
||||
barHeight = 5.dp,
|
||||
animated = false
|
||||
)
|
||||
LabeledBar(
|
||||
color = colorResource(R.color.xpColor),
|
||||
|
|
@ -151,7 +154,8 @@ fun MemberItem(
|
|||
value = member.stats?.exp ?: 0.0,
|
||||
maxValue = (member.stats?.toNextLevel ?: 0).toDouble(),
|
||||
displayCompact = true,
|
||||
barHeight = 5.dp
|
||||
barHeight = 5.dp,
|
||||
animated = false
|
||||
)
|
||||
if (member.hasClass) {
|
||||
LabeledBar(
|
||||
|
|
@ -160,7 +164,8 @@ fun MemberItem(
|
|||
value = member.stats?.mp ?: 0.0,
|
||||
maxValue = (member.stats?.maxMP ?: 0).toDouble(),
|
||||
displayCompact = true,
|
||||
barHeight = 5.dp
|
||||
barHeight = 5.dp,
|
||||
animated = false
|
||||
)
|
||||
}
|
||||
Row(horizontalArrangement = Arrangement.SpaceBetween) {
|
||||
|
|
@ -181,13 +186,6 @@ fun MemberItem(
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun BuffIcon(buffed: Boolean?, modifier: Modifier = Modifier) {
|
||||
if (buffed == true) {
|
||||
Image(HabiticaIconsHelper.imageOfBuffIcon().asImageBitmap(), null, modifier = modifier)
|
||||
}
|
||||
}
|
||||
|
||||
private class MemberProvider : PreviewParameterProvider<Member> {
|
||||
override val values: Sequence<Member>
|
||||
get() {
|
||||
|
|
@ -217,5 +215,5 @@ private class MemberProvider : PreviewParameterProvider<Member> {
|
|||
@Composable
|
||||
@Preview
|
||||
private fun Preview(@PreviewParameter(MemberProvider::class) member: Member) {
|
||||
MemberItem(member = member, role = "Manager", onMemberClicked = {}, onMoreClicked = {})
|
||||
MemberItem(member = member, role = "Manager", onMemberClicked = {})
|
||||
}
|
||||
|
|
@ -2,7 +2,8 @@ package com.habitrpg.android.habitica.ui.views
|
|||
|
||||
import android.graphics.Bitmap
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.animation.core.animateIntAsState
|
||||
import androidx.compose.animation.core.spring
|
||||
import androidx.compose.animation.slideInHorizontally
|
||||
import androidx.compose.animation.slideOutHorizontally
|
||||
import androidx.compose.foundation.Image
|
||||
|
|
@ -16,7 +17,6 @@ import androidx.compose.foundation.layout.padding
|
|||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.LinearProgressIndicator
|
||||
import androidx.compose.material.ProgressIndicatorDefaults
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
|
|
@ -50,14 +50,15 @@ fun LabeledBar(
|
|||
barHeight: Dp = 8.dp,
|
||||
disabled: Boolean = false,
|
||||
abbreviateValue: Boolean = true,
|
||||
abbreviateMax: Boolean = true
|
||||
abbreviateMax: Boolean = true,
|
||||
animated: Boolean = true
|
||||
) {
|
||||
val cleanedMaxValue = java.lang.Double.max(1.0, maxValue)
|
||||
|
||||
val animatedValue = animateFloatAsState(
|
||||
targetValue = value.toFloat(),
|
||||
animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec,
|
||||
).value
|
||||
val animatedValue = if (animated) animateIntAsState(
|
||||
targetValue = value.toInt(),
|
||||
animationSpec = spring()
|
||||
).value else value.toInt()
|
||||
val formatter = NumberFormat.getNumberInstance()
|
||||
formatter.minimumFractionDigits = 0
|
||||
formatter.maximumFractionDigits = 2
|
||||
|
|
@ -92,7 +93,7 @@ fun LabeledBar(
|
|||
if (!disabled) {
|
||||
val currentValueText = if (abbreviateValue) NumberAbbreviator.abbreviate(
|
||||
LocalContext.current,
|
||||
animatedValue,
|
||||
animatedValue.toFloat(),
|
||||
0
|
||||
) else formatter.format(animatedValue)
|
||||
val maxValueText = if (abbreviateMax) NumberAbbreviator.abbreviate(
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ fun SegmentedControl(
|
|||
onItemSelection: (selectedItemIndex: Int) -> Unit
|
||||
) {
|
||||
val selectedIndex = remember { mutableStateOf(defaultSelectedItemIndex) }
|
||||
val color = MaterialTheme.colors.primary
|
||||
val color = MaterialTheme.colors.surface
|
||||
Row(
|
||||
modifier = Modifier
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ class SubscriptionDetailsView : LinearLayout {
|
|||
val now = LocalDate.now()
|
||||
val nextHourglassDate = LocalDate.now().plusMonths(plan.monthsUntilNextHourglass.toLong())
|
||||
val format = if (now.year != nextHourglassDate.year) {
|
||||
"MM YYYY"
|
||||
"MMM YYYY"
|
||||
} else {
|
||||
"MMMM"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ buildscript {
|
|||
app_version_name = ''
|
||||
app_version_code = 0
|
||||
|
||||
accompanist_version = '0.28.0'
|
||||
amplitude_version = '1.5.1'
|
||||
appcompat_version = '1.5.1'
|
||||
coil_version = '2.2.2'
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
New in 4.0.3:
|
||||
-Habitica has a brand new WearOS app for smart watches!
|
||||
-Reminders for tasks done the previous day will show again
|
||||
-Group Plan subscribers can switch on displaying shared tasks from Settings
|
||||
-Pet category labels show again
|
||||
-Newly designed Backgrounds section
|
||||
-Ability to filter, preview, and pin Backgrounds
|
||||
-New bottom sheet designs in Items, Pets & Mounts, and Filters
|
||||
-New Day Start Adjustment interface
|
||||
-Improvements to payment and subscription handling
|
||||
New in 4.1:
|
||||
-You can view, complete, assign, and add tasks to your Group Plan’s shared task board!
|
||||
-Tap your name on a task screen to switch to different task boards
|
||||
-Subscription details will show extra months and when you’ll get your next Hourglass
|
||||
-More intuitive system notification settings
|
||||
-Audio will be controlled by media volume now
|
||||
-Task details are now tinted based on task health
|
||||
-Fixed a bug that caused tasks to shuffle around
|
||||
-Monthly Dailies should recur more consistently now
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
NAME=4.1
|
||||
CODE=4841
|
||||
CODE=4891
|
||||
|
|
@ -16,6 +16,7 @@ class User: Avatar {
|
|||
override val currentPet: String?
|
||||
get() = items?.currentPet
|
||||
override var sleep: Boolean = false
|
||||
override var id: String? = null
|
||||
override var balance: Double = 0.0
|
||||
@Json(ignore = true)
|
||||
override var authentication: AvatarAuthentication? = null
|
||||
|
|
|
|||
Loading…
Reference in a new issue