mirror of
https://github.com/sudoxnym/habitica-android.git
synced 2026-04-14 19:56:32 +00:00
Display assigned avatars
This commit is contained in:
parent
dc33e91010
commit
d32fe481e4
26 changed files with 162 additions and 69 deletions
|
|
@ -1270,6 +1270,8 @@
|
|||
<string name="edit_assignees">Edit assignees</string>
|
||||
<string name="assign_to">Assign to...</string>
|
||||
<string name="promote_to_manager">Promote to Manager</string>
|
||||
<string name="manager">Manager</string>
|
||||
<string name="member_list">Member List</string>
|
||||
<plurals name="you_x_others">
|
||||
<item quantity="zero">You</item>
|
||||
<item quantity="one">You, %d other</item>
|
||||
|
|
|
|||
|
|
@ -119,4 +119,5 @@ interface SocialRepository : BaseRepository {
|
|||
fun getGroupMembership(id: String): Flow<GroupMembership?>
|
||||
fun getGroupMemberships(): Flow<List<GroupMembership>>
|
||||
suspend fun blockMember(userID: String): List<String>?
|
||||
fun getMember(userID: String?): Flow<Member?>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,10 @@ class SocialRepositoryImpl(
|
|||
return apiClient.blockMember(userID)
|
||||
}
|
||||
|
||||
override fun getMember(userID: String?): Flow<Member?> {
|
||||
return localRepository.getMember(userID)
|
||||
}
|
||||
|
||||
override fun getGroupMembership(id: String) = localRepository.getGroupMembership(userID, id)
|
||||
|
||||
override fun getGroupMemberships(): Flow<List<GroupMembership>> {
|
||||
|
|
|
|||
|
|
@ -54,4 +54,5 @@ interface SocialLocalRepository : BaseLocalRepository {
|
|||
page: Int
|
||||
)
|
||||
fun saveInboxConversations(userID: String, conversations: List<InboxConversation>)
|
||||
fun getMember(userID: String?): Flow<Member?>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,6 +102,15 @@ class RealmSocialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm)
|
|||
}
|
||||
}
|
||||
|
||||
override fun getMember(userID: String?): Flow<Member?> {
|
||||
return realm.where(Member::class.java)
|
||||
.equalTo("id", userID)
|
||||
.findAll()
|
||||
.toFlow()
|
||||
.filter { member -> member.isLoaded && member.isValid }
|
||||
.map { member -> member.firstOrNull() }
|
||||
}
|
||||
|
||||
override fun saveGroupMemberships(userID: String?, memberships: List<GroupMembership>) {
|
||||
save(memberships)
|
||||
if (userID != null) {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ class BuyRewardUseCase @Inject
|
|||
constructor(
|
||||
private val taskRepository: TaskRepository,
|
||||
private val soundManager: SoundManager,
|
||||
) : FlowUseCase<BuyRewardUseCase.RequestValues, TaskScoringResult?>() {
|
||||
) : UseCase<BuyRewardUseCase.RequestValues, TaskScoringResult?>() {
|
||||
|
||||
override suspend fun run(requestValues: RequestValues): TaskScoringResult? {
|
||||
val response = taskRepository.taskChecked(requestValues.user, requestValues.task, false, false, requestValues.notifyFunc)
|
||||
|
|
@ -23,5 +23,5 @@ constructor(
|
|||
internal val user: User?,
|
||||
val task: Task,
|
||||
val notifyFunc: (TaskScoringResult) -> Unit
|
||||
) : FlowUseCase.RequestValues
|
||||
) : UseCase.RequestValues
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import com.habitrpg.android.habitica.models.user.User
|
|||
import com.habitrpg.android.habitica.ui.activities.ClassSelectionActivity
|
||||
import javax.inject.Inject
|
||||
|
||||
class CheckClassSelectionUseCase @Inject constructor() : FlowUseCase<CheckClassSelectionUseCase.RequestValues, Unit>() {
|
||||
class CheckClassSelectionUseCase @Inject constructor() : UseCase<CheckClassSelectionUseCase.RequestValues, Unit>() {
|
||||
|
||||
override suspend fun run(requestValues: RequestValues) {
|
||||
val user = requestValues.user
|
||||
|
|
@ -42,5 +42,5 @@ class CheckClassSelectionUseCase @Inject constructor() : FlowUseCase<CheckClassS
|
|||
val isInitialSelection: Boolean,
|
||||
val currentClass: String?,
|
||||
val activity: Activity
|
||||
) : FlowUseCase.RequestValues
|
||||
) : UseCase.RequestValues
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import javax.inject.Inject
|
|||
|
||||
class DisplayItemDropUseCase @Inject
|
||||
constructor(private val soundManager: SoundManager):
|
||||
FlowUseCase<DisplayItemDropUseCase.RequestValues, Unit>() {
|
||||
UseCase<DisplayItemDropUseCase.RequestValues, Unit>() {
|
||||
|
||||
override suspend fun run(requestValues: RequestValues) {
|
||||
val data = requestValues.data
|
||||
|
|
@ -49,5 +49,5 @@ constructor(private val soundManager: SoundManager):
|
|||
val context: AppCompatActivity,
|
||||
val snackbarTargetView: ViewGroup,
|
||||
val showQuestItems: Boolean
|
||||
) : FlowUseCase.RequestValues
|
||||
) : UseCase.RequestValues
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import javax.inject.Inject
|
|||
class FeedPetUseCase @Inject
|
||||
constructor(
|
||||
private val inventoryRepository: InventoryRepository,
|
||||
) : FlowUseCase<FeedPetUseCase.RequestValues, FeedResponse?>() {
|
||||
) : UseCase<FeedPetUseCase.RequestValues, FeedResponse?>() {
|
||||
override suspend fun run(requestValues: FeedPetUseCase.RequestValues): FeedResponse? {
|
||||
val feedResponse = inventoryRepository.feedPet(requestValues.pet, requestValues.food)
|
||||
(requestValues.context as? SnackbarActivity)?.showSnackbar(content = feedResponse?.message)
|
||||
|
|
@ -77,5 +77,5 @@ constructor(
|
|||
}
|
||||
|
||||
class RequestValues(val pet: Pet, val food: Food, val context: Context) :
|
||||
FlowUseCase.RequestValues
|
||||
UseCase.RequestValues
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import javax.inject.Inject
|
|||
|
||||
class HatchPetUseCase @Inject
|
||||
constructor(
|
||||
private val inventoryRepository: InventoryRepository) : FlowUseCase<HatchPetUseCase.RequestValues, Items?>() {
|
||||
private val inventoryRepository: InventoryRepository) : UseCase<HatchPetUseCase.RequestValues, Items?>() {
|
||||
override suspend fun run(requestValues: RequestValues): Items? {
|
||||
return inventoryRepository.hatchPet(requestValues.egg, requestValues.potion) {
|
||||
val petWrapper = View.inflate(requestValues.context, R.layout.pet_imageview, null) as? FrameLayout
|
||||
|
|
@ -52,5 +52,5 @@ constructor(
|
|||
}
|
||||
}
|
||||
|
||||
class RequestValues(val potion: HatchingPotion, val egg: Egg, val context: Context) : FlowUseCase.RequestValues
|
||||
class RequestValues(val potion: HatchingPotion, val egg: Egg, val context: Context) : UseCase.RequestValues
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class LevelUpUseCase @Inject
|
|||
constructor(
|
||||
private val soundManager: SoundManager,
|
||||
private val checkClassSelectionUseCase: CheckClassSelectionUseCase
|
||||
) : FlowUseCase<LevelUpUseCase.RequestValues, Stats?>() {
|
||||
) : UseCase<LevelUpUseCase.RequestValues, Stats?>() {
|
||||
|
||||
override suspend fun run(requestValues: RequestValues): Stats? {
|
||||
soundManager.loadAndPlayAudio(SoundManager.SoundLevelUp)
|
||||
|
|
@ -99,7 +99,7 @@ constructor(
|
|||
val level: Int?,
|
||||
val activity: BaseActivity,
|
||||
val snackbarTargetView: ViewGroup
|
||||
) : FlowUseCase.RequestValues {
|
||||
) : UseCase.RequestValues {
|
||||
val newLevel: Int = level ?: 0
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class NotifyUserUseCase @Inject
|
|||
constructor(
|
||||
private val levelUpUseCase: LevelUpUseCase,
|
||||
private val userRepository: UserRepository
|
||||
) : FlowUseCase<NotifyUserUseCase.RequestValues, Stats?>() {
|
||||
) : UseCase<NotifyUserUseCase.RequestValues, Stats?>() {
|
||||
|
||||
override suspend fun run(requestValues: RequestValues): Stats? {
|
||||
if (requestValues.user == null) {
|
||||
|
|
@ -57,7 +57,7 @@ constructor(
|
|||
val questDamage: Double?,
|
||||
val hasLeveledUp: Boolean?,
|
||||
val level: Int?
|
||||
) : FlowUseCase.RequestValues
|
||||
) : UseCase.RequestValues
|
||||
|
||||
companion object {
|
||||
val formatter = NumberFormat.getInstance().apply {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package com.habitrpg.android.habitica.interactors
|
|||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
abstract class FlowUseCase<Q : FlowUseCase.RequestValues?, T> {
|
||||
abstract class UseCase<Q : UseCase.RequestValues?, T> {
|
||||
protected abstract suspend fun run(requestValues: Q): T
|
||||
suspend fun callInteractor(requestValues: Q): T {
|
||||
return withContext(Dispatchers.Main) {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@ import android.view.ViewGroup
|
|||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.activity.viewModels
|
||||
import androidx.appcompat.app.ActionBarDrawerToggle
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.view.children
|
||||
import androidx.drawerlayout.widget.DrawerLayout
|
||||
|
|
@ -240,7 +243,9 @@ open class MainActivity : BaseActivity(), SnackbarActivity {
|
|||
HabiticaTheme {
|
||||
AppHeaderView(viewModel.userViewModel) {
|
||||
showAsBottomSheet { onClose ->
|
||||
GroupPlanMemberList(it, {
|
||||
val group by viewModel.userViewModel.currentTeamPlanGroup.collectAsState(null)
|
||||
val members by viewModel.userViewModel.currentTeamPlanMembers.observeAsState()
|
||||
GroupPlanMemberList(members, group, {
|
||||
onClose()
|
||||
FullProfileActivity.open(it)
|
||||
}, { member ->
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import androidx.compose.material.MaterialTheme
|
|||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.ui.Alignment
|
||||
|
|
@ -42,25 +43,35 @@ import androidx.lifecycle.asLiveData
|
|||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.components.UserComponent
|
||||
import com.habitrpg.android.habitica.data.SocialRepository
|
||||
import com.habitrpg.android.habitica.data.TaskRepository
|
||||
import com.habitrpg.android.habitica.helpers.MainNavigationController
|
||||
import com.habitrpg.android.habitica.helpers.TaskDescriptionBuilder
|
||||
import com.habitrpg.android.habitica.models.members.Member
|
||||
import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.BaseViewModel
|
||||
import com.habitrpg.android.habitica.ui.views.CompletedAt
|
||||
import com.habitrpg.android.habitica.ui.views.UserRow
|
||||
import com.habitrpg.shared.habitica.models.tasks.TaskType
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import javax.inject.Inject
|
||||
|
||||
class TaskSummaryViewModel(val taskId: String) : BaseViewModel() {
|
||||
@Inject
|
||||
lateinit var taskRespository: TaskRepository
|
||||
@Inject
|
||||
lateinit var socialRepository: SocialRepository
|
||||
|
||||
val task = taskRespository.getTask(taskId).asLiveData()
|
||||
|
||||
override fun inject(component: UserComponent) {
|
||||
component.inject(this)
|
||||
}
|
||||
|
||||
fun getMember(userID: String?): Flow<Member?> {
|
||||
return socialRepository.getMember(userID)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class Factory(private val taskID: String) : ViewModelProvider.Factory {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
|
|
@ -230,8 +241,9 @@ fun TaskSummaryView(viewModel: TaskSummaryViewModel) {
|
|||
modifier = titleModifier.padding(bottom = 4.dp)
|
||||
)
|
||||
for (item in task?.group?.assignedUsersDetail ?: emptyList()) {
|
||||
val member = viewModel.getMember(item.assignedUserID).collectAsState(null)
|
||||
UserRow(
|
||||
item.assignedUsername ?: "", Modifier
|
||||
item.assignedUsername ?: "", member.value, Modifier
|
||||
.padding(vertical = 4.dp)
|
||||
.background(
|
||||
colorResource(
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ object HabiticaTheme {
|
|||
contentBackgroundOffset = Color(context.getThemeColor(R.attr.colorContentBackgroundOffset)),
|
||||
textPrimary = Color(context.getThemeColor(R.attr.textColorPrimary)),
|
||||
textSecondary = Color(context.getThemeColor(R.attr.textColorSecondary)),
|
||||
textTertiary = Color(context.getThemeColor(R.attr.colorTertiary)),
|
||||
textTertiary = Color(ContextCompat.getColor(context, R.color.text_ternary)),
|
||||
textDimmed = Color(ContextCompat.getColor(context, R.color.text_dimmed)),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ 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.members.Member
|
||||
import com.habitrpg.android.habitica.models.user.User
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.MainUserViewModel
|
||||
|
||||
|
|
@ -72,7 +71,7 @@ fun UserLevelText(user: User) {
|
|||
@Composable
|
||||
fun AppHeaderView(
|
||||
viewModel: MainUserViewModel,
|
||||
onMemberRowClicked: (List<Member>) -> Unit
|
||||
onMemberRowClicked: () -> Unit
|
||||
) {
|
||||
val user by viewModel.user.observeAsState(null)
|
||||
val teamPlan by viewModel.currentTeamPlan.collectAsState(null)
|
||||
|
|
@ -181,7 +180,7 @@ fun AppHeaderView(
|
|||
colorResource(R.color.window_background)
|
||||
)
|
||||
.clickable {
|
||||
teamPlanMembers?.let { onMemberRowClicked(it) }
|
||||
onMemberRowClicked()
|
||||
}
|
||||
) {
|
||||
for (member in teamPlanMembers?.filter { it.id != user?.id }?.take(6) ?: emptyList()) {
|
||||
|
|
@ -205,11 +204,20 @@ fun AppHeaderView(
|
|||
ClassIcon(className = user?.stats?.habitClass, hasClass = user?.hasClass ?: false, modifier = Modifier.padding(4.dp))
|
||||
user?.let { UserLevelText(it) }
|
||||
Spacer(Modifier.weight(1f))
|
||||
user?.hourglassCount?.toDouble()
|
||||
?.let { CurrencyText("hourglasses", it, modifier = Modifier.padding(end = 12.dp)) }
|
||||
if (user?.isSubscribed == true) {
|
||||
user?.hourglassCount?.toDouble()
|
||||
?.let {
|
||||
CurrencyText(
|
||||
"hourglasses",
|
||||
it,
|
||||
modifier = Modifier.padding(end = 12.dp).clickable {
|
||||
MainNavigationController.navigate(R.id.subscriptionPurchaseActivity)
|
||||
})
|
||||
}
|
||||
}
|
||||
CurrencyText("gold", user?.stats?.gp ?: 0.0, modifier = Modifier.padding(end = 12.dp))
|
||||
CurrencyText("gems", user?.gemCount?.toDouble() ?: 0.0, modifier = Modifier.clickable {
|
||||
MainNavigationController.navigate(R.id.gemPurchaseActivity, bundleOf(Pair("openSubscription", false)))
|
||||
MainNavigationController.navigate(R.id.gemPurchaseActivity)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,21 +74,24 @@ private fun BottomSheetWrapper(
|
|||
val modalBottomSheetState = rememberModalBottomSheetState(ModalBottomSheetValue.Hidden)
|
||||
var isSheetOpened by remember { mutableStateOf(false) }
|
||||
|
||||
val radius = 20.dp
|
||||
ModalBottomSheetLayout(
|
||||
sheetBackgroundColor = Color.Transparent,
|
||||
sheetState = modalBottomSheetState,
|
||||
sheetShape = RoundedCornerShape(topStart = radius, topEnd = radius),
|
||||
sheetContent = {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 4.dp)
|
||||
.border(
|
||||
2.dp,
|
||||
colorResource(R.color.window_background),
|
||||
RoundedCornerShape(topStart = 12.dp, topEnd = 12.dp)
|
||||
RoundedCornerShape(topStart = radius, topEnd = radius)
|
||||
)
|
||||
.background(
|
||||
MaterialTheme.colors.background,
|
||||
RoundedCornerShape(topStart = 12.dp, topEnd = 12.dp)
|
||||
RoundedCornerShape(topStart = radius, topEnd = radius)
|
||||
)
|
||||
.padding(vertical = 8.dp)
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ fun CurrencyText(
|
|||
decimals: Int = 2,
|
||||
minForAbbrevation: Int = 0
|
||||
) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically, modifier = modifier) {
|
||||
when (currency) {
|
||||
"gold" -> HabiticaIconsHelper.imageOfGold()
|
||||
"gems" -> HabiticaIconsHelper.imageOfGem()
|
||||
|
|
@ -39,8 +39,7 @@ fun CurrencyText(
|
|||
else -> colorResource(R.color.text_primary)
|
||||
},
|
||||
fontSize = 12.sp,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
modifier = modifier
|
||||
fontWeight = FontWeight.SemiBold
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -14,18 +14,15 @@ import androidx.compose.foundation.layout.padding
|
|||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.TextButton
|
||||
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.Color
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
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.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
|
|
@ -34,24 +31,52 @@ import androidx.compose.ui.unit.sp
|
|||
import com.habitrpg.android.habitica.R
|
||||
import com.habitrpg.android.habitica.models.auth.LocalAuthentication
|
||||
import com.habitrpg.android.habitica.models.members.Member
|
||||
import com.habitrpg.android.habitica.models.social.Group
|
||||
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.ui.theme.HabiticaTheme
|
||||
import com.habitrpg.common.habitica.extensions.getThemeColor
|
||||
import kotlin.random.Random
|
||||
|
||||
@Composable
|
||||
fun GroupPlanMemberList(
|
||||
members: List<Member>,
|
||||
members: List<Member>?,
|
||||
group: Group?,
|
||||
onMemberClicked: (String) -> Unit,
|
||||
onMoreClicked: (Member) -> Unit
|
||||
) {
|
||||
LazyColumn {
|
||||
for (member in members) {
|
||||
item {
|
||||
Text(stringResource(R.string.member_list),
|
||||
fontSize = 16.sp,
|
||||
fontWeight = FontWeight.Medium,
|
||||
color = HabiticaTheme.colors.textTertiary,
|
||||
textAlign = TextAlign.Center,
|
||||
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)
|
||||
|
|
@ -64,6 +89,7 @@ fun GroupPlanMemberList(
|
|||
@Composable
|
||||
fun MemberItem(
|
||||
member: Member,
|
||||
role: String,
|
||||
onMemberClicked: (String) -> Unit,
|
||||
onMoreClicked: (Member) -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
|
|
@ -77,23 +103,14 @@ fun MemberItem(
|
|||
member.id?.let { onMemberClicked(it) }
|
||||
}
|
||||
) {
|
||||
TextButton(
|
||||
onClick = { onMoreClicked(member) }, modifier = Modifier
|
||||
.size(32.dp)
|
||||
.background(
|
||||
Color(LocalContext.current.getThemeColor(R.attr.colorAccent)),
|
||||
WobblyCircle
|
||||
)
|
||||
.align(Alignment.TopEnd)
|
||||
) {
|
||||
Image(painterResource(R.drawable.menu_messages), null)
|
||||
}
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||
modifier = Modifier.padding(14.dp)
|
||||
horizontalArrangement = Arrangement.spacedBy(10.dp),
|
||||
modifier = Modifier.padding(8.dp)
|
||||
) {
|
||||
ComposableAvatarView(avatar = member, modifier = Modifier.size(94.dp, 98.dp))
|
||||
Column(verticalArrangement = Arrangement.SpaceBetween, modifier = Modifier.height(100.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,
|
||||
|
|
@ -101,17 +118,16 @@ fun MemberItem(
|
|||
color = HabiticaTheme.colors.textPrimary
|
||||
)
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Text(
|
||||
member.formattedUsername ?: "",
|
||||
color = HabiticaTheme.colors.textSecondary
|
||||
color = HabiticaTheme.colors.textTertiary
|
||||
)
|
||||
Spacer(
|
||||
Modifier
|
||||
.weight(1.0f)
|
||||
.background(Color.Red)
|
||||
)
|
||||
ClassIcon(
|
||||
member.stats?.habitClass,
|
||||
|
|
@ -126,14 +142,16 @@ fun MemberItem(
|
|||
barColor = HabiticaTheme.colors.contentBackgroundOffset,
|
||||
value = member.stats?.hp ?: 0.0,
|
||||
maxValue = (member.stats?.maxHealth ?: 0).toDouble(),
|
||||
displayCompact = true
|
||||
displayCompact = true,
|
||||
barHeight = 5.dp
|
||||
)
|
||||
LabeledBar(
|
||||
color = colorResource(R.color.xpColor),
|
||||
barColor = HabiticaTheme.colors.contentBackgroundOffset,
|
||||
value = member.stats?.exp ?: 0.0,
|
||||
maxValue = (member.stats?.toNextLevel ?: 0).toDouble(),
|
||||
displayCompact = true
|
||||
displayCompact = true,
|
||||
barHeight = 5.dp
|
||||
)
|
||||
if (member.hasClass) {
|
||||
LabeledBar(
|
||||
|
|
@ -141,7 +159,8 @@ fun MemberItem(
|
|||
barColor = HabiticaTheme.colors.contentBackgroundOffset,
|
||||
value = member.stats?.mp ?: 0.0,
|
||||
maxValue = (member.stats?.maxMP ?: 0).toDouble(),
|
||||
displayCompact = true
|
||||
displayCompact = true,
|
||||
barHeight = 5.dp
|
||||
)
|
||||
}
|
||||
Row(horizontalArrangement = Arrangement.SpaceBetween) {
|
||||
|
|
@ -149,11 +168,12 @@ fun MemberItem(
|
|||
stringResource(R.string.level_unabbreviated, member.stats?.lvl ?: 0),
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Normal,
|
||||
color = HabiticaTheme.colors.textPrimary
|
||||
color = HabiticaTheme.colors.textTertiary
|
||||
)
|
||||
Spacer(Modifier.weight(1f))
|
||||
Text(
|
||||
"", fontWeight = FontWeight.SemiBold, fontSize = 14.sp,
|
||||
color = HabiticaTheme.colors.textPrimary
|
||||
role, fontWeight = FontWeight.SemiBold, fontSize = 14.sp,
|
||||
color = HabiticaTheme.colors.textSecondary
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -197,5 +217,5 @@ private class MemberProvider : PreviewParameterProvider<Member> {
|
|||
@Composable
|
||||
@Preview
|
||||
private fun Preview(@PreviewParameter(MemberProvider::class) member: Member) {
|
||||
MemberItem(member = member, onMemberClicked = {}, onMoreClicked = {})
|
||||
MemberItem(member = member, role = "Manager", onMemberClicked = {}, onMoreClicked = {})
|
||||
}
|
||||
|
|
@ -29,6 +29,7 @@ import androidx.compose.ui.platform.LocalContext
|
|||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.habitrpg.android.habitica.R
|
||||
|
|
@ -44,7 +45,8 @@ fun LabeledBar(
|
|||
barColor: Color = HabiticaTheme.colors.windowBackground,
|
||||
value: Double,
|
||||
maxValue: Double,
|
||||
displayCompact: Boolean,
|
||||
displayCompact: Boolean = false,
|
||||
barHeight: Dp = 8.dp,
|
||||
disabled: Boolean = false
|
||||
) {
|
||||
val cleanedMaxVlaue = java.lang.Double.max(1.0, maxValue)
|
||||
|
|
@ -72,7 +74,7 @@ fun LabeledBar(
|
|||
Modifier
|
||||
.fillMaxWidth()
|
||||
.clip(CircleShape)
|
||||
.height(8.dp),
|
||||
.height(barHeight),
|
||||
backgroundColor = barColor,
|
||||
color = color
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,27 +1,51 @@
|
|||
package com.habitrpg.android.habitica.ui.views
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.requiredSize
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
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.Color
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.habitrpg.shared.habitica.models.Avatar
|
||||
|
||||
@Composable
|
||||
fun UserRow(
|
||||
username: String,
|
||||
avatar: Avatar?,
|
||||
modifier: Modifier = Modifier,
|
||||
extraContent: @Composable (() -> Unit)? = null,
|
||||
endContent: @Composable (() -> Unit)? = null,
|
||||
color: Color? = null
|
||||
) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween, modifier = modifier.fillMaxWidth()) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically, modifier = modifier.fillMaxWidth()) {
|
||||
Box(modifier = Modifier
|
||||
.padding(end = 12.dp)
|
||||
.clip(CircleShape)
|
||||
.size(40.dp)
|
||||
.padding(end = 12.dp, top = if (avatar?.currentMount?.isNotBlank() == true) 24.dp else 12.dp)) {
|
||||
if (avatar != null) {
|
||||
ComposableAvatarView(
|
||||
avatar = avatar,
|
||||
Modifier
|
||||
.size(96.dp)
|
||||
.requiredSize(96.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
Text(
|
||||
"@$username",
|
||||
|
|
@ -33,6 +57,7 @@ fun UserRow(
|
|||
extraContent()
|
||||
}
|
||||
}
|
||||
Spacer(Modifier.weight(1f))
|
||||
if (endContent != null) {
|
||||
endContent()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.TextButton
|
||||
|
|
@ -122,7 +121,7 @@ fun StatsViewPreview() {
|
|||
levelValue = 10,
|
||||
equipmentValue = 5,
|
||||
buffValue = 4,
|
||||
allocatedValue = 8,
|
||||
allocatedValue = 20,
|
||||
canAllocate = true
|
||||
) {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ fun AssignSheet(
|
|||
}
|
||||
UserRow(
|
||||
username = member.displayName,
|
||||
avatar = member,
|
||||
color = colorResource(R.color.text_primary),
|
||||
extraContent = {
|
||||
Text(
|
||||
|
|
|
|||
|
|
@ -46,7 +46,9 @@ fun AssignedView(
|
|||
.fillMaxWidth()
|
||||
for (assignable in assigned) {
|
||||
UserRow(
|
||||
username = assignable.identifiableName, modifier = rowModifier,
|
||||
username = assignable.identifiableName,
|
||||
avatar = assignable.avatar,
|
||||
modifier = rowModifier,
|
||||
color = color,
|
||||
extraContent = {
|
||||
completedAt[assignable.id]?.let { CompletedAt(completedAt = it) }
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
NAME=4.1
|
||||
CODE=4781
|
||||
CODE=4791
|
||||
Loading…
Reference in a new issue