mirror of
https://github.com/sudoxnym/habitica-android.git
synced 2026-05-22 13:48:55 +00:00
allow rescinding invites from party screen
This commit is contained in:
parent
79d9d744b4
commit
30773b13b9
12 changed files with 193 additions and 66 deletions
|
|
@ -202,6 +202,10 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"/>
|
||||
<androidx.compose.ui.platform.ComposeView
|
||||
android:id="@+id/invites_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
|
|
|
|||
|
|
@ -1385,6 +1385,7 @@
|
|||
<string name="unlock_gear_and_skills">Unlock %s gear and skills</string>
|
||||
<string name="rescind_invite">Rescind Invite</string>
|
||||
<string name="rescinded">Rescinded</string>
|
||||
<string name="pending_invite">Pending Invite</string>
|
||||
|
||||
<plurals name="you_x_others">
|
||||
<item quantity="zero">You</item>
|
||||
|
|
|
|||
|
|
@ -286,6 +286,10 @@ interface ApiService {
|
|||
@POST("groups/{gid}/quests/invite/{questKey}")
|
||||
suspend fun inviteToQuest(@Path("gid") groupId: String, @Path("questKey") questKey: String): HabitResponse<Quest>
|
||||
|
||||
@GET("groups/{gid}/invites")
|
||||
suspend fun getGroupInvites(@Path("gid") groupId: String,
|
||||
@Query("includeAllPublicFields") includeAllPublicFields: Boolean?): HabitResponse<List<Member>>
|
||||
|
||||
@POST("groups/{gid}/quests/abort")
|
||||
suspend fun abortQuest(@Path("gid") groupId: String): HabitResponse<Quest>
|
||||
|
||||
|
|
|
|||
|
|
@ -278,4 +278,5 @@ interface ApiClient {
|
|||
suspend fun getHallMember(userId: String): Member?
|
||||
suspend fun markTaskNeedsWork(taskID: String, userID: String): Task?
|
||||
suspend fun retrievePartySeekingUsers(page: Int) : List<Member>?
|
||||
suspend fun getGroupInvites(groupId: String, includeAllPublicFields: Boolean?): List<Member>?
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,4 +123,5 @@ interface SocialRepository : BaseRepository {
|
|||
fun getMember(userID: String?): Flow<Member?>
|
||||
suspend fun updateMember(memberID: String, key: String, value: Any?): Member?
|
||||
suspend fun retrievePartySeekingUsers(page: Int = 0): List<Member>?
|
||||
suspend fun retrievegroupInvites(id: String, includeAllPublicFields: Boolean): List<Member>?
|
||||
}
|
||||
|
|
|
|||
|
|
@ -578,6 +578,10 @@ class ApiClientImpl(
|
|||
return process { apiService.rejectGroupInvite(groupId) }
|
||||
}
|
||||
|
||||
override suspend fun getGroupInvites(groupId: String, includeAllPublicFields: Boolean?): List<Member>? {
|
||||
return process { apiService.getGroupInvites(groupId, includeAllPublicFields) }
|
||||
}
|
||||
|
||||
override suspend fun acceptQuest(groupId: String): Void? {
|
||||
return process { apiService.acceptQuest(groupId) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -275,6 +275,9 @@ class SocialRepositoryImpl(
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun retrievegroupInvites(id: String, includeAllPublicFields: Boolean) = apiClient.getGroupInvites(id, includeAllPublicFields)
|
||||
|
||||
|
||||
override suspend fun retrieveMemberWithUsername(username: String?, fromHall: Boolean): Member? {
|
||||
return retrieveMember(username, fromHall)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ class UserRepositoryImpl(
|
|||
override suspend fun sendPasswordResetEmail(email: String) = apiClient.sendPasswordResetEmail(email)
|
||||
|
||||
override suspend fun updateLoginName(newLoginName: String, password: String?): User? {
|
||||
if (password != null && password.isNotEmpty()) {
|
||||
if (!password.isNullOrEmpty()) {
|
||||
apiClient.updateLoginName(newLoginName.trim(), password.trim())
|
||||
} else {
|
||||
apiClient.updateUsername(newLoginName.trim())
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import android.view.ViewGroup
|
|||
import android.widget.Button
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.widget.AppCompatEditText
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.view.isVisible
|
||||
|
|
@ -30,10 +31,13 @@ import com.habitrpg.android.habitica.ui.activities.MainActivity
|
|||
import com.habitrpg.android.habitica.ui.fragments.BaseFragment
|
||||
import com.habitrpg.android.habitica.ui.fragments.inventory.items.ItemDialogFragment
|
||||
import com.habitrpg.android.habitica.ui.helpers.dismissKeyboard
|
||||
import com.habitrpg.android.habitica.ui.theme.HabiticaTheme
|
||||
import com.habitrpg.android.habitica.ui.viewHolders.GroupMemberViewHolder
|
||||
import com.habitrpg.android.habitica.ui.viewmodels.PartyViewModel
|
||||
import com.habitrpg.android.habitica.ui.views.HabiticaSnackbar
|
||||
import com.habitrpg.android.habitica.ui.views.LoadingButtonState
|
||||
import com.habitrpg.android.habitica.ui.views.dialogs.HabiticaAlertDialog
|
||||
import com.habitrpg.android.habitica.ui.views.social.PartySeekingListItem
|
||||
import com.habitrpg.common.habitica.extensions.DataBindingUtils
|
||||
import com.habitrpg.common.habitica.extensions.dpToPx
|
||||
import com.habitrpg.common.habitica.extensions.loadImage
|
||||
|
|
@ -55,7 +59,10 @@ class PartyDetailFragment : BaseFragment<FragmentPartyDetailBinding>() {
|
|||
|
||||
override var binding: FragmentPartyDetailBinding? = null
|
||||
|
||||
override fun createBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentPartyDetailBinding {
|
||||
override fun createBinding(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?
|
||||
): FragmentPartyDetailBinding {
|
||||
return FragmentPartyDetailBinding.inflate(inflater, container, false)
|
||||
}
|
||||
|
||||
|
|
@ -110,6 +117,28 @@ class PartyDetailFragment : BaseFragment<FragmentPartyDetailBinding>() {
|
|||
userRepository.retrieveUser(false, true)
|
||||
}
|
||||
}
|
||||
binding?.invitesWrapper?.setContent {
|
||||
HabiticaTheme {
|
||||
val invitedMembers = viewModel?.pendingInvites
|
||||
Column {
|
||||
for (invitedMember in (invitedMembers ?: emptyList())) {
|
||||
val state = viewModel?.pendingInviteStates?.getOrDefault(
|
||||
invitedMember.id,
|
||||
LoadingButtonState.CONTENT
|
||||
) ?: LoadingButtonState.CONTENT
|
||||
PartySeekingListItem(
|
||||
user = invitedMember,
|
||||
inviteState = state,
|
||||
isInvited = state != LoadingButtonState.SUCCESS,
|
||||
showHeader = true,
|
||||
showExtendedInfo = false,
|
||||
onInvite = {
|
||||
viewModel?.rescindInvite(invitedMember)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
viewModel?.getGroupData()?.observe(viewLifecycleOwner) { updateParty(it) }
|
||||
viewModel?.user?.observe(viewLifecycleOwner) { updateUser(it) }
|
||||
|
|
@ -138,7 +167,8 @@ class PartyDetailFragment : BaseFragment<FragmentPartyDetailBinding>() {
|
|||
binding?.questImageWrapper?.visibility = View.VISIBLE
|
||||
lifecycleScope.launch(Dispatchers.Main) {
|
||||
delay(500)
|
||||
val content = inventoryRepository.getQuestContent(party.quest?.key ?: "").firstOrNull()
|
||||
val content =
|
||||
inventoryRepository.getQuestContent(party.quest?.key ?: "").firstOrNull()
|
||||
if (content != null) {
|
||||
updateQuestContent(content)
|
||||
}
|
||||
|
|
@ -239,17 +269,36 @@ class PartyDetailFragment : BaseFragment<FragmentPartyDetailBinding>() {
|
|||
}
|
||||
binding?.questImageWrapper?.alpha = 1.0f
|
||||
binding?.questProgressView?.alpha = 1.0f
|
||||
context?.let { binding?.questParticipationView?.setTextColor(ContextCompat.getColor(it, R.color.text_quad)) }
|
||||
context?.let {
|
||||
binding?.questParticipationView?.setTextColor(
|
||||
ContextCompat.getColor(
|
||||
it,
|
||||
R.color.text_quad
|
||||
)
|
||||
)
|
||||
}
|
||||
if (viewModel?.isQuestActive == true) {
|
||||
binding?.questProgressView?.visibility = View.VISIBLE
|
||||
binding?.questProgressView?.setData(questContent, viewModel?.getGroupData()?.value?.quest?.progress)
|
||||
binding?.questProgressView?.setData(
|
||||
questContent,
|
||||
viewModel?.getGroupData()?.value?.quest?.progress
|
||||
)
|
||||
|
||||
val questParticipants = viewModel?.getGroupData()?.value?.quest?.members
|
||||
if (questParticipants?.find { it.key == viewModel?.userViewModel?.userID } != null) {
|
||||
binding?.questParticipationView?.text = context?.getString(R.string.number_participants, questParticipants.size)
|
||||
binding?.questParticipationView?.text =
|
||||
context?.getString(R.string.number_participants, questParticipants.size)
|
||||
} else {
|
||||
binding?.questParticipationView?.text = context?.getString(R.string.not_participating)
|
||||
context?.let { binding?.questParticipationView?.setTextColor(ContextCompat.getColor(it, R.color.red_10)) }
|
||||
binding?.questParticipationView?.text =
|
||||
context?.getString(R.string.not_participating)
|
||||
context?.let {
|
||||
binding?.questParticipationView?.setTextColor(
|
||||
ContextCompat.getColor(
|
||||
it,
|
||||
R.color.red_10
|
||||
)
|
||||
)
|
||||
}
|
||||
binding?.questImageWrapper?.alpha = 0.5f
|
||||
binding?.questProgressView?.alpha = 0.5f
|
||||
}
|
||||
|
|
@ -257,7 +306,8 @@ class PartyDetailFragment : BaseFragment<FragmentPartyDetailBinding>() {
|
|||
binding?.questProgressView?.visibility = View.GONE
|
||||
val members = viewModel?.getGroupData()?.value?.quest?.members
|
||||
val responded = members?.filter { it.isParticipating != null }
|
||||
binding?.questParticipationView?.text = context?.getString(R.string.number_responded, responded?.size, members?.size)
|
||||
binding?.questParticipationView?.text =
|
||||
context?.getString(R.string.number_responded, responded?.size, members?.size)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -294,7 +344,8 @@ class PartyDetailFragment : BaseFragment<FragmentPartyDetailBinding>() {
|
|||
val factory = LayoutInflater.from(context)
|
||||
val newMessageView = factory.inflate(R.layout.profile_new_message_dialog, null)
|
||||
|
||||
val emojiEditText = newMessageView.findViewById<AppCompatEditText>(R.id.edit_new_message_text)
|
||||
val emojiEditText =
|
||||
newMessageView.findViewById<AppCompatEditText>(R.id.edit_new_message_text)
|
||||
|
||||
val newMessageTitle = newMessageView.findViewById<TextView>(R.id.new_message_title)
|
||||
newMessageTitle.text = String.format(getString(R.string.profile_send_message_to), username)
|
||||
|
|
@ -306,13 +357,17 @@ class PartyDetailFragment : BaseFragment<FragmentPartyDetailBinding>() {
|
|||
(activity as? MainActivity)?.snackbarContainer?.let { it1 ->
|
||||
HabiticaSnackbar.showSnackbar(
|
||||
it1,
|
||||
String.format(getString(R.string.profile_message_sent_to), username), HabiticaSnackbar.SnackbarDisplayType.NORMAL
|
||||
String.format(getString(R.string.profile_message_sent_to), username),
|
||||
HabiticaSnackbar.SnackbarDisplayType.NORMAL
|
||||
)
|
||||
}
|
||||
}
|
||||
activity?.dismissKeyboard()
|
||||
}
|
||||
addMessageDialog?.addButton(android.R.string.cancel, false) { _, _ -> activity?.dismissKeyboard() }
|
||||
addMessageDialog?.addButton(
|
||||
android.R.string.cancel,
|
||||
false
|
||||
) { _, _ -> activity?.dismissKeyboard() }
|
||||
addMessageDialog?.setAdditionalContentView(newMessageView)
|
||||
addMessageDialog?.show()
|
||||
}
|
||||
|
|
@ -325,7 +380,8 @@ class PartyDetailFragment : BaseFragment<FragmentPartyDetailBinding>() {
|
|||
(activity as? MainActivity)?.snackbarContainer?.let { it1 ->
|
||||
HabiticaSnackbar.showSnackbar(
|
||||
it1,
|
||||
String.format(getString(R.string.transferred_ownership), displayName), HabiticaSnackbar.SnackbarDisplayType.NORMAL
|
||||
String.format(getString(R.string.transferred_ownership), displayName),
|
||||
HabiticaSnackbar.SnackbarDisplayType.NORMAL
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -333,7 +389,12 @@ class PartyDetailFragment : BaseFragment<FragmentPartyDetailBinding>() {
|
|||
}
|
||||
dialog?.addButton(android.R.string.cancel, false) { _, _ -> activity?.dismissKeyboard() }
|
||||
dialog?.setTitle(context?.getString(R.string.transfer_ownership_confirm))
|
||||
dialog?.setMessage(context?.getString(R.string.transfer_ownership_confirm_message, displayName))
|
||||
dialog?.setMessage(
|
||||
context?.getString(
|
||||
R.string.transfer_ownership_confirm_message,
|
||||
displayName
|
||||
)
|
||||
)
|
||||
dialog?.show()
|
||||
}
|
||||
|
||||
|
|
@ -345,7 +406,8 @@ class PartyDetailFragment : BaseFragment<FragmentPartyDetailBinding>() {
|
|||
(activity as? MainActivity)?.snackbarContainer?.let { it1 ->
|
||||
HabiticaSnackbar.showSnackbar(
|
||||
it1,
|
||||
String.format(getString(R.string.removed_member), displayName), HabiticaSnackbar.SnackbarDisplayType.NORMAL
|
||||
String.format(getString(R.string.removed_member), displayName),
|
||||
HabiticaSnackbar.SnackbarDisplayType.NORMAL
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -370,7 +432,8 @@ class PartyDetailFragment : BaseFragment<FragmentPartyDetailBinding>() {
|
|||
lifecycleScope.launchCatching {
|
||||
userRepository.getUser().collect {
|
||||
it?.challenges?.forEach { membership ->
|
||||
val challenge = challengeRepository.getChallenge(membership.challengeID).firstOrNull()
|
||||
val challenge =
|
||||
challengeRepository.getChallenge(membership.challengeID).firstOrNull()
|
||||
if (challenge != null && challenge.groupId == viewModel?.groupID) {
|
||||
groupChallenges.add(challenge)
|
||||
}
|
||||
|
|
@ -396,7 +459,11 @@ class PartyDetailFragment : BaseFragment<FragmentPartyDetailBinding>() {
|
|||
MainNavigationController.navigate(R.id.noPartyFragment)
|
||||
}
|
||||
}
|
||||
alert.addButton(R.string.leave_challenges_delete_tasks, false, isDestructive = true) { _, _ ->
|
||||
alert.addButton(
|
||||
R.string.leave_challenges_delete_tasks,
|
||||
false,
|
||||
isDestructive = true
|
||||
) { _, _ ->
|
||||
viewModel?.leaveGroup(groupChallenges, false) {
|
||||
parentFragmentManager.popBackStack()
|
||||
MainNavigationController.navigate(R.id.noPartyFragment)
|
||||
|
|
@ -408,7 +475,11 @@ class PartyDetailFragment : BaseFragment<FragmentPartyDetailBinding>() {
|
|||
val alert = HabiticaAlertDialog(context)
|
||||
alert.setTitle(R.string.leave_party_confirmation)
|
||||
alert.setMessage(R.string.rejoin_party)
|
||||
alert.addButton(R.string.leave, isPrimary = true, isDestructive = true) { _, _ ->
|
||||
alert.addButton(
|
||||
R.string.leave,
|
||||
isPrimary = true,
|
||||
isDestructive = true
|
||||
) { _, _ ->
|
||||
viewModel?.leaveGroup(groupChallenges, false) {
|
||||
parentFragmentManager.popBackStack()
|
||||
MainNavigationController.navigate(R.id.noPartyFragment)
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ fun PartySeekingView(
|
|||
user = it,
|
||||
inviteState =viewModel.inviteStates[it.id] ?: LoadingButtonState.CONTENT,
|
||||
isInvited = viewModel.successfulInvites.contains(it.id),
|
||||
modifier = Modifier.animateItemPlacement()
|
||||
modifier = Modifier.animateItemPlacement().padding(horizontal = 14.dp)
|
||||
) { member ->
|
||||
scope.launchCatching({
|
||||
viewModel.inviteStates[member.id] = LoadingButtonState.FAILED
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package com.habitrpg.android.habitica.ui.viewmodels
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.mutableStateMapOf
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.asLiveData
|
||||
|
|
@ -14,12 +16,14 @@ import com.habitrpg.android.habitica.models.members.Member
|
|||
import com.habitrpg.android.habitica.models.social.Challenge
|
||||
import com.habitrpg.android.habitica.models.social.ChatMessage
|
||||
import com.habitrpg.android.habitica.models.social.Group
|
||||
import com.habitrpg.android.habitica.ui.views.LoadingButtonState
|
||||
import com.habitrpg.common.habitica.helpers.ExceptionHandler
|
||||
import com.habitrpg.common.habitica.helpers.launchCatching
|
||||
import com.habitrpg.common.habitica.models.notifications.NewChatMessageData
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import io.realm.kotlin.toFlow
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
|
|
@ -29,8 +33,10 @@ import kotlinx.coroutines.flow.map
|
|||
import kotlinx.coroutines.launch
|
||||
import retrofit2.HttpException
|
||||
import javax.inject.Inject
|
||||
import kotlin.time.DurationUnit
|
||||
import kotlin.time.toDuration
|
||||
|
||||
enum class GroupViewType(internal val order : String) {
|
||||
enum class GroupViewType(internal val order: String) {
|
||||
PARTY("party"),
|
||||
GUILD("guild"),
|
||||
TAVERN("tavern")
|
||||
|
|
@ -39,17 +45,17 @@ enum class GroupViewType(internal val order : String) {
|
|||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
@HiltViewModel
|
||||
open class GroupViewModel @Inject constructor(
|
||||
userRepository : UserRepository,
|
||||
userViewModel : MainUserViewModel,
|
||||
val challengeRepository : ChallengeRepository,
|
||||
val socialRepository : SocialRepository,
|
||||
val notificationsManager : NotificationsManager
|
||||
userRepository: UserRepository,
|
||||
userViewModel: MainUserViewModel,
|
||||
val challengeRepository: ChallengeRepository,
|
||||
val socialRepository: SocialRepository,
|
||||
val notificationsManager: NotificationsManager
|
||||
) : BaseViewModel(userRepository, userViewModel) {
|
||||
|
||||
protected val groupIDState = MutableStateFlow<String?>(null)
|
||||
val groupIDFlow : Flow<String?> = groupIDState
|
||||
val groupIDFlow: Flow<String?> = groupIDState
|
||||
|
||||
var groupViewType : GroupViewType? = null
|
||||
var groupViewType: GroupViewType? = null
|
||||
|
||||
private val groupFlow = groupIDFlow
|
||||
.filterNotNull()
|
||||
|
|
@ -67,21 +73,21 @@ open class GroupViewModel @Inject constructor(
|
|||
.map { it != null }
|
||||
private val isMemberData = isMemberFlow.asLiveData()
|
||||
|
||||
private val _chatMessages : MutableLiveData<List<ChatMessage>> by lazy {
|
||||
private val _chatMessages: MutableLiveData<List<ChatMessage>> by lazy {
|
||||
MutableLiveData<List<ChatMessage>>(listOf())
|
||||
}
|
||||
val chatmessages : LiveData<List<ChatMessage>> by lazy {
|
||||
val chatmessages: LiveData<List<ChatMessage>> by lazy {
|
||||
_chatMessages
|
||||
}
|
||||
|
||||
var gotNewMessages : Boolean = false
|
||||
var gotNewMessages: Boolean = false
|
||||
|
||||
override fun onCleared() {
|
||||
socialRepository.close()
|
||||
super.onCleared()
|
||||
}
|
||||
|
||||
fun setGroupID(groupID : String) {
|
||||
fun setGroupID(groupID: String) {
|
||||
if (groupID == groupIDState.value) return
|
||||
groupIDState.value = groupID
|
||||
|
||||
|
|
@ -95,22 +101,25 @@ open class GroupViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
val groupID : String?
|
||||
val groupID: String?
|
||||
get() = groupIDState.value
|
||||
val isMember : Boolean
|
||||
val isMember: Boolean
|
||||
get() = isMemberData.value ?: false
|
||||
val leaderID : String?
|
||||
val leaderID: String?
|
||||
get() = group.value?.leaderID
|
||||
val isLeader : Boolean
|
||||
val isLeader: Boolean
|
||||
get() = user.value?.id == leaderID
|
||||
val isPublicGuild : Boolean
|
||||
val isPublicGuild: Boolean
|
||||
get() = group.value?.privacy == "public"
|
||||
|
||||
fun getGroupData() : LiveData<Group?> = group
|
||||
fun getLeaderData() : LiveData<Member?> = leader
|
||||
fun getIsMemberData() : LiveData<Boolean> = isMemberData
|
||||
val pendingInvites = mutableStateListOf<Member>()
|
||||
val pendingInviteStates = mutableStateMapOf<String, LoadingButtonState>()
|
||||
|
||||
fun retrieveGroup(function : (() -> Unit)?) {
|
||||
fun getGroupData(): LiveData<Group?> = group
|
||||
fun getLeaderData(): LiveData<Member?> = leader
|
||||
fun getIsMemberData(): LiveData<Boolean> = isMemberData
|
||||
|
||||
fun retrieveGroup(function: (() -> Unit)?) {
|
||||
if (groupID?.isNotEmpty() == true) {
|
||||
viewModelScope.launch(
|
||||
ExceptionHandler.coroutine {
|
||||
|
|
@ -122,19 +131,23 @@ open class GroupViewModel @Inject constructor(
|
|||
val group = socialRepository.retrieveGroup(groupID ?: "")
|
||||
if (groupViewType == GroupViewType.PARTY) {
|
||||
socialRepository.retrievePartyMembers(group?.id ?: "", true)
|
||||
val invites =
|
||||
socialRepository.retrievegroupInvites(group?.id ?: "", true) ?: emptyList()
|
||||
pendingInvites.clear()
|
||||
pendingInvites.addAll(invites)
|
||||
}
|
||||
function?.invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun inviteToGroup(inviteData : HashMap<String, Any>) {
|
||||
fun inviteToGroup(inviteData: HashMap<String, Any>) {
|
||||
viewModelScope.launchCatching {
|
||||
socialRepository.inviteToGroup(group.value?.id ?: "", inviteData)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateOrCreateGroup(bundle : Bundle?) {
|
||||
fun updateOrCreateGroup(bundle: Bundle?) {
|
||||
viewModelScope.launch(ExceptionHandler.coroutine()) {
|
||||
if (group.value == null) {
|
||||
socialRepository.createGroup(
|
||||
|
|
@ -157,9 +170,9 @@ open class GroupViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
fun leaveGroup(
|
||||
groupChallenges : List<Challenge>,
|
||||
keepChallenges : Boolean = true,
|
||||
function : (() -> Unit)? = null
|
||||
groupChallenges: List<Challenge>,
|
||||
keepChallenges: Boolean = true,
|
||||
function: (() -> Unit)? = null
|
||||
) {
|
||||
if (!keepChallenges) {
|
||||
viewModelScope.launchCatching {
|
||||
|
|
@ -175,14 +188,14 @@ open class GroupViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
fun joinGroup(id : String? = null, function : (() -> Unit)? = null) {
|
||||
fun joinGroup(id: String? = null, function: (() -> Unit)? = null) {
|
||||
viewModelScope.launchCatching {
|
||||
socialRepository.joinGroup(id ?: groupID)
|
||||
function?.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
fun rejectGroupInvite(id : String? = null) {
|
||||
fun rejectGroupInvite(id: String? = null) {
|
||||
groupID?.let {
|
||||
viewModelScope.launchCatching {
|
||||
socialRepository.rejectGroupInvite(id ?: it)
|
||||
|
|
@ -200,7 +213,7 @@ open class GroupViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
fun likeMessage(message : ChatMessage) {
|
||||
fun likeMessage(message: ChatMessage) {
|
||||
viewModelScope.launchCatching {
|
||||
val message = socialRepository.likeMessage(message)
|
||||
val index = _chatMessages.value?.indexOfFirst { it.id == message?.id }
|
||||
|
|
@ -216,7 +229,7 @@ open class GroupViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
fun deleteMessage(chatMessage : ChatMessage) {
|
||||
fun deleteMessage(chatMessage: ChatMessage) {
|
||||
val oldIndex = _chatMessages.value?.indexOf(chatMessage) ?: return
|
||||
val list = _chatMessages.value?.toMutableList()
|
||||
list?.remove(chatMessage)
|
||||
|
|
@ -232,7 +245,7 @@ open class GroupViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
fun postGroupChat(chatText : String, onComplete : () -> Unit, onError : () -> Unit) {
|
||||
fun postGroupChat(chatText: String, onComplete: () -> Unit, onError: () -> Unit) {
|
||||
groupID?.let { groupID ->
|
||||
viewModelScope.launch(
|
||||
ExceptionHandler.coroutine {
|
||||
|
|
@ -251,7 +264,7 @@ open class GroupViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
fun retrieveGroupChat(onComplete : () -> Unit) {
|
||||
fun retrieveGroupChat(onComplete: () -> Unit) {
|
||||
var groupID = groupID
|
||||
if (groupViewType == GroupViewType.PARTY) {
|
||||
groupID = "party"
|
||||
|
|
@ -267,7 +280,7 @@ open class GroupViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
fun updateGroup(bundle : Bundle?) {
|
||||
fun updateGroup(bundle: Bundle?) {
|
||||
viewModelScope.launch(ExceptionHandler.coroutine()) {
|
||||
socialRepository.updateGroup(
|
||||
group.value,
|
||||
|
|
@ -278,4 +291,16 @@ open class GroupViewModel @Inject constructor(
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun rescindInvite(invitedMember: Member) {
|
||||
pendingInviteStates[invitedMember.id] = LoadingButtonState.LOADING
|
||||
viewModelScope.launchCatching({
|
||||
pendingInviteStates[invitedMember.id] = LoadingButtonState.FAILED
|
||||
}) {
|
||||
socialRepository.removeMemberFromGroup(groupID ?: "", invitedMember.id)
|
||||
pendingInviteStates[invitedMember.id] = LoadingButtonState.SUCCESS
|
||||
delay(1.toDuration(DurationUnit.SECONDS))
|
||||
pendingInvites.remove(invitedMember)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,13 +46,14 @@ fun PartySeekingListItem(
|
|||
modifier : Modifier = Modifier,
|
||||
inviteState : LoadingButtonState = LoadingButtonState.LOADING,
|
||||
isInvited: Boolean = false,
|
||||
showHeader: Boolean = false,
|
||||
showExtendedInfo: Boolean = true,
|
||||
onInvite : (Member) -> Unit
|
||||
) {
|
||||
Column(
|
||||
modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 14.dp)
|
||||
.padding(bottom = 4.dp)
|
||||
.padding(bottom = 6.dp)
|
||||
.background(HabiticaTheme.colors.windowBackground, HabiticaTheme.shapes.large)
|
||||
.padding(14.dp)
|
||||
) {
|
||||
|
|
@ -68,6 +69,14 @@ fun PartySeekingListItem(
|
|||
verticalArrangement = Arrangement.Top,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
if (showHeader) {
|
||||
Text(
|
||||
stringResource(R.string.pending_invite).uppercase(),
|
||||
fontSize = 12.sp,
|
||||
color = HabiticaTheme.colors.textQuad,
|
||||
modifier = Modifier.padding(bottom = 4.dp)
|
||||
)
|
||||
}
|
||||
ProvideTextStyle(value = TextStyle(fontSize = 14.sp)) {
|
||||
ComposableUsernameLabel(
|
||||
user.displayName,
|
||||
|
|
@ -101,18 +110,22 @@ fun PartySeekingListItem(
|
|||
hasClass = user.hasClass
|
||||
)
|
||||
}
|
||||
Text(
|
||||
stringResource(R.string.x_checkins, user.loginIncentives),
|
||||
fontWeight = FontWeight.Medium,
|
||||
fontSize = 14.sp,
|
||||
color = HabiticaTheme.colors.textPrimary
|
||||
)
|
||||
Text(
|
||||
Locale(user.preferences?.language ?: "en").getDisplayName(Locale.getDefault()),
|
||||
fontWeight = FontWeight.Medium,
|
||||
fontSize = 14.sp,
|
||||
color = HabiticaTheme.colors.textPrimary
|
||||
)
|
||||
if (showExtendedInfo) {
|
||||
Text(
|
||||
stringResource(R.string.x_checkins, user.loginIncentives),
|
||||
fontWeight = FontWeight.Medium,
|
||||
fontSize = 14.sp,
|
||||
color = HabiticaTheme.colors.textPrimary
|
||||
)
|
||||
Text(
|
||||
Locale(
|
||||
user.preferences?.language ?: "en"
|
||||
).getDisplayName(Locale.getDefault()),
|
||||
fontWeight = FontWeight.Medium,
|
||||
fontSize = 14.sp,
|
||||
color = HabiticaTheme.colors.textPrimary
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
InviteButton(
|
||||
|
|
|
|||
Loading…
Reference in a new issue