Skip to content

Commit

Permalink
Merge branch 'main' into add-condition-to-block-place-addition-for-on…
Browse files Browse the repository at this point in the history
…e-member-groups

# Conflicts:
#	app/src/main/res/values/strings.xml
  • Loading branch information
cp-sneh-s committed Dec 16, 2024
2 parents d3f1606 + 2a551e4 commit cc9b19b
Show file tree
Hide file tree
Showing 15 changed files with 551 additions and 29 deletions.
3 changes: 3 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -210,5 +210,8 @@ dependencies {
// Desugaring
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.3")

// Gson
implementation("com.google.code.gson:gson:2.10.1")

implementation(project(":data"))
}
14 changes: 14 additions & 0 deletions app/src/main/java/com/canopas/yourspace/ui/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.canopas.yourspace.ui

import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.Window
import androidx.activity.ComponentActivity
Expand All @@ -22,6 +23,7 @@ import androidx.lifecycle.ViewModelProvider
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.rememberNavController
import com.canopas.yourspace.R
import com.canopas.yourspace.data.models.space.SpaceInfo
import com.canopas.yourspace.ui.component.AppAlertDialog
import com.canopas.yourspace.ui.flow.auth.SignInMethodsScreen
import com.canopas.yourspace.ui.flow.geofence.add.addnew.AddNewPlaceScreen
Expand All @@ -48,13 +50,16 @@ import com.canopas.yourspace.ui.flow.permission.EnablePermissionsScreen
import com.canopas.yourspace.ui.flow.settings.SettingsScreen
import com.canopas.yourspace.ui.flow.settings.profile.EditProfileScreen
import com.canopas.yourspace.ui.flow.settings.space.SpaceProfileScreen
import com.canopas.yourspace.ui.flow.settings.space.edit.ChangeAdminScreen
import com.canopas.yourspace.ui.flow.settings.support.SupportScreen
import com.canopas.yourspace.ui.navigation.AppDestinations
import com.canopas.yourspace.ui.navigation.AppDestinations.ChangeAdminScreen.KEY_SPACE_NAME
import com.canopas.yourspace.ui.navigation.AppNavigator
import com.canopas.yourspace.ui.navigation.KEY_RESULT
import com.canopas.yourspace.ui.navigation.RESULT_OKAY
import com.canopas.yourspace.ui.navigation.slideComposable
import com.canopas.yourspace.ui.theme.CatchMeTheme
import com.google.gson.Gson
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
Expand Down Expand Up @@ -159,6 +164,15 @@ fun MainApp(viewModel: MainViewModel) {
SpaceProfileScreen()
}

slideComposable(AppDestinations.ChangeAdminScreen.path) {
val spaceInfo = it.arguments?.getString(KEY_SPACE_NAME)?.let { encodedInfo ->
Uri.decode(encodedInfo)
} ?: ""

val space = Gson().fromJson(spaceInfo, SpaceInfo::class.java)
ChangeAdminScreen(space = space)
}

slideComposable(AppDestinations.spaceThreads.path) {
ThreadsScreen()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.canopas.yourspace.ui.flow.settings

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.net.Uri
import androidx.compose.foundation.Image
Expand Down Expand Up @@ -186,6 +187,18 @@ private fun OtherSettingsContent(viewModel: SettingsViewModel) {
}
)

SettingsItem(
label = stringResource(id = R.string.setting_share_app),
icon = R.drawable.ic_setting_share_icon,
onClick = { shareApp(context) }
)

SettingsItem(
label = stringResource(id = R.string.setting_rate_app),
icon = R.drawable.ic_setting_rate_icon,
onClick = { rateApp(context) }
)

SettingsItem(
label = stringResource(id = R.string.setting_btn_sign_out),
icon = R.drawable.ic_setting_sign_out_icon,
Expand All @@ -202,6 +215,29 @@ private fun openUrl(context: Activity, url: String) {
context.startActivity(intent)
}

fun shareApp(context: Context) {
val appUrl = "https://play.google.com/store/apps/details?id=${context.packageName}"
val shareMessage = context.getString(R.string.app_share_message, appUrl)

val shareIntent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_TEXT, shareMessage)
type = "text/plain"
}
context.startActivity(
Intent.createChooser(
shareIntent,
context.getString(R.string.setting_share_app)
)
)
}

fun rateApp(context: Context) {
val appUrl = "https://play.google.com/store/apps/details?id=${context.packageName}"
val rateIntent = Intent(Intent.ACTION_VIEW, Uri.parse(appUrl))
context.startActivity(rateIntent)
}

