Skip to content

Commit

Permalink
Merge branch 'main' into radhi/clound-function-delete-space
Browse files Browse the repository at this point in the history
  • Loading branch information
cp-megh-l authored Jan 24, 2025
2 parents 24473c0 + 0aa1874 commit 4038dc4
Show file tree
Hide file tree
Showing 20 changed files with 300 additions and 209 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import androidx.lifecycle.viewModelScope
import com.canopas.yourspace.data.models.user.ApiUserSession
import com.canopas.yourspace.data.repository.SpaceRepository
import com.canopas.yourspace.data.service.auth.AuthService
import com.canopas.yourspace.data.service.location.toBytes
import com.canopas.yourspace.data.service.user.ApiUserService
import com.canopas.yourspace.data.storage.UserPreferences
import com.canopas.yourspace.data.utils.AppDispatcher
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.canopas.yourspace.data.service.auth.AuthService
import com.canopas.yourspace.data.service.auth.FirebaseAuthService
import com.canopas.yourspace.data.service.location.toBytes
import com.canopas.yourspace.data.storage.UserPreferences
import com.canopas.yourspace.data.utils.AppDispatcher
import com.canopas.yourspace.domain.utils.ConnectivityObserver
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class SettingsViewModel @Inject constructor(
}

private fun getUser() = viewModelScope.launch(appDispatcher.IO) {
authService.getUserFlow().collectLatest { user ->
authService.getUserFlow()?.collectLatest { user ->
_state.emit(_state.value.copy(user = user))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import android.content.Intent
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsFocusedAsState
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
Expand All @@ -18,13 +19,17 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ExitToApp
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material.icons.filled.Share
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
Expand All @@ -47,8 +52,10 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
Expand All @@ -63,7 +70,6 @@ import com.canopas.yourspace.ui.component.AppProgressIndicator
import com.canopas.yourspace.ui.component.NoInternetScreen
import com.canopas.yourspace.ui.component.PrimaryTextButton
import com.canopas.yourspace.ui.component.UserProfile
import com.canopas.yourspace.ui.flow.settings.profile.UserTextField
import com.canopas.yourspace.ui.theme.AppTheme
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
Expand Down Expand Up @@ -194,21 +200,6 @@ private fun SpaceProfileToolbar() {
}
},
actions = {
Text(
text = stringResource(id = R.string.edit_profile_toolbar_save_text),
color = if (state.allowSave) AppTheme.colorScheme.primary else AppTheme.colorScheme.textDisabled,
style = AppTheme.appTypography.button,
modifier = Modifier
.padding(end = 8.dp)
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = ripple(bounded = false),
enabled = state.allowSave,
onClick = {
viewModel.saveSpace()
}
)
)
if (state.isAdmin && state.spaceMemberCount > 1) {
IconButton(
onClick = { viewModel.onAdminMenuExpanded(true) }
Expand Down Expand Up @@ -243,88 +234,146 @@ private fun SpaceProfileContent() {
val scrollState = rememberScrollState()
val context = LocalContext.current

val focusManager = LocalFocusManager.current
val interactionSource = remember { MutableInteractionSource() }
val isFocused by interactionSource.collectIsFocusedAsState()
val outlineColor =
if (isFocused) AppTheme.colorScheme.primary else AppTheme.colorScheme.outline

Box(modifier = Modifier.fillMaxSize()) {
Column(
Modifier
.fillMaxSize()
.verticalScroll(scrollState)
.padding(bottom = 80.dp)
) {
UserTextField(
label = stringResource(R.string.space_setting_hint_space_name),
text = state.spaceName ?: "",
enabled = state.isAdmin,
onValueChange = {
viewModel.onNameChanged(it.trimStart())
Text(
text = stringResource(id = R.string.space_setting_hint_space_name),
color = if (isFocused) AppTheme.colorScheme.primary else AppTheme.colorScheme.textDisabled,
style = AppTheme.appTypography.caption,
modifier = Modifier.padding(start = 16.dp)
)
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp)
) {
BasicTextField(
value = state.spaceName ?: "",
onValueChange = { viewModel.onNameChanged(it.trimStart()) },
enabled = state.isAdmin,
maxLines = 1,
interactionSource = interactionSource,
modifier = Modifier
.weight(1f)
.padding(top = 8.dp),
singleLine = true,
textStyle = AppTheme.appTypography.subTitle2.copy(color = AppTheme.colorScheme.textPrimary),
keyboardActions = KeyboardActions(onDone = {
focusManager.clearFocus()
}),
cursorBrush = SolidColor(AppTheme.colorScheme.primary)
)
if (state.allowSave) {
if (state.isNameChanging) {
CircularProgressIndicator(modifier = Modifier.size(20.dp))
} else {
Icon(
imageVector = Icons.Default.Check,
contentDescription = "",
tint = outlineColor,
modifier = Modifier
.padding(horizontal = 8.dp)
.clickable {
ripple(true)
viewModel.saveSpace()
focusManager.clearFocus()
}
)
}
}
}

HorizontalDivider(
Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 4.dp),
color = outlineColor
)

Spacer(modifier = Modifier.height(24.dp))
Spacer(modifier = Modifier.height(12.dp))

Text(
text = stringResource(R.string.space_invite_code_title),
style = AppTheme.appTypography.body2,
color = AppTheme.colorScheme.textDisabled,
modifier = Modifier.padding(start = 8.dp)
modifier = Modifier.padding(start = 16.dp)
)

Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.padding(horizontal = 8.dp)
modifier = Modifier.padding(horizontal = 16.dp)
) {
Text(
text = state.inviteCode,
modifier = Modifier.weight(1f),
style = AppTheme.appTypography.header4
)

if (state.isAdmin) {
if (state.isCodeLoading) {
CircularProgressIndicator(modifier = Modifier.size(24.dp))
} else {
IconButton(onClick = { viewModel.regenerateInviteCode() }) {
Icon(Icons.Default.Refresh, contentDescription = "")
}
}
}

IconButton(
onClick = { shareInvitationCode(context = context, code = state.inviteCode) }
) {
Icon(Icons.Default.Share, contentDescription = "")
}
if (state.isAdmin) {
IconButton(onClick = { viewModel.regenerateInviteCode() }) {
Icon(Icons.Default.Refresh, contentDescription = "")
}
}
}
Text(
text = stringResource(R.string.space_invite_code_expire_text, state.codeExpireTime),
style = AppTheme.appTypography.body2,
color = AppTheme.colorScheme.textDisabled,
modifier = Modifier.padding(start = 8.dp)
modifier = Modifier.padding(start = 16.dp)
)

HorizontalDivider(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 24.dp),
.padding(vertical = 12.dp, horizontal = 16.dp),
color = AppTheme.colorScheme.outline
)

Header(title = stringResource(id = R.string.space_setting_title_your_location))

state.spaceInfo?.members?.firstOrNull { it.user.id == state.currentUserId }?.let {
UserItem(
userInfo = it,
isChecked = state.locationEnabled,
enable = true,
isAdmin = state.isAdmin,
currentUser = state.currentUserId!!,
isAdminUser = state.spaceInfo?.space?.admin_id == it.user.id,
onCheckedChange = {
viewModel.onLocationEnabledChanged(it)
},
onMemberRemove = {
viewModel.showRemoveMemberConfirmationWithId(true, "")
}
)
}
state.spaceInfo?.members?.firstOrNull { it.user.id == state.currentUserId }
?.let { user ->
UserItem(
userInfo = user,
isChecked = state.locationEnabled,
enable = true,
isAdmin = state.isAdmin,
currentUser = state.currentUserId!!,
isAdminUser = state.spaceInfo?.space?.admin_id == user.user.id,
onCheckedChange = { isChecked ->
viewModel.onLocationEnabledChanged(isChecked)
},
onMemberRemove = {
viewModel.showRemoveMemberConfirmationWithId(true, "")
}
)
}

HorizontalDivider(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 24.dp),
.padding(vertical = 16.dp),
color = AppTheme.colorScheme.outline
)

Expand All @@ -335,18 +384,19 @@ private fun SpaceProfileContent() {
?: emptyList()

if (others.isNotEmpty()) {
others.forEach {
others.forEach { user ->
UserItem(
userInfo = it,
isChecked = it.isLocationEnable,
enable = false,
userInfo = user,
isChecked = user.isLocationEnable,
enable = state.isAdmin,
isAdmin = state.isAdmin,
currentUser = state.currentUserId!!,
isAdminUser = state.spaceInfo?.space?.admin_id == it.user.id,
onCheckedChange = {
isAdminUser = state.spaceInfo?.space?.admin_id == user.user.id,
onCheckedChange = { isChecked ->
viewModel.updateMemberLocation(user.user.id, isChecked)
},
onMemberRemove = {
viewModel.showRemoveMemberConfirmationWithId(true, it.user.id)
viewModel.showRemoveMemberConfirmationWithId(true, user.user.id)
}
)
}
Expand Down Expand Up @@ -502,8 +552,8 @@ private fun UserItem(
uncheckedTrackColor = AppTheme.colorScheme.containerHigh,
disabledCheckedTrackColor = AppTheme.colorScheme.containerHigh
),
onCheckedChange = {
onCheckedChange(it)
onCheckedChange = { isChecked ->
onCheckedChange(isChecked)
},
modifier = Modifier.padding(end = 8.dp)
)
Expand Down
Loading

0 comments on commit 4038dc4

Please sign in to comment.