@Composable
private fun SpaceSettingsContent(
spaces: List<ApiSpace>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ 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.Delete
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
Expand All @@ -32,6 +35,7 @@ import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.ripple
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
Expand All @@ -56,12 +60,20 @@ 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

@Composable
fun SpaceProfileScreen() {
val viewModel = hiltViewModel<SpaceProfileViewModel>()
val state by viewModel.state.collectAsState()

LaunchedEffect(Unit) {
withContext(Dispatchers.IO) {
viewModel.fetchSpaceDetail()
}
}

Scaffold(
topBar = {
SpaceProfileToolbar()
Expand Down Expand Up @@ -105,6 +117,18 @@ fun SpaceProfileScreen() {
)
}

if (state.showChangeAdminDialog) {
AppAlertDialog(
title = stringResource(R.string.space_setting_change_admin_title),
subTitle = stringResource(R.string.space_setting_change_admin_description),
confirmBtnText = stringResource(R.string.change_admin_button),
dismissBtnText = stringResource(id = R.string.common_btn_cancel),
isConfirmDestructive = true,
onConfirmClick = { viewModel.onChangeAdminClicked() },
onDismissClick = { viewModel.showChangeAdminDialog(false) }
)
}

if (state.showLeaveSpaceConfirmation) {
AppAlertDialog(
title = stringResource(id = R.string.space_settings_btn_leave_space),
Expand Down Expand Up @@ -180,6 +204,29 @@ private fun SpaceProfileToolbar() {
}
)
)
if (state.isAdmin && state.spaceMemberCount > 1) {
IconButton(
onClick = { viewModel.onAdminMenuExpanded(true) }
) {
Icon(
imageVector = Icons.Default.MoreVert,
contentDescription = ""
)
}

DropdownMenu(
expanded = state.isMenuExpanded,
onDismissRequest = { viewModel.onAdminMenuExpanded(false) }
) {
DropdownMenuItem(
text = { Text(stringResource(id = R.string.space_setting_change_admin_title)) },
onClick = {
viewModel.onAdminMenuExpanded(false)
viewModel.navigateToChangeAdminScreen(state.spaceInfo)
}
)
}
}
}
)
}
Expand Down Expand Up @@ -222,6 +269,7 @@ private fun SpaceProfileContent() {
enable = true,
isAdmin = state.isAdmin,
currentUser = state.currentUserId!!,
isAdminUser = state.spaceInfo?.space?.admin_id == it.user.id,
onCheckedChange = {
viewModel.onLocationEnabledChanged(it)
},
Expand Down Expand Up @@ -252,6 +300,7 @@ private fun SpaceProfileContent() {
enable = false,
isAdmin = state.isAdmin,
currentUser = state.currentUserId!!,
isAdminUser = state.spaceInfo?.space?.admin_id == it.user.id,
onCheckedChange = {
},
onMemberRemove = {
Expand All @@ -276,7 +325,7 @@ private fun SpaceProfileContent() {
)
}
}
if (state.spaceInfo != null && state.currentUserId == state.spaceInfo?.space?.admin_id) {
if (state.spaceInfo != null && state.spaceMemberCount == 1) {
FooterButton(
title = stringResource(id = R.string.space_settings_btn_delete_space),
onClick = {
Expand All @@ -287,11 +336,15 @@ private fun SpaceProfileContent() {
)
}

if (state.spaceInfo != null && state.currentUserId != state.spaceInfo?.space?.admin_id) {
if (state.spaceInfo != null && state.spaceMemberCount > 1) {
FooterButton(
title = stringResource(id = R.string.space_settings_btn_leave_space),
onClick = {
viewModel.showLeaveSpaceConfirmation(true)
if (state.isAdmin) {
viewModel.showChangeAdminDialog(true)
} else {
viewModel.showLeaveSpaceConfirmation(true)
}
},
showLoader = state.leavingSpace,
icon = Icons.AutoMirrored.Filled.ExitToApp
Expand Down Expand Up @@ -348,6 +401,7 @@ private fun UserItem(
enable: Boolean,
isAdmin: Boolean,
currentUser: String,
isAdminUser: Boolean = false,
onCheckedChange: (Boolean) -> Unit,
onMemberRemove: () -> Unit
) {
Expand All @@ -360,13 +414,28 @@ private fun UserItem(
) {
UserProfile(modifier = Modifier.size(40.dp), user = userInfo.user)
Spacer(modifier = Modifier.width(8.dp))
Text(
text = userInfo.user.fullName,
style = AppTheme.appTypography.subTitle2,
color = AppTheme.colorScheme.textPrimary,
textAlign = TextAlign.Start,

Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Start,
modifier = Modifier.weight(1f)
)
) {
Text(
text = userInfo.user.fullName,
style = AppTheme.appTypography.subTitle2,
color = AppTheme.colorScheme.textPrimary,
textAlign = TextAlign.Start
)

if (isAdminUser) {
Text(
text = stringResource(R.string.space_profile_screen_admin_text),
style = AppTheme.appTypography.subTitle3,
color = AppTheme.colorScheme.textDisabled,
modifier = Modifier.padding(start = 8.dp)
)
}
}

Switch(
checked = isChecked,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.canopas.yourspace.ui.flow.settings.space

import android.net.Uri
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
Expand All @@ -10,6 +11,7 @@ import com.canopas.yourspace.data.utils.AppDispatcher
import com.canopas.yourspace.domain.utils.ConnectivityObserver
import com.canopas.yourspace.ui.navigation.AppDestinations
import com.canopas.yourspace.ui.navigation.AppNavigator
import com.google.gson.Gson
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
Expand Down Expand Up @@ -37,10 +39,9 @@ class SpaceProfileViewModel @Inject constructor(

init {
checkInternetConnection()
fetchSpaceDetail()
}

private fun fetchSpaceDetail() = viewModelScope.launch(appDispatcher.IO) {
fun fetchSpaceDetail() = viewModelScope.launch(appDispatcher.IO) {
_state.emit(_state.value.copy(isLoading = true))
try {
val spaceInfo = spaceRepository.getSpaceInfo(spaceID)
Expand All @@ -54,7 +55,8 @@ class SpaceProfileViewModel @Inject constructor(
currentUserId = authService.currentUser?.id,
isAdmin = spaceInfo?.space?.admin_id == authService.currentUser?.id,
spaceName = spaceInfo?.space?.name,
locationEnabled = locationEnabled
locationEnabled = locationEnabled,
spaceMemberCount = spaceInfo?.members?.size ?: 1
)
)
} catch (e: Exception) {
Expand Down Expand Up @@ -184,18 +186,27 @@ class SpaceProfileViewModel @Inject constructor(
}
}

fun checkInternetConnection() {
viewModelScope.launch(appDispatcher.IO) {
connectivityObserver.observe().collectLatest { status ->
_state.emit(
_state.value.copy(
connectivityStatus = status
)
)
}
fun onChangeAdminClicked() {
val spaceInfo = _state.value.spaceInfo
if (spaceInfo != null) {
navigateToChangeAdminScreen(spaceInfo)
_state.value = _state.value.copy(showChangeAdminDialog = false)
}
}

fun onAdminMenuExpanded(value: Boolean) {
_state.value = _state.value.copy(isMenuExpanded = value)
}

fun showChangeAdminDialog(show: Boolean) {
_state.value = _state.value.copy(showChangeAdminDialog = show)
}

fun navigateToChangeAdminScreen(spaceInfo: SpaceInfo?) {
val spaceDetail = Uri.encode(Gson().toJson(spaceInfo))
navigator.navigateTo(AppDestinations.ChangeAdminScreen.getSpaceDetail(spaceDetail).path)
}

fun showRemoveMemberConfirmationWithId(show: Boolean, memberId: String) {
_state.value = state.value.copy(showRemoveMemberConfirmation = show, memberToRemove = memberId)
}
Expand All @@ -220,6 +231,18 @@ class SpaceProfileViewModel @Inject constructor(
)
}
}

fun checkInternetConnection() {
viewModelScope.launch(appDispatcher.IO) {
connectivityObserver.observe().collectLatest { status ->
_state.emit(
_state.value.copy(
connectivityStatus = status
)
)
}
}
}
}

data class SpaceProfileState(
Expand All @@ -238,5 +261,8 @@ data class SpaceProfileState(
val error: Exception? = null,
val connectivityStatus: ConnectivityObserver.Status = ConnectivityObserver.Status.Available,
val showRemoveMemberConfirmation: Boolean = false,
val memberToRemove: String? = null
val memberToRemove: String? = null,
val spaceMemberCount: Int = 1,
val showChangeAdminDialog: Boolean = false,
var isMenuExpanded: Boolean = false
)
Loading

0 comments on commit cc9b19b

Please sign in to comment.